This is an automated email from the ASF dual-hosted git repository.

zhangchen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new 4510e16845 [improvement](delete) support delete predicate on value 
column for merge-on-write unique table (#21933)
4510e16845 is described below

commit 4510e16845e0d7b98f9243753fbb8b61112ee213
Author: bobhan1 <bh2444151...@outlook.com>
AuthorDate: Wed Aug 16 12:18:05 2023 +0800

    [improvement](delete) support delete predicate on value column for 
merge-on-write unique table (#21933)
    
    Previously, delete statement with conditions on value columns are only 
supported on duplicate tables. After we introduce delete sign mechanism to do 
batch delete, a delete statement with conditions on value columns on unique 
tables will be transformed into the corresponding insert into ..., 
__DELETE_SIGN__ select ... statement. However, for unique table with 
merge-on-write enabled, the overhead of inserting these data can be eliminated. 
So this PR add the ability to allow delete predi [...]
---
 be/src/olap/delete_handler.cpp                     |   7 +-
 be/test/olap/delete_handler_test.cpp               |  14 +-
 .../java/org/apache/doris/analysis/DeleteStmt.java |  17 ++-
 .../java/org/apache/doris/load/DeleteHandler.java  |  18 ++-
 .../data/delete_p0/test_delete_on_value.out        |  94 +++++++++++++
 .../suites/delete_p0/test_delete_on_value.groovy   | 153 +++++++++++++++++++++
 6 files changed, 280 insertions(+), 23 deletions(-)

diff --git a/be/src/olap/delete_handler.cpp b/be/src/olap/delete_handler.cpp
index b7bbfe2908..1df44e0004 100644
--- a/be/src/olap/delete_handler.cpp
+++ b/be/src/olap/delete_handler.cpp
@@ -177,12 +177,9 @@ Status DeleteHandler::check_condition_valid(const 
TabletSchema& schema, const TC
     // the condition column type should not be float or double.
     const TabletColumn& column = schema.column(field_index);
 
-    if ((!column.is_key() && schema.keys_type() != KeysType::DUP_KEYS) ||
-        column.type() == FieldType::OLAP_FIELD_TYPE_DOUBLE ||
+    if (column.type() == FieldType::OLAP_FIELD_TYPE_DOUBLE ||
         column.type() == FieldType::OLAP_FIELD_TYPE_FLOAT) {
-        return Status::Error<DELETE_INVALID_CONDITION>(
-                "field is not key column, or storage model is not duplicate, 
or data type is float "
-                "or double.");
+        return Status::Error<DELETE_INVALID_CONDITION>("data type is float or 
double.");
     }
 
     // Check operator and operands size are matched.
diff --git a/be/test/olap/delete_handler_test.cpp 
b/be/test/olap/delete_handler_test.cpp
index 28308b1048..c2aa5f1efe 100644
--- a/be/test/olap/delete_handler_test.cpp
+++ b/be/test/olap/delete_handler_test.cpp
@@ -406,7 +406,6 @@ TEST_F(TestDeleteConditionHandler, 
StoreCondInvalidParameters) {
     DeletePredicatePB del_pred;
     Status failed_res = 
DeleteHandler::generate_delete_predicate(*tablet->tablet_schema(),
                                                                  conditions, 
&del_pred);
-    ;
     EXPECT_EQ(Status::Error<DELETE_INVALID_PARAMETERS>(""), failed_res);
 }
 
@@ -423,7 +422,6 @@ TEST_F(TestDeleteConditionHandler, 
StoreCondNonexistentColumn) {
     DeletePredicatePB del_pred;
     Status failed_res = 
DeleteHandler::generate_delete_predicate(*tablet->tablet_schema(),
                                                                  conditions, 
&del_pred);
-    ;
     EXPECT_EQ(Status::Error<DELETE_INVALID_CONDITION>(""), failed_res);
 
     // 'v'是value列
@@ -434,10 +432,9 @@ TEST_F(TestDeleteConditionHandler, 
StoreCondNonexistentColumn) {
     condition.condition_values.push_back("5");
     conditions.push_back(condition);
 
-    failed_res = 
DeleteHandler::generate_delete_predicate(*tablet->tablet_schema(), conditions,
-                                                          &del_pred);
-    ;
-    EXPECT_EQ(Status::Error<DELETE_INVALID_CONDITION>(""), failed_res);
+    Status success_res = 
DeleteHandler::generate_delete_predicate(*tablet->tablet_schema(),
+                                                                  conditions, 
&del_pred);
+    EXPECT_EQ(Status::OK(), success_res);
 
     // value column in duplicate model can be deleted;
     conditions.clear();
@@ -447,9 +444,8 @@ TEST_F(TestDeleteConditionHandler, 
StoreCondNonexistentColumn) {
     condition.condition_values.push_back("5");
     conditions.push_back(condition);
 
-    Status success_res = 
DeleteHandler::generate_delete_predicate(*dup_tablet->tablet_schema(),
-                                                                  conditions, 
&del_pred);
-    ;
+    success_res = 
DeleteHandler::generate_delete_predicate(*dup_tablet->tablet_schema(), 
conditions,
+                                                           &del_pred);
     EXPECT_EQ(Status::OK(), success_res);
 }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/DeleteStmt.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/DeleteStmt.java
index ac28d5850e..351fd4f82c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/DeleteStmt.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/DeleteStmt.java
@@ -329,10 +329,19 @@ public class DeleteStmt extends DdlStmt {
             // Due to rounding errors, most floating-point numbers end up 
being slightly imprecise,
             // it also means that numbers expected to be equal often differ 
slightly, so we do not allow compare with
             // floating-point numbers, floating-point number not allowed in 
where clause
-            if (!column.isKey() && table.getKeysType() != KeysType.DUP_KEYS
-                    || column.getDataType().isFloatingPointType()) {
-                throw new AnalysisException("Column[" + columnName + "] is not 
key column or storage model "
-                        + "is not duplicate or column type is float or 
double.");
+            if (column.getDataType().isFloatingPointType()) {
+                throw new AnalysisException("Column[" + columnName + "] type 
is float or double.");
+            }
+            if (!column.isKey()) {
+                if (table.getKeysType() == KeysType.AGG_KEYS) {
+                    throw new AnalysisException("delete predicate on value 
column only supports Unique table with"
+                            + " merge-on-write enabled and Duplicate table, 
but " + "Table[" + table.getName()
+                                    + "] is an Aggregate table.");
+                } else if (table.getKeysType() == KeysType.UNIQUE_KEYS && 
!table.getEnableUniqueKeyMergeOnWrite()) {
+                    throw new AnalysisException("delete predicate on value 
column only supports Unique table with"
+                            + " merge-on-write enabled and Duplicate table, 
but " + "Table[" + table.getName()
+                                    + "] is an Aggregate table.");
+                }
             }
 
             if (condition instanceof BinaryPredicate) {
diff --git a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java 
b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java
index 578b3cd4d0..494fbd5db3 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/load/DeleteHandler.java
@@ -688,11 +688,19 @@ public class DeleteHandler implements Writable {
             // Due to rounding errors, most floating-point numbers end up 
being slightly imprecise,
             // it also means that numbers expected to be equal often differ 
slightly, so we do not allow compare with
             // floating-point numbers, floating-point number not allowed in 
where clause
-            if (!column.isKey() && table.getKeysType() != KeysType.DUP_KEYS
-                    || column.getDataType().isFloatingPointType()) {
-                // 
ErrorReport.reportDdlException(ErrorCode.ERR_NOT_KEY_COLUMN, columnName);
-                throw new DdlException("Column[" + columnName + "] is not key 
column or storage model "
-                        + "is not duplicate or column type is float or 
double.");
+            if (column.getDataType().isFloatingPointType()) {
+                throw new DdlException("Column[" + columnName + "] type is 
float or double.");
+            }
+            if (!column.isKey()) {
+                if (table.getKeysType() == KeysType.AGG_KEYS) {
+                    throw new DdlException("delete predicate on value column 
only supports Unique table with"
+                            + " merge-on-write enabled and Duplicate table, 
but " + "Table[" + table.getName()
+                                    + "] is an Aggregate table.");
+                } else if (table.getKeysType() == KeysType.UNIQUE_KEYS && 
!table.getEnableUniqueKeyMergeOnWrite()) {
+                    throw new DdlException("delete predicate on value column 
only supports Unique table with"
+                            + " merge-on-write enabled and Duplicate table, 
but " + "Table[" + table.getName()
+                                    + "] is an Aggregate table.");
+                }
             }
 
             if (condition instanceof BinaryPredicate) {
diff --git a/regression-test/data/delete_p0/test_delete_on_value.out 
b/regression-test/data/delete_p0/test_delete_on_value.out
new file mode 100644
index 0000000000..2bc8846297
--- /dev/null
+++ b/regression-test/data/delete_p0/test_delete_on_value.out
@@ -0,0 +1,94 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+1      1       1
+2      2       2
+3      3       3
+4      4       4
+5      5       5
+6      6       6
+7      7       7
+8      8       8
+9      9       9
+
+-- !sql --
+1      1       1
+2      2       2
+3      3       3
+5      5       5
+6      6       6
+7      7       7
+8      8       8
+9      9       9
+
+-- !sql --
+1      1       1
+2      2       2
+8      8       8
+9      9       9
+
+-- !sql --
+1      1       1       0
+2      2       2       0
+3      3       3       0
+4      4       4       0
+5      5       5       0
+6      6       6       0
+7      7       7       0
+8      8       8       0
+9      9       9       0
+
+-- !sql --
+1      1       1
+2      2       2
+4      4       4
+5      5       5
+8      8       8
+9      9       9
+
+-- !sql --
+1      1       1
+2      2       2
+4      4       4
+8      8       8
+9      9       9
+
+-- !sql --
+1      1       1       0
+2      2       2       0
+3      3       3       0
+4      4       4       0
+4      4       4       0
+5      5       5       0
+5      5       5       0
+6      6       6       0
+7      7       7       0
+8      8       8       0
+9      9       9       0
+
+-- !sql --
+1      1       10
+
+-- !sql --
+1      1       5       0       3       5
+1      1       10      0       2       10
+
+-- !sql --
+
+-- !sql --
+1      1       5       0       3       5
+1      1       10      0       2       10
+
+-- !sql --
+1      1       10
+
+-- !sql --
+1      1       5       0       3       5
+1      1       10      0       2       10
+
+-- !sql --
+
+-- !sql --
+1      \N      \N      1       4       10
+1      1       5       0       3       5
+1      1       10      0       2       10
+
diff --git a/regression-test/suites/delete_p0/test_delete_on_value.groovy 
b/regression-test/suites/delete_p0/test_delete_on_value.groovy
new file mode 100644
index 0000000000..353e3d64f7
--- /dev/null
+++ b/regression-test/suites/delete_p0/test_delete_on_value.groovy
@@ -0,0 +1,153 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+suite("test_delete_on_value") {
+    sql 'set enable_nereids_planner=false'
+    sql "set experimental_enable_nereids_planner=false;"
+    sql 'set enable_nereids_dml=false'
+
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+    def tableName = "test_delete_on_value"
+    sql """ DROP TABLE IF EXISTS ${tableName} """
+    sql """ CREATE TABLE ${tableName} (
+            `x` BIGINT NOT NULL,
+            `y` BIGINT NULL,
+            `z` BIGINT NULL)
+            ENGINE=OLAP
+            UNIQUE KEY(`x`)
+            COMMENT 'OLAP'
+            DISTRIBUTED BY HASH(`x`) BUCKETS 4
+            PROPERTIES (
+                "replication_num" = "1",
+                "enable_unique_key_merge_on_write" = "true"
+            );"""
+    sql """ insert into ${tableName} 
values(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),(6,6,6),(7,7,7),(8,8,8),(9,9,9); 
"""
+    qt_sql "select * from ${tableName} order by x,y,z;"
+    sql "delete from ${tableName} where y=4;"
+    qt_sql "select * from ${tableName} order by x,y,z;"
+    sql "delete from ${tableName} where z>=3 and z<=7;"
+    qt_sql "select * from ${tableName} order by x,y,z;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select x,y,z,__DORIS_DELETE_SIGN__ from ${tableName} order by 
x,y,z,__DORIS_DELETE_SIGN__;"
+    sql "set skip_delete_predicate=false;"
+    sql "insert into ${tableName} values(4,4,4),(5,5,5);"
+    qt_sql "select * from ${tableName} order by x,y,z;"
+    sql "delete from ${tableName} where y=5;"
+    qt_sql "select * from ${tableName} order by x,y,z;"
+    sql "set skip_storage_engine_merge=true;"
+    sql "set skip_delete_bitmap=true;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select x,y,z,__DORIS_DELETE_SIGN__ from ${tableName} order by 
x,y,z,__DORIS_DELETE_SIGN__;"
+    sql "DROP TABLE IF EXISTS ${tableName};"
+
+
+    def tableName2 = "test_delete_on_value2"
+    sql """ DROP TABLE IF EXISTS ${tableName2} """
+    sql """ CREATE TABLE ${tableName2} (
+            `x` BIGINT NOT NULL,
+            `y` BIGINT REPLACE_IF_NOT_NULL NULL,
+            `z` BIGINT REPLACE_IF_NOT_NULL NULL)
+            ENGINE=OLAP
+            AGGREGATE KEY(`x`)
+            COMMENT 'OLAP'
+            DISTRIBUTED BY HASH(`x`) BUCKETS 4
+            PROPERTIES (
+                "replication_num" = "1"
+            );"""
+    sql """ insert into ${tableName2} values(1,1,1); """
+    test {
+        sql "delete from ${tableName2} where y=4;"
+        exception "delete predicate on value column only supports Unique table 
with merge-on-write enabled and Duplicate table, but 
Table[test_delete_on_value2] is an Aggregate table."
+    }
+
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+    def tableName3 = "test_delete_on_value_with_seq_col"
+    sql """ DROP TABLE IF EXISTS ${tableName3} """
+    sql """ CREATE TABLE ${tableName3} (
+            `x` BIGINT NOT NULL,
+            `y` BIGINT NULL,
+            `z` BIGINT NULL)
+            ENGINE=OLAP
+            UNIQUE KEY(`x`)
+            COMMENT 'OLAP'
+            DISTRIBUTED BY HASH(`x`) BUCKETS 4
+            PROPERTIES (
+                "replication_num" = "1",
+                "enable_unique_key_merge_on_write" = "true",
+                "function_column.sequence_col" = "z"
+            );"""
+    sql "insert into ${tableName3} values(1,1,10);"
+    sql "insert into ${tableName3} values(1,1,5);"
+    qt_sql "select * from ${tableName3} order by x,y,z;"
+    sql "set skip_storage_engine_merge=true;"
+    sql "set skip_delete_bitmap=true;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select * from ${tableName3} order by x,y,z;"
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+    sql "delete from ${tableName3} where z>=10;"
+    qt_sql "select * from ${tableName3} order by x,y,z;"
+    sql "set skip_storage_engine_merge=true;"
+    sql "set skip_delete_bitmap=true;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select * from ${tableName3} order by x,y,z;"
+    sql "DROP TABLE IF EXISTS ${tableName3}"
+
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+    def tableName4 = "test_delete_on_value_with_seq_col_mor"
+    sql """ DROP TABLE IF EXISTS ${tableName4} """
+    sql """ CREATE TABLE ${tableName4} (
+            `x` BIGINT NOT NULL,
+            `y` BIGINT NULL,
+            `z` BIGINT NULL)
+            ENGINE=OLAP
+            UNIQUE KEY(`x`)
+            COMMENT 'OLAP'
+            DISTRIBUTED BY HASH(`x`) BUCKETS 4
+            PROPERTIES (
+                "replication_num" = "1",
+                "function_column.sequence_col" = "z"
+            );"""
+    sql "insert into ${tableName4} values(1,1,10);"
+    sql "insert into ${tableName4} values(1,1,5);"
+    qt_sql "select * from ${tableName4} order by x,y,z;"
+    sql "set skip_storage_engine_merge=true;"
+    sql "set skip_delete_bitmap=true;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select * from ${tableName4} order by x,y,z;"
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+    sql "delete from ${tableName4} where z>=10;"
+    qt_sql "select * from ${tableName4} order by x,y,z;"
+    sql "set skip_storage_engine_merge=true;"
+    sql "set skip_delete_bitmap=true;"
+    sql "set skip_delete_predicate=true;"
+    qt_sql "select * from ${tableName4} order by x,y,z;"
+    sql "DROP TABLE IF EXISTS ${tableName4};"
+
+    sql "set skip_storage_engine_merge=false;"
+    sql "set skip_delete_bitmap=false;"
+    sql "set skip_delete_predicate=false;"
+}


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to