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

dataroaring 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 adeae3c4cc2 [fix](cluster key) some data type is not supported for 
cluster key (#38966)
adeae3c4cc2 is described below

commit adeae3c4cc209fba619e56bd744988becd7957c8
Author: meiyi <myime...@gmail.com>
AuthorDate: Wed Aug 7 23:51:13 2024 +0800

    [fix](cluster key) some data type is not supported for cluster key (#38966)
    
    1. some data type is not supported for key column, it's the same for
    cluster key column
    2. modify some cluster key cases as the mow cases
---
 .../plans/commands/info/ColumnDefinition.java      |  61 +++++----
 .../trees/plans/commands/info/CreateMTMVInfo.java  |   2 +-
 .../trees/plans/commands/info/CreateTableInfo.java |   4 +-
 .../data/unique_with_mow_c_p0/test_delete_sign.out |  69 ++++++++++
 .../test_mow_full_clone_exception.out              |  37 ++++++
 .../test_point_query_cluster_key.groovy            |   2 +-
 .../ssb_unique_sql_zstd/ddl/customer_create.sql    |   1 -
 .../ssb_unique_sql_zstd/ddl/date_create.sql        |   1 -
 .../ssb_unique_sql_zstd/ddl/lineorder_create.sql   |   1 -
 .../ssb_unique_sql_zstd/ddl/part_create.sql        |   1 -
 .../ssb_unique_sql_zstd/ddl/supplier_create.sql    |   1 -
 .../unique_with_mow_c_p0/test_create_table.groovy  |  20 +++
 .../unique_with_mow_c_p0/test_delete_sign.groovy   | 141 +++++++++++++++++++++
 .../test_mow_full_clone_exception.groovy           | 139 ++++++++++++++++++++
 .../test_mow_with_null_sequence.groovy             |   2 -
 .../test_primary_key_simple_case.groovy            |   1 -
 .../unique_with_mow_c_p0/test_schema_change.groovy |   1 -
 .../test_unique_mow_sequence.groovy                |   1 -
 .../ssb_unique_sql_zstd/ddl/customer_create.sql    |   1 -
 .../ssb_unique_sql_zstd/ddl/date_create.sql        |   1 -
 .../ssb_unique_sql_zstd/ddl/lineorder_create.sql   |   1 -
 .../ssb_unique_sql_zstd/ddl/part_create.sql        |   1 -
 .../ssb_unique_sql_zstd/ddl/supplier_create.sql    |   1 -
 23 files changed, 444 insertions(+), 46 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
index 1d1f82f3fd6..0b2694cc311 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java
@@ -199,10 +199,37 @@ public class ColumnDefinition {
         }
     }
 
+    private void checkKeyColumnType(boolean isOlap) {
+        if (isOlap) {
+            if (type.isFloatLikeType()) {
+                throw new AnalysisException("Float or double can not used as a 
key, use decimal instead.");
+            } else if (type.isStringType()) {
+                throw new AnalysisException("String Type should not be used in 
key column[" + name + "]");
+            } else if (type.isArrayType()) {
+                throw new AnalysisException("Array can only be used in the 
non-key column of"
+                        + " the duplicate table at present.");
+            }
+        }
+        if (type.isBitmapType() || type.isHllType() || 
type.isQuantileStateType()) {
+            throw new AnalysisException("Key column can not set complex type:" 
+ name);
+        } else if (type.isJsonType()) {
+            throw new AnalysisException("JsonType type should not be used in 
key column[" + getName() + "].");
+        } else if (type.isVariantType()) {
+            throw new AnalysisException("Variant type should not be used in 
key column[" + getName() + "].");
+        } else if (type.isMapType()) {
+            throw new AnalysisException("Map can only be used in the non-key 
column of"
+                    + " the duplicate table at present.");
+        } else if (type.isStructType()) {
+            throw new AnalysisException("Struct can only be used in the 
non-key column of"
+                    + " the duplicate table at present.");
+        }
+    }
+
     /**
      * validate column definition and analyze
      */
-    public void validate(boolean isOlap, Set<String> keysSet, boolean 
isEnableMergeOnWrite, KeysType keysType) {
+    public void validate(boolean isOlap, Set<String> keysSet, Set<String> 
clusterKeySet, boolean isEnableMergeOnWrite,
+            KeysType keysType) {
         try {
             FeNameFormat.checkColumnName(name);
         } catch (Exception e) {
@@ -234,33 +261,7 @@ public class ColumnDefinition {
                 throw new AnalysisException(
                         String.format("Key column %s can not set aggregation 
type", name));
             }
-            if (isOlap) {
-                if (type.isFloatLikeType()) {
-                    throw new AnalysisException(
-                            "Float or double can not used as a key, use 
decimal instead.");
-                } else if (type.isStringType()) {
-                    throw new AnalysisException(
-                            "String Type should not be used in key column[" + 
name + "]");
-                } else if (type.isArrayType()) {
-                    throw new AnalysisException("Array can only be used in the 
non-key column of"
-                            + " the duplicate table at present.");
-                }
-            }
-            if (type.isBitmapType() || type.isHllType() || 
type.isQuantileStateType()) {
-                throw new AnalysisException("Key column can not set complex 
type:" + name);
-            } else if (type.isJsonType()) {
-                throw new AnalysisException(
-                        "JsonType type should not be used in key column[" + 
getName() + "].");
-            } else if (type.isVariantType()) {
-                throw new AnalysisException(
-                        "Variant type should not be used in key column[" + 
getName() + "].");
-            } else if (type.isMapType()) {
-                throw new AnalysisException("Map can only be used in the 
non-key column of"
-                        + " the duplicate table at present.");
-            } else if (type.isStructType()) {
-                throw new AnalysisException("Struct can only be used in the 
non-key column of"
-                        + " the duplicate table at present.");
-            }
+            checkKeyColumnType(isOlap);
         } else if (aggType == null && isOlap) {
             Preconditions.checkState(keysType != null, "keysType is null");
             if (keysType.equals(KeysType.DUP_KEYS)) {
@@ -274,6 +275,10 @@ public class ColumnDefinition {
             }
         }
 
+        if (clusterKeySet.contains(name)) {
+            checkKeyColumnType(isOlap);
+        }
+
         if (aggType != null) {
             // check if aggregate type is valid
             if (aggType != AggregateType.GENERIC
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
index 6ccc6a08fb9..2e8774f4f8a 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateMTMVInfo.java
@@ -162,7 +162,7 @@ public class CreateMTMVInfo {
         final boolean finalEnableMergeOnWrite = false;
         Set<String> keysSet = Sets.newTreeSet(String.CASE_INSENSITIVE_ORDER);
         keysSet.addAll(keys);
-        columns.forEach(c -> c.validate(true, keysSet, 
finalEnableMergeOnWrite, KeysType.DUP_KEYS));
+        columns.forEach(c -> c.validate(true, keysSet, Sets.newHashSet(), 
finalEnableMergeOnWrite, KeysType.DUP_KEYS));
 
         if (distribution == null) {
             throw new AnalysisException("Create async materialized view should 
contain distribution desc");
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
index 4bbae8d4e78..3bc8bb91d62 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/CreateTableInfo.java
@@ -558,7 +558,9 @@ public class CreateTableInfo {
         final boolean finalEnableMergeOnWrite = isEnableMergeOnWrite;
         Set<String> keysSet = Sets.newTreeSet(String.CASE_INSENSITIVE_ORDER);
         keysSet.addAll(keys);
-        columns.forEach(c -> c.validate(engineName.equals(ENGINE_OLAP), 
keysSet, finalEnableMergeOnWrite,
+        Set<String> clusterKeySet = 
Sets.newTreeSet(String.CASE_INSENSITIVE_ORDER);
+        clusterKeySet.addAll(clusterKeysColumnNames);
+        columns.forEach(c -> c.validate(engineName.equals(ENGINE_OLAP), 
keysSet, clusterKeySet, finalEnableMergeOnWrite,
                 keysType));
 
         // validate index
diff --git a/regression-test/data/unique_with_mow_c_p0/test_delete_sign.out 
b/regression-test/data/unique_with_mow_c_p0/test_delete_sign.out
new file mode 100644
index 00000000000..60bf812800b
--- /dev/null
+++ b/regression-test/data/unique_with_mow_c_p0/test_delete_sign.out
@@ -0,0 +1,69 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !select_0 --
+true   1       10      {"c":"c"}
+
+-- !select_1 --
+
+-- !select_2 --
+
+-- !select_3 --
+true   1       10      {"c":"c"}
+
+-- !select_4 --
+
+-- !select_5 --
+
+-- !select_6 --
+
+-- !select_7 --
+true   1       10      {"c":"c"}
+
+-- !select_8 --
+true   1       10      {"c":"c"}
+
+-- !select_9 --
+true   1       30      {"b":"b"}
+
+-- !select_10 --
+true   1       10      {"c":"c"}
+
+-- !select_11 --
+true   1       10      {"c":"c"}
+
+-- !select_12 --
+true   1       30      {"b":"b"}
+
+-- !select_0 --
+true   1       10      {"c":"c"}
+
+-- !select_1 --
+
+-- !select_2 --
+
+-- !select_3 --
+true   1       10      {"c":"c"}
+
+-- !select_4 --
+
+-- !select_5 --
+
+-- !select_6 --
+
+-- !select_7 --
+true   1       10      {"c":"c"}
+
+-- !select_8 --
+true   1       10      {"c":"c"}
+
+-- !select_9 --
+true   1       30      {"b":"b"}
+
+-- !select_10 --
+true   1       10      {"c":"c"}
+
+-- !select_11 --
+true   1       10      {"c":"c"}
+
+-- !select_12 --
+true   1       30      {"b":"b"}
+
diff --git 
a/regression-test/data/unique_with_mow_c_p0/test_mow_full_clone_exception.out 
b/regression-test/data/unique_with_mow_c_p0/test_mow_full_clone_exception.out
new file mode 100644
index 00000000000..f11c60b41e1
--- /dev/null
+++ 
b/regression-test/data/unique_with_mow_c_p0/test_mow_full_clone_exception.out
@@ -0,0 +1,37 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+1      10
+2      200
+3      30
+4      400
+5      500
+6      600
+7      7
+8      8
+9      9
+10     10
+
+-- !sql --
+1      10
+2      200
+3      30
+4      400
+5      500
+6      600
+7      7
+8      8
+9      9
+10     10
+
+-- !sql --
+1      10
+2      200
+3      30
+4      400
+5      500
+6      600
+7      7
+8      8
+9      9
+10     10
+
diff --git 
a/regression-test/suites/point_query_p0/test_point_query_cluster_key.groovy 
b/regression-test/suites/point_query_p0/test_point_query_cluster_key.groovy
index 0ce1ddaddec..7497fc8b5e4 100644
--- a/regression-test/suites/point_query_p0/test_point_query_cluster_key.groovy
+++ b/regression-test/suites/point_query_p0/test_point_query_cluster_key.groovy
@@ -239,7 +239,7 @@ suite("test_point_query_cluster_key") {
                 sql """CREATE TABLE ${tableName} (
                         `customer_key` bigint(20) NULL,
                         `customer_btm_value_0` text NULL,
-                        `customer_btm_value_1` text NULL,
+                        `customer_btm_value_1` VARCHAR(1000) NULL,
                         `customer_btm_value_2` text NULL
                     ) ENGINE=OLAP
                     UNIQUE KEY(`customer_key`)
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/customer_create.sql
 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/customer_create.sql
index 3640400704c..1d593fb15ba 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/customer_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/customer_create.sql
@@ -14,6 +14,5 @@ DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/date_create.sql
 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/date_create.sql
index 6a065537829..e46caac95dc 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/date_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/date_create.sql
@@ -23,6 +23,5 @@ DISTRIBUTED BY HASH(`d_datekey`) BUCKETS 1
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/lineorder_create.sql
 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/lineorder_create.sql
index d56c8aee33c..d3015f954c9 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/lineorder_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/lineorder_create.sql
@@ -31,6 +31,5 @@ DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 48
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/part_create.sql
 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/part_create.sql
index 34a1555fa52..5ec4981cf10 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/part_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/part_create.sql
@@ -15,6 +15,5 @@ DISTRIBUTED BY HASH(`p_partkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/supplier_create.sql
 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/supplier_create.sql
index 662aca9847d..266a2119eb6 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/supplier_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p0/ssb_unique_sql_zstd/ddl/supplier_create.sql
@@ -13,6 +13,5 @@ DISTRIBUTED BY HASH(`s_suppkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_create_table.groovy 
b/regression-test/suites/unique_with_mow_c_p0/test_create_table.groovy
index c7a530b9143..8cd7cb6d198 100644
--- a/regression-test/suites/unique_with_mow_c_p0/test_create_table.groovy
+++ b/regression-test/suites/unique_with_mow_c_p0/test_create_table.groovy
@@ -227,4 +227,24 @@ suite("test_create_table") {
         """
         exception "Cluster keys only support unique keys table"
     }
+
+    // cluster key contains complex type
+    test {
+        sql """
+            CREATE TABLE `$tableName` (
+                `c_custkey` int(11) NOT NULL COMMENT "",
+                `c_name` varchar(26) NOT NULL COMMENT "",
+                `c_address` varchar(41) NOT NULL COMMENT "",
+                `c_city` variant NOT NULL COMMENT ""
+            )
+            UNIQUE KEY (`c_custkey`)
+            CLUSTER BY (`c_name`, `c_city`, `c_address`)
+            DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 1
+            PROPERTIES (
+                "replication_num" = "1",
+                "enable_unique_key_merge_on_write" = "true"
+            );
+        """
+        exception "Variant type should not be used in key column"
+    }
 }
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_delete_sign.groovy 
b/regression-test/suites/unique_with_mow_c_p0/test_delete_sign.groovy
new file mode 100644
index 00000000000..8192aa2de1d
--- /dev/null
+++ b/regression-test/suites/unique_with_mow_c_p0/test_delete_sign.groovy
@@ -0,0 +1,141 @@
+
+// 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_sign", "p0") {
+
+    String db = context.config.getDbNameByFile(context.file)
+    sql "select 1;" // to create database
+
+    for (def use_row_store : [false, true]) {
+        logger.info("current params: use_row_store: ${use_row_store}")
+
+        connect(user = context.config.jdbcUser, password = 
context.config.jdbcPassword, url = context.config.jdbcUrl) {
+            sql "use ${db};"
+            def tableName = "test_delete_sign"
+            // test delete sigin X sequence column
+            sql """ DROP TABLE IF EXISTS ${tableName} """
+            sql """ CREATE TABLE ${tableName} (
+                        col1 BOOLEAN,
+                        col2 INT,
+                        col3 INT,
+                        col4 variant
+                    ) unique key(col1, col2)
+                    CLUSTER BY (`col3`, `col2`) 
+                    distributed by hash(col1) buckets 1
+                    properties(
+                        "replication_num" = "1",
+                        "function_column.sequence_col" = 'col3',
+                        "store_row_column" = "${use_row_store}"
+                    ); """
+
+            sql """insert into ${tableName} values(true, 1, 1, '{"a":"a"}');"""
+            sql """insert into ${tableName} values(true, 1, 10, 
'{"c":"c"}');"""
+            sql """insert into ${tableName} values(true, 1, 2, '{"b":"b"}');"""
+            qt_select_0 "select * from ${tableName};"
+            sql """insert into ${tableName} 
(col1,col2,col3,col4,__DORIS_DELETE_SIGN__)values(true, 1, 10, 
'{"c":"c"}',1);"""
+            qt_select_1 "select * from ${tableName};"
+            sql """insert into ${tableName} values(true, 1, 3, '{"c":"c"}');"""
+            qt_select_2 "select * from ${tableName};"
+
+            // test delete sigin X update
+            sql """ DROP TABLE IF EXISTS ${tableName} """
+            sql """ CREATE TABLE ${tableName} (
+                        col1 BOOLEAN,
+                        col2 INT,
+                        col3 INT,
+                        col4 variant
+                    ) unique key(col1, col2) 
+                    CLUSTER BY (`col2`, `col3`) 
+                    distributed by hash(col1) buckets 1
+                    properties(
+                        "replication_num" = "1",
+                        "function_column.sequence_col" = 'col3',
+                        "store_row_column" = "${use_row_store}"
+                    ); """
+
+            sql """insert into ${tableName} values(true, 1, 1, '{"a":"a"}');"""
+            sql """insert into ${tableName} values(true, 1, 10, 
'{"c":"c"}');"""
+            sql """insert into ${tableName} values(true, 1, 2, '{"b":"b"}');"""
+            qt_select_3 "select * from ${tableName};"
+            sql """insert into ${tableName} 
(col1,col2,col3,col4,__DORIS_DELETE_SIGN__)values(true, 1, 10, 
'{"c":"c"}',1);"""
+            qt_select_4 "select * from ${tableName};"
+            sql """insert into ${tableName} values(true, 1, 3, '{"c":"c"}');"""
+            qt_select_5 "select * from ${tableName};"
+            //sql """update ${tableName} set __DORIS_DELETE_SIGN__=0 where 
col3=10;"""
+            qt_select_6 "select * from ${tableName};"
+            sql """insert into ${tableName} values(true, 1, 5, '{"c":"c"}');"""
+
+            // test delete sigin X default value
+            sql """ DROP TABLE IF EXISTS ${tableName} """
+            sql """ CREATE TABLE ${tableName} (
+                        col1 BOOLEAN,
+                        col2 INT,
+                        col3 INT,
+                        col4 variant NULL
+                    ) unique key(col1, col2)
+                    CLUSTER BY (`col1`, `col3`)  
+                    distributed by hash(col1) buckets 1
+                    properties(
+                        "replication_num" = "1",
+                        "function_column.sequence_col" = 'col3',
+                        "store_row_column" = "${use_row_store}"
+                    ); """
+
+            sql """insert into ${tableName} values(true, 1, 1, '{"a":"a"}');"""
+            sql """insert into ${tableName} values(true, 1, 10, 
'{"c":"c"}');"""
+            sql """insert into ${tableName} values(true, 1, 2, '{"b":"b"}');"""
+            qt_select_7 "select * from ${tableName};"
+            sql """insert into ${tableName} (col1,col2,col3)values(true, 1, 
1);"""
+            qt_select_8 "select * from ${tableName};"
+            sql """insert into ${tableName} values(true, 1, 30, 
'{"b":"b"}');"""
+            qt_select_9 "select * from ${tableName};"
+
+            // test delete sigin X txn
+            sql """ DROP TABLE IF EXISTS ${tableName} """
+            sql """ CREATE TABLE ${tableName} (
+                        col1 BOOLEAN,
+                        col2 INT,
+                        col3 INT,
+                        col4 variant default NULL,
+                        INDEX idx_col3 (`col3`) USING INVERTED,
+                    ) unique key(col1, col2)
+                    CLUSTER BY (`col3`, `col1`, `col2`)  
+                    distributed by hash(col1) buckets 1
+                    properties(
+                        "replication_num" = "1",
+                        "function_column.sequence_col" = 'col3',
+                        "store_row_column" = "${use_row_store}"
+                    ); """
+
+            sql """begin"""
+            sql """insert into ${tableName} values(true, 1, 1, '{"a":"a"}');"""
+            sql """insert into ${tableName} values(true, 1, 10, 
'{"c":"c"}');"""
+            sql """insert into ${tableName} values(true, 1, 2, '{"b":"b"}');"""
+            sql """commit"""
+            qt_select_10 "select * from ${tableName};"
+            sql """begin"""
+            sql """insert into ${tableName} (col1,col2,col3)values(true, 1, 
1);"""
+            sql """commit"""
+            qt_select_11 "select * from ${tableName};"
+            sql """begin"""
+            sql """insert into ${tableName} values(true, 1, 30, 
'{"b":"b"}');"""
+            sql """commit"""
+            qt_select_12 "select * from ${tableName};"
+        }
+    }
+}
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_mow_full_clone_exception.groovy
 
b/regression-test/suites/unique_with_mow_c_p0/test_mow_full_clone_exception.groovy
new file mode 100644
index 00000000000..516cff9d4f5
--- /dev/null
+++ 
b/regression-test/suites/unique_with_mow_c_p0/test_mow_full_clone_exception.groovy
@@ -0,0 +1,139 @@
+// 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.
+
+import org.apache.doris.regression.suite.ClusterOptions
+import org.apache.doris.regression.util.NodeType
+
+// This case can reproduce an clone issue which may produce duplicate keys in 
mow table
+// the bug would be triggered in the following condition:
+// 1. replica 0 miss version
+// 2. replica 0 try to do full clone from other replicas
+// 3. the full clone failed and the delete bitmap is overrided incorrectly
+// 4. replica 0 try to do incremental clone again and this time the clone 
succeed
+// 5. incremental clone can't fix the delete bitmap overrided by previous 
failed full clone
+// 6. duplicate key occurred
+//
+// the bug is fixed in #37001
+
+suite('test_full_clone_exception') {
+    def options = new ClusterOptions()
+    options.feConfigs += [
+        'disable_tablet_scheduler=true',
+        'tablet_checker_interval_ms=500',
+        'schedule_batch_size=1000',
+        'schedule_slot_num_per_hdd_path=1000',
+    ]
+    options.beConfigs += [
+        'disable_auto_compaction=true',
+        'report_tablet_interval_seconds=1',
+        'enable_java_support=false',
+    ]
+
+    options.enableDebugPoints()
+    options.cloudMode = false
+    docker(options) {
+        def txnFailureInject = 'TxnManager.prepare_txn.random_failed'
+        def fullCloneInject = 
'SnapshotManager.create_snapshot_files.allow_inc_clone'
+        def reviseTabletMetaInject='Tablet.revise_tablet_meta_fail'
+        def be1 = sql_return_maparray('show backends').get(0)
+        def be2 = sql_return_maparray('show backends').get(1)
+        def be3 = sql_return_maparray('show backends').get(2)
+
+        def addInjectToBE = { beIdx, injectName, param ->
+            def be = sql_return_maparray('show backends').get(beIdx)
+            GetDebugPoint().enableDebugPoint(be.Host, be.HttpPort as int, 
NodeType.BE, injectName, param)
+        }
+
+        def deleteInjectOnBE = { beIdx, injectName ->
+            def be = sql_return_maparray('show backends').get(beIdx)
+            GetDebugPoint().disableDebugPoint(be.Host, be.HttpPort as int, 
NodeType.BE, injectName)
+        }
+
+        sql """
+                CREATE TABLE IF NOT EXISTS t (
+                    k int,
+                    v int
+                )
+                UNIQUE KEY(k)
+                CLUSTER BY(v)
+                DISTRIBUTED BY HASH(k) BUCKETS 1 properties(
+                    "enable_unique_key_merge_on_write" = "true"
+                );
+            """
+
+        sql 'INSERT INTO t VALUES(1,1),(2,2),(3,3),(4,4)'
+        sql 'INSERT INTO t VALUES(1,10),(2,20),(3,30),(4,40)'
+
+        // inject txn failure, make replica 0 miss version
+        addInjectToBE(0, txnFailureInject, [percent:1.0])
+
+        sql 'INSERT INTO t VALUES(2,200),(4,400),(5,500),(6,600)'
+        sql 'INSERT INTO t VALUES(7,7)'
+        sql 'INSERT INTO t VALUES(8,8)'
+        sql 'INSERT INTO t VALUES(9,9)'
+
+        deleteInjectOnBE(0, txnFailureInject)
+
+        sql 'INSERT INTO t VALUES(10,10)'
+
+        sleep 5000
+
+        // check replica 0 miss version
+        def replica1 = sql_return_maparray('show tablets from t').find { 
it.BackendId.toLong().equals(be1.BackendId.toLong()) }
+        assertNotNull(replica1)
+        assertEquals(3, replica1.VersionCount.toInteger())
+        assertEquals(3, replica1.Version.toInteger())
+        assertEquals(8, replica1.LstFailedVersion.toInteger())
+
+        def tabletId = replica1.TabletId
+        // inject failure on replica 0, which can't clone succeed
+        addInjectToBE(0, reviseTabletMetaInject, [tablet_id:tabletId])
+        // inject on replica 1, force replica 0 full clone from them
+        addInjectToBE(1, fullCloneInject, [tablet_id:tabletId, 
is_full_clone:true])
+        addInjectToBE(2, fullCloneInject, [tablet_id:tabletId, 
is_full_clone:true])
+
+        // start clone
+        setFeConfig('disable_tablet_scheduler', false)
+
+        sleep 10000
+
+        // now, there's lots of full clone failures, remove all debug points, 
make
+        // replica 0 can do normal incremental clone from other replicas
+        deleteInjectOnBE(0, reviseTabletMetaInject)
+        deleteInjectOnBE(1, fullCloneInject)
+        deleteInjectOnBE(2, fullCloneInject)
+
+        sleep 10000
+
+        // make sure the clone succeed
+        replica1 = sql_return_maparray('show tablets from t').find { 
it.BackendId.toLong().equals(be1.BackendId.toLong()) }
+        assertNotNull(replica1)
+        assertEquals(8, replica1.VersionCount.toInteger())
+        assertEquals(8, replica1.Version.toInteger())
+        assertEquals(-1, replica1.LstFailedVersion.toInteger())
+
+        // three replica's content should be consistent
+        sql 'set use_fix_replica=0'
+        qt_sql 'select * from t order by k'
+
+        sql 'set use_fix_replica=1'
+        qt_sql 'select * from t order by k'
+
+        sql 'set use_fix_replica=2'
+        qt_sql 'select * from t order by k'
+    }
+}
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_mow_with_null_sequence.groovy
 
b/regression-test/suites/unique_with_mow_c_p0/test_mow_with_null_sequence.groovy
index bf3ce215a90..3e6f7cce599 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/test_mow_with_null_sequence.groovy
+++ 
b/regression-test/suites/unique_with_mow_c_p0/test_mow_with_null_sequence.groovy
@@ -31,7 +31,6 @@ suite("test_mow_with_null_sequence") {
             PROPERTIES (
                     "function_column.sequence_col" = 'c_date',
                     "replication_num" = "1",
-                    "disable_auto_compaction" = "true",
                     "enable_unique_key_merge_on_write" = "true"
              );
         """
@@ -65,7 +64,6 @@ suite("test_mow_with_null_sequence") {
             PROPERTIES (
                     "function_column.sequence_col" = 'c_int',
                     "replication_num" = "1",
-                    "disable_auto_compaction" = "true",
                     "enable_unique_key_merge_on_write" = "true"
              );
         """
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_primary_key_simple_case.groovy
 
b/regression-test/suites/unique_with_mow_c_p0/test_primary_key_simple_case.groovy
index 94b3051cba3..8e5d683cea5 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/test_primary_key_simple_case.groovy
+++ 
b/regression-test/suites/unique_with_mow_c_p0/test_primary_key_simple_case.groovy
@@ -41,7 +41,6 @@ suite("test_primary_key_simple_case") {
         CLUSTER BY(`user_id`, `age`, `cost`, `sex`)
         DISTRIBUTED BY HASH(`user_id`)
         PROPERTIES ( "replication_num" = "1",
-                     "disable_auto_compaction" = "true",
                      "enable_unique_key_merge_on_write" = "true"
         );
     """
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_schema_change.groovy 
b/regression-test/suites/unique_with_mow_c_p0/test_schema_change.groovy
index 26fa94ab4e5..9abee82f7c0 100644
--- a/regression-test/suites/unique_with_mow_c_p0/test_schema_change.groovy
+++ b/regression-test/suites/unique_with_mow_c_p0/test_schema_change.groovy
@@ -50,7 +50,6 @@ suite("test_schema_change") {
         CLUSTER BY(`cost`, `comment`)
         DISTRIBUTED BY HASH(`user_id`)
         PROPERTIES ( "replication_num" = "1",
-                     "disable_auto_compaction" = "true",
                      "enable_unique_key_merge_on_write" = "true"
         );
     """
diff --git 
a/regression-test/suites/unique_with_mow_c_p0/test_unique_mow_sequence.groovy 
b/regression-test/suites/unique_with_mow_c_p0/test_unique_mow_sequence.groovy
index c3ded30c048..d9e7c53312f 100644
--- 
a/regression-test/suites/unique_with_mow_c_p0/test_unique_mow_sequence.groovy
+++ 
b/regression-test/suites/unique_with_mow_c_p0/test_unique_mow_sequence.groovy
@@ -36,7 +36,6 @@ suite("test_unique_mow_sequence") {
                     "function_column.sequence_type" = 'int',
                     "compression"="zstd",
                     "replication_num" = "1",
-                    "disable_auto_compaction" = "true",
                     "enable_unique_key_merge_on_write" = "true"
              );
         """
diff --git 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/customer_create.sql
 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/customer_create.sql
index 8240bd709ce..9e201b44646 100644
--- 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/customer_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/customer_create.sql
@@ -14,6 +14,5 @@ DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/date_create.sql
 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/date_create.sql
index 1ff610fd690..3d12170cf99 100644
--- 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/date_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/date_create.sql
@@ -23,6 +23,5 @@ DISTRIBUTED BY HASH(`d_datekey`) BUCKETS 1
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/lineorder_create.sql
 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/lineorder_create.sql
index 829b8d65bd4..b9481142be1 100644
--- 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/lineorder_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/lineorder_create.sql
@@ -31,6 +31,5 @@ DISTRIBUTED BY HASH(`lo_orderkey`) BUCKETS 48
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/part_create.sql
 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/part_create.sql
index 9dda02c7b72..3975ff83f09 100644
--- 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/part_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/part_create.sql
@@ -15,6 +15,5 @@ DISTRIBUTED BY HASH(`p_partkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );
diff --git 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/supplier_create.sql
 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/supplier_create.sql
index b827e9b6db4..7e101c5667f 100644
--- 
a/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/supplier_create.sql
+++ 
b/regression-test/suites/unique_with_mow_c_p2/ssb_unique_sql_zstd/ddl/supplier_create.sql
@@ -13,6 +13,5 @@ DISTRIBUTED BY HASH(`s_suppkey`) BUCKETS 10
 PROPERTIES (
 "compression"="zstd",
 "replication_num" = "1",
-"disable_auto_compaction" = "true",
 "enable_unique_key_merge_on_write" = "true"
 );


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


Reply via email to