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

zhangstar333 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 8a8a3adb2fb [Enhancement](partition) Support use Auto and Dynamic 
partition at the same time (#39580)
8a8a3adb2fb is described below

commit 8a8a3adb2fbad944a49bf19df05e252736ef0f3d
Author: zclllhhjj <zhaochan...@selectdb.com>
AuthorDate: Tue Aug 27 16:43:01 2024 +0800

    [Enhancement](partition) Support use Auto and Dynamic partition at the same 
time (#39580)
    
    ## Proposed changes
    before we forbid it in https://github.com/apache/doris/pull/33736, now
    it's time to let it go.
    
    now we support:
    ```sql
    mysql> create table auto_dynamic(
        ->             k0 datetime(6) NOT NULL
        ->         )
        ->         auto partition by range (date_trunc(k0, 'year'))
        ->         (
        ->         )
        ->         DISTRIBUTED BY HASH(`k0`) BUCKETS 2
        ->         properties(
        ->             "dynamic_partition.enable" = "true",
        ->             "dynamic_partition.prefix" = "p",
        ->             "dynamic_partition.start" = "-50",
        ->             "dynamic_partition.end" = "0",
        ->             "dynamic_partition.time_unit" = "year",
        ->             "replication_num" = "1"
        ->         );
    Query OK, 0 rows affected (0.12 sec)
    ```
    
    with this, the users could manage their data more flexible
    
    we will refactor the docs of it, and the only recommended way it set end
    to zero.
---
 .../doris/common/util/DynamicPartitionUtil.java    |  41 ++++-
 .../apache/doris/datasource/InternalCatalog.java   |   6 +-
 .../test_auto_partition_behavior.out               |  10 +-
 .../test_auto_partition_behavior.groovy            | 195 +++++++++------------
 .../test_dynamic_partition.groovy                  |  31 ++--
 5 files changed, 143 insertions(+), 140 deletions(-)

diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java
 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java
index d3c50be141f..7fc13392cef 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/common/util/DynamicPartitionUtil.java
@@ -17,6 +17,9 @@
 
 package org.apache.doris.common.util;
 
+import org.apache.doris.analysis.Expr;
+import org.apache.doris.analysis.FunctionCallExpr;
+import org.apache.doris.analysis.LiteralExpr;
 import org.apache.doris.analysis.TimestampArithmeticExpr.TimeUnit;
 import org.apache.doris.catalog.Column;
 import org.apache.doris.catalog.Database;
@@ -128,13 +131,14 @@ public class DynamicPartitionUtil {
         return DynamicPartitionProperty.MIN_START_OFFSET;
     }
 
-    private static int checkEnd(String end) throws DdlException {
+    private static int checkEnd(String end, boolean enableAutoPartition) 
throws DdlException {
         if (Strings.isNullOrEmpty(end)) {
             
ErrorReport.reportDdlException(ErrorCode.ERROR_DYNAMIC_PARTITION_END_EMPTY);
         }
         try {
             int endInt = Integer.parseInt(end);
-            if (endInt <= 0) {
+            // with auto partition sometime we dont like to create future 
partition by dynamic partition.
+            if (endInt < 0 || endInt == 0 && !enableAutoPartition) {
                 
ErrorReport.reportDdlException(ErrorCode.ERROR_DYNAMIC_PARTITION_END_ZERO, end);
             }
             return endInt;
@@ -521,6 +525,25 @@ public class DynamicPartitionUtil {
         }
     }
 
+    public static void partitionIntervalCompatible(String dynamicUnit, 
ArrayList<Expr> autoExprs)
+            throws AnalysisException {
+        if (autoExprs == null) {
+            return;
+        }
+        for (Expr autoExpr : autoExprs) {
+            Expr func = (FunctionCallExpr) autoExpr;
+            for (Expr child : func.getChildren()) {
+                if (child instanceof LiteralExpr) {
+                    String autoUnit = ((LiteralExpr) child).getStringValue();
+                    if (!dynamicUnit.equalsIgnoreCase(autoUnit)) {
+                        throw new AnalysisException("If support auto partition 
and dynamic partition at same time, "
+                                + "they must have the same interval unit.");
+                    }
+                }
+            }
+        }
+    }
+
     // Analyze all properties to check their validation
     public static Map<String, String> analyzeDynamicPartition(Map<String, 
String> properties,
             OlapTable olapTable, Database db) throws UserException {
@@ -529,6 +552,12 @@ public class DynamicPartitionUtil {
         if (properties.containsKey(DynamicPartitionProperty.TIME_UNIT)) {
             String timeUnitValue = 
properties.get(DynamicPartitionProperty.TIME_UNIT);
             checkTimeUnit(timeUnitValue, olapTable.getPartitionInfo());
+
+            // if both enabled, must use same interval.
+            if (olapTable.getPartitionInfo().enableAutomaticPartition()) {
+                partitionIntervalCompatible(timeUnitValue, 
olapTable.getPartitionInfo().getPartitionExprs());
+            }
+
             properties.remove(DynamicPartitionProperty.TIME_UNIT);
             analyzedProperties.put(DynamicPartitionProperty.TIME_UNIT, 
timeUnitValue);
         }
@@ -553,11 +582,7 @@ public class DynamicPartitionUtil {
             analyzedProperties.put(DynamicPartitionProperty.ENABLE, 
enableValue);
         }
 
-        if 
(Boolean.parseBoolean(analyzedProperties.getOrDefault(DynamicPartitionProperty.ENABLE,
 "true"))
-                && olapTable.getPartitionInfo().enableAutomaticPartition()) {
-            throw new AnalysisException(
-                    "Can't use Dynamic Partition and Auto Partition at the 
same time");
-        }
+        boolean enableAutoPartition = 
olapTable.getPartitionInfo().enableAutomaticPartition();
 
         // If dynamic property "start" is not specified, use Integer.MIN_VALUE 
as default
         int start = DynamicPartitionProperty.MIN_START_OFFSET;
@@ -572,7 +597,7 @@ public class DynamicPartitionUtil {
         boolean hasEnd = false;
         if (properties.containsKey(DynamicPartitionProperty.END)) {
             String endValue = properties.get(DynamicPartitionProperty.END);
-            end = checkEnd(endValue);
+            end = checkEnd(endValue, enableAutoPartition);
             properties.remove(DynamicPartitionProperty.END);
             analyzedProperties.put(DynamicPartitionProperty.END, endValue);
             hasEnd = true;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
index 3b28f01f2b4..2e1729d8bb7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/datasource/InternalCatalog.java
@@ -3073,8 +3073,10 @@ public class InternalCatalog implements 
CatalogIf<Database> {
                             .getDynamicPartitionProperty();
                     if (dynamicProperty.isExist() && 
dynamicProperty.getEnable()
                             && partitionDesc.isAutoCreatePartitions()) {
-                        throw new AnalysisException(
-                                "Can't use Dynamic Partition and Auto 
Partition at the same time");
+                        String dynamicUnit = dynamicProperty.getTimeUnit();
+                        ArrayList<Expr> autoExprs = 
partitionDesc.getPartitionExprs();
+                        // check same interval. fail will leading to 
AnalysisException
+                        
DynamicPartitionUtil.partitionIntervalCompatible(dynamicUnit, autoExprs);
                     }
                 } catch (AnalysisException e) {
                     throw new DdlException(e.getMessage());
diff --git 
a/regression-test/data/partition_p0/auto_partition/test_auto_partition_behavior.out
 
b/regression-test/data/partition_p0/auto_partition/test_auto_partition_behavior.out
index 40ae8a97a89..27d77c500f2 100644
--- 
a/regression-test/data/partition_p0/auto_partition/test_auto_partition_behavior.out
+++ 
b/regression-test/data/partition_p0/auto_partition/test_auto_partition_behavior.out
@@ -102,10 +102,7 @@ xxX        3
 2013-12-12T00:00       2013-12-12T00:00
 2020-12-12T00:00       2020-12-12T12:12:12.123456
 
--- !sql_overwrite1 --
-Yyy
-
--- !sql_overwrite2 --
+-- !sql_overwrite --
 Xxx
 
 -- !sql_non_order1 --
@@ -117,3 +114,8 @@ Xxx
 -- !sql_non_order3 --
 3      2013-12-12T00:00
 
+-- !sql_dynamic_auto --
+2024-01-01T00:00
+2900-01-01T00:00
+3000-01-01T00:00
+
diff --git 
a/regression-test/suites/partition_p0/auto_partition/test_auto_partition_behavior.groovy
 
b/regression-test/suites/partition_p0/auto_partition/test_auto_partition_behavior.groovy
index 4c3f184e332..fb8be0b5510 100644
--- 
a/regression-test/suites/partition_p0/auto_partition/test_auto_partition_behavior.groovy
+++ 
b/regression-test/suites/partition_p0/auto_partition/test_auto_partition_behavior.groovy
@@ -16,6 +16,9 @@
 // under the License.
 
 suite("test_auto_partition_behavior") {
+    sql "set experimental_enable_nereids_planner=true;"
+    sql "set enable_fallback_to_original_planner=false;"
+
     /// unique key table
     sql "drop table if exists unique_table"
     sql """
@@ -165,18 +168,6 @@ suite("test_auto_partition_behavior") {
         );
         """
     sql """ insert into rewrite values ("Xxx"); """
-    // legacy planner
-    sql " set experimental_enable_nereids_planner=false "
-    try {
-        sql """ insert overwrite table rewrite partition(p1) values ("XXX") """
-        fail()
-    } catch (Exception e) {
-        assertTrue(e.getMessage().contains("Insert has filtered data in strict 
mode"))
-    }
-    sql """ insert overwrite table rewrite partition(p1) values ("Yyy") """
-    qt_sql_overwrite1 """ select * from rewrite """ // Yyy
-    // nereids planner
-    sql " set experimental_enable_nereids_planner=true "
     try {
         sql """ insert overwrite table rewrite partition(p1) values ("") """
         fail()
@@ -184,7 +175,7 @@ suite("test_auto_partition_behavior") {
         assertTrue(e.getMessage().contains("Insert has filtered data in strict 
mode"))
     }
     sql """ insert overwrite table rewrite partition(p1) values ("Xxx") """
-    qt_sql_overwrite2 """ select * from rewrite """ // Xxx
+    qt_sql_overwrite """ select * from rewrite """ // Xxx
 
     sql " drop table if exists non_order; "
     sql """
@@ -209,22 +200,6 @@ suite("test_auto_partition_behavior") {
     qt_sql_non_order3 """ select * from non_order where k1 = '2013-12-12'; """
 
     // range partition can't auto create null partition
-    sql " set experimental_enable_nereids_planner=true "
-    sql "drop table if exists invalid_null_range"
-    test {
-        sql """
-            create table invalid_null_range(
-                k0 datetime(6) null
-            )
-            auto partition by range (date_trunc(k0, 'hour'))
-            (
-            )
-            DISTRIBUTED BY HASH(`k0`) BUCKETS 2
-            properties("replication_num" = "1");
-        """
-        exception "AUTO RANGE PARTITION doesn't support NULL column"
-    }
-    sql " set experimental_enable_nereids_planner=false "
     sql "drop table if exists invalid_null_range"
     test {
         sql """
@@ -240,18 +215,11 @@ suite("test_auto_partition_behavior") {
         exception "AUTO RANGE PARTITION doesn't support NULL column"
     }
 
-    sql "drop table if exists test_dynamic"
-    sql """
-            create table test_dynamic(
-                k0 DATE not null
-            )
-            auto partition by range (date_trunc(k0, 'year')) ()
-            DISTRIBUTED BY HASH(`k0`) BUCKETS auto
-            properties("replication_num" = "1");
-        """
 
+
+    // dynamic + auto partition
+    sql """ admin set frontend config 
('dynamic_partition_check_interval_seconds' = '1') """
     // PROHIBIT different timeunit of interval when use both auto & dynamic 
partition
-    sql "set experimental_enable_nereids_planner=true;"
     test{
         sql """
             CREATE TABLE tbl3
@@ -273,45 +241,18 @@ suite("test_auto_partition_behavior") {
                 "dynamic_partition.buckets" = "8"
             ); 
         """
-        exception "Can't use Dynamic Partition and Auto Partition at the same 
time"
-    }
-    test {
-        sql """
-            ALTER TABLE test_dynamic set (
-                "dynamic_partition.enable" = "true", 
-                "dynamic_partition.time_unit" = "DAY", 
-                "dynamic_partition.end" = "3", 
-                "dynamic_partition.prefix" = "p", 
-                "dynamic_partition.buckets" = "32"
-            );
-        """
-        exception "Can't use Dynamic Partition and Auto Partition at the same 
time"
+        exception "If support auto partition and dynamic partition at same 
time, they must have the same interval unit."
     }
 
-    sql "set experimental_enable_nereids_planner=false;"
-    test{
-        sql """
-            CREATE TABLE tbl3
-            (
-                k1 DATETIME NOT NULL,
-                col1 int 
+    sql " drop table if exists test_dynamic "
+    sql """
+            create table test_dynamic(
+                k0 DATE not null
             )
-            auto partition by range (date_trunc(`k1`, 'year')) ()
-            DISTRIBUTED BY HASH(k1)
-            PROPERTIES
-            (
-                "replication_num" = "1",
-                "dynamic_partition.create_history_partition"="true",
-                "dynamic_partition.enable" = "true",
-                "dynamic_partition.time_unit" = "HOUR",
-                "dynamic_partition.start" = "-2",
-                "dynamic_partition.end" = "2",
-                "dynamic_partition.prefix" = "p",
-                "dynamic_partition.buckets" = "8"
-            ); 
+            auto partition by range (date_trunc(k0, 'year')) ()
+            DISTRIBUTED BY HASH(`k0`) BUCKETS auto
+            properties("replication_num" = "1");
         """
-        exception "Can't use Dynamic Partition and Auto Partition at the same 
time"
-    }
     test {
         sql """
             ALTER TABLE test_dynamic set (
@@ -322,8 +263,70 @@ suite("test_auto_partition_behavior") {
                 "dynamic_partition.buckets" = "32"
             );
         """
-        exception "Can't use Dynamic Partition and Auto Partition at the same 
time"
+        exception "If support auto partition and dynamic partition at same 
time, they must have the same interval unit."
     }
+    sql """
+        ALTER TABLE test_dynamic set (
+            "dynamic_partition.enable" = "true", 
+            "dynamic_partition.time_unit" = "YeAr", 
+            "dynamic_partition.end" = "3", 
+            "dynamic_partition.prefix" = "p", 
+            "dynamic_partition.buckets" = "32"
+        );
+    """
+
+    sql " drop table if exists auto_dynamic "
+    sql """
+        create table auto_dynamic(
+            k0 datetime(6) NOT NULL
+        )
+        auto partition by range (date_trunc(k0, 'hour'))
+        (
+        )
+        DISTRIBUTED BY HASH(`k0`) BUCKETS 2
+        properties(
+            "dynamic_partition.enable" = "true",
+            "dynamic_partition.prefix" = "p",
+            "dynamic_partition.create_history_partition" = "true",
+            "dynamic_partition.start" = "-5",
+            "dynamic_partition.end" = "0",
+            "dynamic_partition.time_unit" = "hour",
+            "replication_num" = "1"
+        );
+    """
+    def part_result = sql " show partitions from auto_dynamic "
+    assertEquals(part_result.size, 6)
+
+    sql " drop table if exists auto_dynamic "
+    sql """
+        create table auto_dynamic(
+            k0 datetime(6) NOT NULL
+        )
+        auto partition by range (date_trunc(k0, 'year'))
+        (
+        )
+        DISTRIBUTED BY HASH(`k0`) BUCKETS 2
+        properties(
+            "dynamic_partition.enable" = "true",
+            "dynamic_partition.prefix" = "p",
+            "dynamic_partition.start" = "-50",
+            "dynamic_partition.end" = "0",
+            "dynamic_partition.time_unit" = "year",
+            "replication_num" = "1"
+        );
+    """
+    part_result = sql " show partitions from auto_dynamic "
+    assertEquals(part_result.size, 1)
+    sql " insert into auto_dynamic values ('2024-01-01'), ('2900-01-01'), 
('1900-01-01'), ('3000-01-01'); "
+    sleep(3000)
+    part_result = sql " show partitions from auto_dynamic "
+    log.info("${part_result}".toString())
+    assertEquals(part_result.size, 3)
+    qt_sql_dynamic_auto "select * from auto_dynamic order by k0;"
+    sql """ admin set frontend config 
('dynamic_partition_check_interval_seconds' = '600') """
+
+
+
 
     // prohibit too long value for partition column
     sql "drop table if exists `long_value`"
@@ -345,25 +348,10 @@ suite("test_auto_partition_behavior") {
         exception exception_str
     }
 
-    // illegal partiton definetion
-    sql "set experimental_enable_nereids_planner=false;"
-    test{
-        sql """
-            create table illegal(
-                k0 datetime(6) NOT null,
-                k1 datetime(6) NOT null
-            )
-            auto partition by range (date_trunc(k0, k1, 'hour'))
-            (
-            )
-            DISTRIBUTED BY HASH(`k0`) BUCKETS 2
-            properties("replication_num" = "1");
-        """
-        exception "auto create partition only support one slotRef in function 
expr"
-    }
 
-    sql "set experimental_enable_nereids_planner=true;"
-    sql "set enable_fallback_to_original_planner=false;"
+
+
+    /// illegal partition exprs
     test{
         sql """
             create table illegal(
@@ -393,24 +381,11 @@ suite("test_auto_partition_behavior") {
         """
         exception "partition expr date_trunc is illegal!"
     }
-    sql "set experimental_enable_nereids_planner=false;"
-    test{
-        sql """
-            create table illegal(
-                k0 datetime(6) NOT null,
-                k1 int NOT null
-            )
-            auto partition by range (date_trunc(k1, 'hour'))
-            (
-            )
-            DISTRIBUTED BY HASH(`k0`) BUCKETS 2
-            properties("replication_num" = "1");
-        """
-        exception "Auto range partition needs Date/DateV2/Datetime/DatetimeV2 
column as partition column"
-    }
 
-    sql "set experimental_enable_nereids_planner=true;"
 
+
+
+    // altering table property effects new partitions.
     sql " drop table if exists test_change "
     sql """
         create table test_change(
@@ -426,7 +401,7 @@ suite("test_auto_partition_behavior") {
     logger.info("get table replica num: " + replicaNum)
 
     sql """ insert into test_change values ("20201212"); """
-    def part_result = sql " show tablets from test_change "
+    part_result = sql " show tablets from test_change "
     assertEquals(part_result.size, 2 * replicaNum)
     sql """ ALTER TABLE test_change MODIFY DISTRIBUTION DISTRIBUTED BY 
HASH(k0) BUCKETS 50; """
     sql """ insert into test_change values ("20001212"); """
diff --git 
a/regression-test/suites/partition_p1/dynamic_partition/test_dynamic_partition.groovy
 
b/regression-test/suites/partition_p1/dynamic_partition/test_dynamic_partition.groovy
index a0434bb0c10..a9dfcce8eac 100644
--- 
a/regression-test/suites/partition_p1/dynamic_partition/test_dynamic_partition.groovy
+++ 
b/regression-test/suites/partition_p1/dynamic_partition/test_dynamic_partition.groovy
@@ -15,11 +15,10 @@
 // specific language governing permissions and limitations
 // under the License.
 
-suite("test_dynamic_partition_with_update","nonConcurrent") {
-    def tbl = "test_dynamic_partition_with_update"
-    sql "drop table if exists ${tbl}"
+suite("test_dynamic_partition_with_update", "nonConcurrent") {
+    sql "drop table if exists test_dynamic_partition_with_update"
     sql """
-            CREATE TABLE IF NOT EXISTS ${tbl}
+            CREATE TABLE IF NOT EXISTS test_dynamic_partition_with_update
             ( k1 date NOT NULL )
             PARTITION BY RANGE(k1) ( )
             DISTRIBUTED BY HASH(k1) BUCKETS 1
@@ -36,38 +35,38 @@ suite("test_dynamic_partition_with_update","nonConcurrent") 
{
         """
 
     // set check interval time
-    sql """ admin set frontend config 
('dynamic_partition_check_interval_seconds' = '2') """
+    sql """ admin set frontend config 
('dynamic_partition_check_interval_seconds' = '1') """
 
     // check table init
-    def result = sql "show partitions from ${tbl}"
+    def result = sql "show partitions from test_dynamic_partition_with_update"
     assertEquals(7, result.size())
     result = sql "show dynamic partition tables"
     assertEquals("true",result.get(0).get(1))
 
     // disable dynamic partition to insert partition
-    sql """ alter table ${tbl} set ('dynamic_partition.enable' = 'false') """
+    sql """ alter table test_dynamic_partition_with_update set 
('dynamic_partition.enable' = 'false') """
     result = sql "show dynamic partition tables"
     assertEquals("false",result.get(0).get(1))
 
     // manually insert partition
-    sql """ alter table ${tbl} add partition p1 values [("2020-01-02"), 
("2020-01-05")) """
-    sql """ alter table ${tbl} add partition p2 values [("2020-05-02"), 
("2020-06-06")) """
-    sql """ alter table ${tbl} add partition p3 values [("2020-07-04"), 
("2020-07-28")) """
-    sql """ alter table ${tbl} add partition p4 values [("2999-04-25"), 
("2999-04-28")) """
+    sql """ alter table test_dynamic_partition_with_update add partition p1 
values [("2020-01-02"), ("2020-01-05")) """
+    sql """ alter table test_dynamic_partition_with_update add partition p2 
values [("2020-05-02"), ("2020-06-06")) """
+    sql """ alter table test_dynamic_partition_with_update add partition p3 
values [("2020-07-04"), ("2020-07-28")) """
+    sql """ alter table test_dynamic_partition_with_update add partition p4 
values [("2999-04-25"), ("2999-04-28")) """
 
     // check size
-    result = sql "show partitions from ${tbl}"
+    result = sql "show partitions from test_dynamic_partition_with_update"
     assertEquals(11, result.size())
-    sql """ alter table ${tbl} set ('dynamic_partition.enable' = 'true') """
+    sql """ alter table test_dynamic_partition_with_update set 
('dynamic_partition.enable' = 'true') """
     result = sql "show dynamic partition tables"
     assertEquals("true",result.get(0).get(1))
 
     // check and update
-    sleep(5000);
+    sleep(3000)
 
     // check size
-    result = sql "show partitions from ${tbl}"
+    result = sql "show partitions from test_dynamic_partition_with_update"
     assertEquals(8, result.size())
 
-    sql "drop table ${tbl}"
+    sql """ admin set frontend config 
('dynamic_partition_check_interval_seconds' = '600') """
 }


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

Reply via email to