You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@doris.apache.org by mo...@apache.org on 2021/07/10 02:10:39 UTC

[incubator-doris] branch master updated: [Bug] Create dynamic partition table failed with enable create_history_partition and not specify the start value (#6129)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 65892ce  [Bug] Create dynamic partition table failed with enable create_history_partition and not specify the start value (#6129)
65892ce is described below

commit 65892cec3bd90f6b1933929855f7763a68a098fa
Author: harveyyue <yw...@126.com>
AuthorDate: Sat Jul 10 10:10:28 2021 +0800

    [Bug] Create dynamic partition table failed with enable create_history_partition and not specify the start value (#6129)
    
    fix the issue #5995
    Add the property "dynamic_partition.history_partition_num" to specify the history partition number when enable create_history_partition to fix the invalid date format value
    and add these two properties to docs
---
 docs/en/administrator-guide/dynamic-partition.md   |  4 +++
 .../sql-statements/Data Definition/CREATE TABLE.md | 16 ++++-----
 .../zh-CN/administrator-guide/dynamic-partition.md |  4 +++
 .../sql-statements/Data Definition/CREATE TABLE.md |  2 ++
 .../doris/catalog/DynamicPartitionProperty.java    |  9 +++++
 .../doris/clone/DynamicPartitionScheduler.java     | 15 ++++++--
 .../java/org/apache/doris/common/ErrorCode.java    |  4 ++-
 .../doris/common/util/DynamicPartitionUtil.java    | 42 ++++++++++++++++++++--
 .../doris/catalog/DynamicPartitionTableTest.java   | 27 ++++++++++++++
 9 files changed, 108 insertions(+), 15 deletions(-)

diff --git a/docs/en/administrator-guide/dynamic-partition.md b/docs/en/administrator-guide/dynamic-partition.md
index 11125cc..cc5a12e 100644
--- a/docs/en/administrator-guide/dynamic-partition.md
+++ b/docs/en/administrator-guide/dynamic-partition.md
@@ -131,6 +131,10 @@ The rules of dynamic partition are prefixed with `dynamic_partition.`:
 
     When the `start` attribute is not specified, this parameter has no effect.
 
+* `dynamic_partition.history_partition_num`
+
+   When `create_history_partition` is `true`, this parameter is used to specify the number of history partitions.
+
 * `dynamic_partition.hot_partition_num`
 
     Specify how many of the latest partitions are hot partitions. For hot partition, the system will automatically set its `storage_medium` parameter to SSD, and set `storage_cooldown_time`.
diff --git a/docs/en/sql-reference/sql-statements/Data Definition/CREATE TABLE.md b/docs/en/sql-reference/sql-statements/Data Definition/CREATE TABLE.md
index d03094c..04caede 100644
--- a/docs/en/sql-reference/sql-statements/Data Definition/CREATE TABLE.md	
+++ b/docs/en/sql-reference/sql-statements/Data Definition/CREATE TABLE.md	
@@ -303,16 +303,14 @@ Syntax:
         )    
        ```
        
-       Dynamic_partition. Enable: specifies whether dynamic partitioning at the table level is enabled
-       
-       Dynamic_partition. Time_unit: used to specify the time unit for dynamically adding partitions, which can be selected as HOUR, DAY, WEEK, and MONTH.
+       dynamic_partition.enable: specifies whether dynamic partitioning at the table level is enabled
+       dynamic_partition.time_unit: used to specify the time unit for dynamically adding partitions, which can be selected as HOUR, DAY, WEEK, and MONTH.
                                      Attention: When the time unit is HOUR, the data type of partition column cannot be DATE.
-       
-       Dynamic_partition. End: used to specify the number of partitions created in advance
-       
-       Dynamic_partition. Prefix: used to specify the partition name prefix to be created, such as the partition name prefix p, automatically creates the partition name p20200108
-       
-       Dynamic_partition. Buckets: specifies the number of partition buckets that are automatically created
+       dynamic_partition.end: used to specify the number of partitions created in advance
+       dynamic_partition.prefix: used to specify the partition name prefix to be created, such as the partition name prefix p, automatically creates the partition name p20200108
+       dynamic_partition.buckets: specifies the number of partition buckets that are automatically created
+       dynamic_partition.create_history_partition: specifies whether create history partitions, default value is false
+       dynamic_partition.history_partition_num: used to specify the number of history partitions when enable create_history_partition
        ```
     5)  You can create multiple Rollups in bulk when building a table
     grammar:
diff --git a/docs/zh-CN/administrator-guide/dynamic-partition.md b/docs/zh-CN/administrator-guide/dynamic-partition.md
index 80d3163..2c49d3d 100644
--- a/docs/zh-CN/administrator-guide/dynamic-partition.md
+++ b/docs/zh-CN/administrator-guide/dynamic-partition.md
@@ -129,6 +129,10 @@ under the License.
 
     当不指定 `start` 属性时,该参数不生效。
 
+* `dynamic_partition.history_partition_num`
+   
+   当 `create_history_partition` 为 `true` 时,该参数用于指定创建历史分区数量。
+
 * `dynamic_partition.hot_partition_num`
 
     指定最新的多少个分区为热分区。对于热分区,系统会自动设置其 `storage_medium` 参数为SSD,并且设置 `storage_cooldown_time`。
diff --git a/docs/zh-CN/sql-reference/sql-statements/Data Definition/CREATE TABLE.md b/docs/zh-CN/sql-reference/sql-statements/Data Definition/CREATE TABLE.md
index fad649d..15abbbf 100644
--- a/docs/zh-CN/sql-reference/sql-statements/Data Definition/CREATE TABLE.md	
+++ b/docs/zh-CN/sql-reference/sql-statements/Data Definition/CREATE TABLE.md	
@@ -332,6 +332,8 @@ under the License.
     dynamic_partition.end: 用于指定提前创建的分区数量。值必须大于0。
     dynamic_partition.prefix: 用于指定创建的分区名前缀,例如分区名前缀为p,则自动创建分区名为p20200108
     dynamic_partition.buckets: 用于指定自动创建的分区分桶数量
+    dynamic_partition.create_history_partition: 用于创建历史分区功能是否开启。默认为 false。
+    dynamic_partition.history_partition_num: 当开启创建历史分区功能时,用于指定创建历史分区数量。
     
     5) 建表时可以批量创建多个 Rollup
     语法:
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/DynamicPartitionProperty.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/DynamicPartitionProperty.java
index 50892a0..1837c63 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/DynamicPartitionProperty.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/DynamicPartitionProperty.java
@@ -37,11 +37,13 @@ public class DynamicPartitionProperty {
     public static final String TIME_ZONE = "dynamic_partition.time_zone";
     public static final String REPLICATION_NUM = "dynamic_partition.replication_num";
     public static final String CREATE_HISTORY_PARTITION = "dynamic_partition.create_history_partition";
+    public static final String HISTORY_PARTITION_NUM = "dynamic_partition.history_partition_num";
     public static final String HOT_PARTITION_NUM = "dynamic_partition.hot_partition_num";
 
     public static final int MIN_START_OFFSET = Integer.MIN_VALUE;
     public static final int MAX_END_OFFSET = Integer.MAX_VALUE;
     public static final int NOT_SET_REPLICATION_NUM = -1;
+    public static final int NOT_SET_HISTORY_PARTITION_NUM = -1;
 
     private boolean exist;
 
@@ -56,6 +58,7 @@ public class DynamicPartitionProperty {
     private TimeZone tz = TimeUtils.getSystemTimeZone();
     private int replicationNum;
     private boolean createHistoryPartition = false;
+    private int historyPartitionNum;
     // This property are used to describe the number of partitions that need to be reserved on the high-speed storage.
     // If not set, default is 0
     private int hotPartitionNum;
@@ -73,6 +76,7 @@ public class DynamicPartitionProperty {
             this.buckets = Integer.parseInt(properties.get(BUCKETS));
             this.replicationNum = Integer.parseInt(properties.getOrDefault(REPLICATION_NUM, String.valueOf(NOT_SET_REPLICATION_NUM)));
             this.createHistoryPartition = Boolean.parseBoolean(properties.get(CREATE_HISTORY_PARTITION));
+            this.historyPartitionNum = Integer.parseInt(properties.getOrDefault(HISTORY_PARTITION_NUM, String.valueOf(NOT_SET_HISTORY_PARTITION_NUM)));
             this.hotPartitionNum = Integer.parseInt(properties.getOrDefault(HOT_PARTITION_NUM, "0"));
             createStartOfs(properties);
         } else {
@@ -136,6 +140,10 @@ public class DynamicPartitionProperty {
         return createHistoryPartition;
     }
 
+    public int getHistoryPartitionNum() {
+        return historyPartitionNum;
+    }
+
     public int getHotPartitionNum() {
         return hotPartitionNum;
     }
@@ -175,6 +183,7 @@ public class DynamicPartitionProperty {
                 ",\n\"" + REPLICATION_NUM + "\" = \"" + useReplicationNum + "\"" +
                 ",\n\"" + BUCKETS + "\" = \"" + buckets + "\"" +
                 ",\n\"" + CREATE_HISTORY_PARTITION + "\" = \"" + createHistoryPartition + "\"" +
+                ",\n\"" + HISTORY_PARTITION_NUM + "\" = \"" + historyPartitionNum + "\"" +
                 ",\n\"" + HOT_PARTITION_NUM + "\" = \"" + hotPartitionNum + "\"";
         if (getTimeUnit().equalsIgnoreCase(TimeUnit.WEEK.toString())) {
             res += ",\n\"" + START_DAY_OF_WEEK + "\" = \"" + startOfWeek.dayOfWeek + "\"";
diff --git a/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java b/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
index abca24b..a860c1f 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/clone/DynamicPartitionScheduler.java
@@ -143,9 +143,20 @@ public class DynamicPartitionScheduler extends MasterDaemon {
         ZonedDateTime now = ZonedDateTime.now(dynamicPartitionProperty.getTimeZone().toZoneId());
 
         boolean createHistoryPartition = dynamicPartitionProperty.isCreateHistoryPartition();
-        int idx = createHistoryPartition ? dynamicPartitionProperty.getStart() : 0;
+        int idx;
+        int start = dynamicPartitionProperty.getStart();
+        int historyPartitionNum = dynamicPartitionProperty.getHistoryPartitionNum();
+        // When enable create_history_partition, will check the valid value from start and history_partition_num.
+        if (createHistoryPartition) {
+            if (historyPartitionNum == DynamicPartitionProperty.NOT_SET_HISTORY_PARTITION_NUM) {
+                idx = start;
+            } else {
+                idx = Math.max(start, -historyPartitionNum);
+            }
+        } else {
+            idx = 0;
+        }
         int hotPartitionNum = dynamicPartitionProperty.getHotPartitionNum();
-        String timeUnit = dynamicPartitionProperty.getTimeUnit();
 
         for (; idx <= dynamicPartitionProperty.getEnd(); idx++) {
             String prevBorder = DynamicPartitionUtil.getPartitionRangeString(dynamicPartitionProperty, now, idx, partitionFormat);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java b/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java
index 71447c6..10819a7 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/common/ErrorCode.java
@@ -241,7 +241,9 @@ public enum ErrorCode {
     ERROR_CREATE_TABLE_LIKE_EMPTY(5073, new byte[] {'4', '2', '0', '0', '0'},
             "Origin create table stmt is empty"),
     ERROR_DYNAMIC_PARTITION_CREATE_HISTORY_PARTITION(5074, new byte[]{'4', '2', '0', '0', '0'},
-            "Invalid dynamic partition create_history_partition: %s. Expected true or false");
+            "Invalid dynamic partition create_history_partition: %s. Expected true or false"),
+    ERROR_DYNAMIC_PARTITION_HISTORY_PARTITION_NUM_ZERO(5075, new byte[] {'4', '2', '0', '0', '0'},
+            "Dynamic history partition num must greater than 0");
 
     ErrorCode(int code, byte[] sqlState, String errorMsg) {
         this.code = code;
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 4454087..bf9e2c5 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
@@ -79,7 +79,7 @@ public class DynamicPartitionUtil {
                     + TimeUnit.HOUR.toString() + " when type of partition column "
                     + partitionColumn.getDisplayName() + " is " + PrimitiveType.DATE.toString());
         } else if (PrimitiveType.getIntegerTypes().contains(partitionColumn.getDataType())
-           && timeUnit.equalsIgnoreCase(TimeUnit.HOUR.toString())) {
+                && timeUnit.equalsIgnoreCase(TimeUnit.HOUR.toString())) {
             // The partition column's type is INT, not support HOUR
             ErrorReport.reportDdlException(DynamicPartitionProperty.TIME_UNIT + " could not be "
                     + TimeUnit.HOUR.toString() + " when type of partition column "
@@ -152,6 +152,20 @@ public class DynamicPartitionUtil {
         return Boolean.valueOf(create);
     }
 
+    private static void checkHistoryPartitionNum(String val) throws DdlException {
+        if (Strings.isNullOrEmpty(val)) {
+            throw new DdlException("Invalid properties: " + DynamicPartitionProperty.HISTORY_PARTITION_NUM);
+        }
+        try {
+            int historyPartitionNum = Integer.parseInt(val);
+            if (historyPartitionNum <= 0) {
+                ErrorReport.reportDdlException(ErrorCode.ERROR_DYNAMIC_PARTITION_HISTORY_PARTITION_NUM_ZERO);
+            }
+        } catch (NumberFormatException e) {
+            throw new DdlException("Invalid properties: " + DynamicPartitionProperty.HISTORY_PARTITION_NUM);
+        }
+    }
+
     private static void checkStartDayOfMonth(String val) throws DdlException {
         if (Strings.isNullOrEmpty(val)) {
             throw new DdlException("Invalid properties: " + DynamicPartitionProperty.START_DAY_OF_MONTH);
@@ -348,13 +362,35 @@ public class DynamicPartitionUtil {
             analyzedProperties.put(DynamicPartitionProperty.CREATE_HISTORY_PARTITION, val);
         }
 
+        if (properties.containsKey(DynamicPartitionProperty.HISTORY_PARTITION_NUM)) {
+            String val = properties.get(DynamicPartitionProperty.HISTORY_PARTITION_NUM);
+            checkHistoryPartitionNum(val);
+            properties.remove(DynamicPartitionProperty.HISTORY_PARTITION_NUM);
+            analyzedProperties.put(DynamicPartitionProperty.HISTORY_PARTITION_NUM, val);
+        }
+
         // Check the number of dynamic partitions that need to be created to avoid creating too many partitions at once.
         // If create_history_partition is false, history partition is not considered.
+        // If create_history_partition is true, will pre-create history partition according the valid value from
+        // start and history_partition_num.
+        int expectCreatePartitionNum;
         if (!createHistoryPartition) {
             start = 0;
+            expectCreatePartitionNum = end - start;
+        } else {
+            int historyPartitionNum = Integer.valueOf(analyzedProperties.getOrDefault(DynamicPartitionProperty.HISTORY_PARTITION_NUM,
+                    String.valueOf(DynamicPartitionProperty.NOT_SET_HISTORY_PARTITION_NUM)));
+            if (historyPartitionNum != DynamicPartitionProperty.NOT_SET_HISTORY_PARTITION_NUM) {
+                expectCreatePartitionNum = end - Math.max(start, -historyPartitionNum);
+            } else {
+                if (start == Integer.MIN_VALUE) {
+                    throw new DdlException("Provide start or create_history_partition property when creating history partition");
+                }
+                expectCreatePartitionNum = end - start;
+            }
         }
-        if (hasEnd && (end - start > Config.max_dynamic_partition_num)) {
-            throw new DdlException("Too many dynamic partitions: " + (end - start) + ". Limit: " + Config.max_dynamic_partition_num);
+        if (hasEnd && (expectCreatePartitionNum > Config.max_dynamic_partition_num)) {
+            throw new DdlException("Too many dynamic partitions: " + expectCreatePartitionNum + ". Limit: " + Config.max_dynamic_partition_num);
         }
 
         if (properties.containsKey(DynamicPartitionProperty.START_DAY_OF_MONTH)) {
diff --git a/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java b/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
index 06f01c0..f46c149 100644
--- a/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
+++ b/fe/fe-core/src/test/java/org/apache/doris/catalog/DynamicPartitionTableTest.java
@@ -587,6 +587,33 @@ public class DynamicPartitionTableTest {
     }
 
     @Test
+    public void testFillHistoryDynamicPartitionWithHistoryPartitionNum() throws Exception {
+        String createOlapTblStmt = "CREATE TABLE test.`history_dynamic_partition_day` (\n" +
+                "  `k1` datetime NULL COMMENT \"\",\n" +
+                "  `k2` int NULL COMMENT \"\"\n" +
+                ") ENGINE=OLAP\n" +
+                "PARTITION BY RANGE(`k1`)\n" +
+                "()\n" +
+                "DISTRIBUTED BY HASH(`k2`) BUCKETS 3\n" +
+                "PROPERTIES (\n" +
+                "\"replication_num\" = \"1\",\n" +
+                "\"dynamic_partition.enable\" = \"true\",\n" +
+                "\"dynamic_partition.end\" = \"3\",\n" +
+                "\"dynamic_partition.create_history_partition\" = \"true\",\n" +
+                "\"dynamic_partition.history_partition_num\" = \"10\",\n" +
+                "\"dynamic_partition.time_unit\" = \"day\",\n" +
+                "\"dynamic_partition.prefix\" = \"p\",\n" +
+                "\"dynamic_partition.buckets\" = \"1\"\n" +
+                ");";
+        createTable(createOlapTblStmt);
+        OlapTable emptyDynamicTable = (OlapTable) Catalog.getCurrentCatalog().getDb("default_cluster:test").getTable("history_dynamic_partition_day");
+        Map<String, String> tableProperties = emptyDynamicTable.getTableProperty().getProperties();
+        Assert.assertEquals(14, emptyDynamicTable.getAllPartitions().size());
+        // never delete the old partitions
+        Assert.assertEquals(Integer.parseInt(tableProperties.get("dynamic_partition.start")), Integer.MIN_VALUE);
+    }
+
+    @Test
     public void testAllTypeDynamicPartition() throws Exception {
         String createOlapTblStmt = "CREATE TABLE test.`hour_dynamic_partition` (\n" +
                 "  `k1` datetime NULL COMMENT \"\",\n" +

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