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

yiguolei 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 3f4ca3da32 [Bug](CURRENT_TIMESTAMP) Fix wrong default value after 
schema change (#16364)
3f4ca3da32 is described below

commit 3f4ca3da32a9d4a5506addbb2304774ea85b08f4
Author: Gabriel <gabrielleeb...@gmail.com>
AuthorDate: Fri Feb 3 17:06:24 2023 +0800

    [Bug](CURRENT_TIMESTAMP) Fix wrong default value after schema change 
(#16364)
    
    * [Bug](CURRENT_TIMESTAMP) Fix wrong default value after schema change
    
    * update
    
    * update
---
 .../java/org/apache/doris/analysis/ColumnDef.java  | 20 ++++++--
 .../main/java/org/apache/doris/catalog/Column.java | 32 +++++++++++--
 .../doris/datasource/HMSExternalCatalog.java       |  4 +-
 .../datasource/iceberg/IcebergExternalCatalog.java |  2 +-
 .../org/apache/doris/external/jdbc/JdbcClient.java |  4 +-
 .../date/test_default_current_timestamp.out        |  4 ++
 .../date/test_default_current_timestamp.groovy     | 54 ++++++++++++++++++++++
 7 files changed, 107 insertions(+), 13 deletions(-)

diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
index 49052059d9..123e6e0bbc 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/ColumnDef.java
@@ -28,11 +28,14 @@ import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
 import org.apache.doris.common.Config;
 import org.apache.doris.common.FeNameFormat;
+import org.apache.doris.common.util.TimeUtils;
 
 import com.google.common.base.Preconditions;
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
+import java.time.LocalDateTime;
+
 // Column definition which is generated by SQL syntax parser
 // Syntax:
 //      name type [key] [agg_type] [NULL | NOT NULL] [DEFAULT default_value] 
[comment]
@@ -95,6 +98,16 @@ public class ColumnDef {
         public static DefaultValue HLL_EMPTY_DEFAULT_VALUE = new 
DefaultValue(true, ZERO);
         // default "value", "0" means empty bitmap
         public static DefaultValue BITMAP_EMPTY_DEFAULT_VALUE = new 
DefaultValue(true, ZERO);
+
+        public boolean isCurrentTimeStamp() {
+            return "CURRENT_TIMESTAMP".equals(value) && 
NOW.equals(defaultValueExprDef.getExprName());
+        }
+
+        public String getValue() {
+            return isCurrentTimeStamp()
+                    ? 
LocalDateTime.now(TimeUtils.getTimeZone().toZoneId()).toString().replace('T', ' 
')
+                    : value;
+        }
     }
 
     // parameter initialized in constructor
@@ -362,12 +375,12 @@ public class ColumnDef {
                 break;
             case DATE:
             case DATEV2:
-                new DateLiteral(defaultValue, 
ScalarType.getDefaultDateType(type));
+                new DateLiteral(defaultValue, scalarType);
                 break;
             case DATETIME:
             case DATETIMEV2:
                 if (defaultValueExprDef == null) {
-                    new DateLiteral(defaultValue, 
ScalarType.getDefaultDateType(type));
+                    new DateLiteral(defaultValue, scalarType);
                 } else {
                     if 
(defaultValueExprDef.getExprName().equals(DefaultValue.NOW)) {
                         break;
@@ -424,7 +437,8 @@ public class ColumnDef {
 
     public Column toColumn() {
         return new Column(name, typeDef.getType(), isKey, aggregateType, 
isAllowNull, defaultValue.value, comment,
-                visible, defaultValue.defaultValueExprDef, 
Column.COLUMN_UNIQUE_ID_INIT_VALUE);
+                visible, defaultValue.defaultValueExprDef, 
Column.COLUMN_UNIQUE_ID_INIT_VALUE,
+                defaultValue.getValue());
     }
 
     @Override
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
index d1230e6cb1..9a48960ce5 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Column.java
@@ -90,6 +90,16 @@ public class Column implements Writable, GsonPostProcessable 
{
     private ColumnStats stats;     // cardinality and selectivity etc.
     @SerializedName(value = "children")
     private List<Column> children;
+    /**
+     * This is similar as `defaultValue`. Differences are:
+     * 1. `realDefaultValue` indicates the **default underlying literal**.
+     * 2. Instead, `defaultValue` indicates the **original expression** which 
is specified by users.
+     *
+     * For example, if user create a table with (columnA, DATETIME, DEFAULT 
CURRENT_TIMESTAMP)
+     * `realDefaultValue` here is current date time while `defaultValue` is 
`CURRENT_TIMESTAMP`.
+     */
+    @SerializedName(value = "realDefaultValue")
+    private String realDefaultValue;
     // Define expr may exist in two forms, one is analyzed, and the other is 
not analyzed.
     // Currently, analyzed define expr is only used when creating materialized 
views,
     // so the define expr in RollupJob must be analyzed.
@@ -137,12 +147,18 @@ public class Column implements Writable, 
GsonPostProcessable {
     public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
             String defaultValue, String comment) {
         this(name, type, isKey, aggregateType, isAllowNull, defaultValue, 
comment, true, null,
-                COLUMN_UNIQUE_ID_INIT_VALUE);
+                COLUMN_UNIQUE_ID_INIT_VALUE, defaultValue);
+    }
+
+    public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
+            String comment, boolean visible, int colUniqueId) {
+        this(name, type, isKey, aggregateType, isAllowNull, null, comment, 
visible, null,
+                colUniqueId, null);
     }
 
     public Column(String name, Type type, boolean isKey, AggregateType 
aggregateType, boolean isAllowNull,
             String defaultValue, String comment, boolean visible, 
DefaultValueExprDef defaultValueExprDef,
-            int colUniqueId) {
+            int colUniqueId, String realDefaultValue) {
         this.name = name;
         if (this.name == null) {
             this.name = "";
@@ -158,6 +174,7 @@ public class Column implements Writable, 
GsonPostProcessable {
         this.isKey = isKey;
         this.isAllowNull = isAllowNull;
         this.defaultValue = defaultValue;
+        this.realDefaultValue = realDefaultValue;
         this.defaultValueExprDef = defaultValueExprDef;
         this.comment = comment;
         this.stats = new ColumnStats();
@@ -176,6 +193,7 @@ public class Column implements Writable, 
GsonPostProcessable {
         this.isCompoundKey = column.isCompoundKey();
         this.isAllowNull = column.isAllowNull();
         this.defaultValue = column.getDefaultValue();
+        this.realDefaultValue = column.realDefaultValue;
         this.defaultValueExprDef = column.defaultValueExprDef;
         this.comment = column.getComment();
         this.stats = column.getStats();
@@ -393,7 +411,8 @@ public class Column implements Writable, 
GsonPostProcessable {
         }
         tColumn.setIsKey(this.isKey);
         tColumn.setIsAllowNull(this.isAllowNull);
-        tColumn.setDefaultValue(this.defaultValue);
+        // keep compatibility
+        tColumn.setDefaultValue(this.realDefaultValue == null ? 
this.defaultValue : this.realDefaultValue);
         tColumn.setVisible(visible);
         toChildrenThrift(this, tColumn);
 
@@ -591,7 +610,8 @@ public class Column implements Writable, 
GsonPostProcessable {
     @Override
     public int hashCode() {
         return Objects.hash(name, getDataType(), getStrLen(), getPrecision(), 
getScale(), aggregationType,
-                isAggregationTypeImplicit, isKey, isAllowNull, defaultValue, 
comment, children, visible);
+                isAggregationTypeImplicit, isKey, isAllowNull, defaultValue, 
comment, children, visible,
+                realDefaultValue);
     }
 
     @Override
@@ -617,7 +637,8 @@ public class Column implements Writable, 
GsonPostProcessable {
                 && getScale() == other.getScale()
                 && Objects.equals(comment, other.comment)
                 && visible == other.visible
-                && Objects.equals(children, other.children);
+                && Objects.equals(children, other.children)
+                && Objects.equals(realDefaultValue, other.realDefaultValue);
     }
 
     @Override
@@ -640,6 +661,7 @@ public class Column implements Writable, 
GsonPostProcessable {
         notNull = in.readBoolean();
         if (notNull) {
             defaultValue = Text.readString(in);
+            realDefaultValue = defaultValue;
         }
         stats = ColumnStats.read(in);
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/HMSExternalCatalog.java 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/HMSExternalCatalog.java
index 336d31df7e..ccf05e597b 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/HMSExternalCatalog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/HMSExternalCatalog.java
@@ -192,7 +192,7 @@ public class HMSExternalCatalog extends ExternalCatalog {
         for (FieldSchema field : schema) {
             tmpSchema.add(new Column(field.getName(),
                     
HiveMetaStoreClientHelper.hiveTypeToDorisType(field.getType()), true, null,
-                    true, null, field.getComment(), true, null, -1));
+                    true, field.getComment(), true, -1));
         }
         return tmpSchema;
     }
@@ -204,7 +204,7 @@ public class HMSExternalCatalog extends ExternalCatalog {
         for (FieldSchema field : hmsSchema) {
             tmpSchema.add(new Column(field.getName(),
                     
HiveMetaStoreClientHelper.hiveTypeToDorisType(field.getType()), true, null,
-                    true, null, field.getComment(), true, null,
+                    true, field.getComment(), true,
                     
schema.caseInsensitiveFindField(field.getName()).fieldId()));
         }
         return tmpSchema;
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
index 53e5b57459..c396ca268f 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/datasource/iceberg/IcebergExternalCatalog.java
@@ -185,7 +185,7 @@ public abstract class IcebergExternalCatalog extends 
ExternalCatalog {
         for (Types.NestedField field : columns) {
             tmpSchema.add(new Column(field.name(),
                     icebergTypeToDorisType(field.type()), true, null,
-                    true, null, field.doc(), true, null, -1));
+                    true, field.doc(), true, -1));
         }
         return tmpSchema;
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java 
b/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
index 3605fefdd9..8e9d754b8c 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/external/jdbc/JdbcClient.java
@@ -678,8 +678,8 @@ public class JdbcClient {
         for (JdbcFieldSchema field : jdbcTableSchema) {
             dorisTableSchema.add(new Column(field.getColumnName(),
                     jdbcTypeToDoris(field), true, null,
-                    true, null, field.getRemarks(),
-                    true, null, -1));
+                    true, field.getRemarks(),
+                    true, -1));
         }
         return dorisTableSchema;
     }
diff --git 
a/regression-test/data/datatype_p0/date/test_default_current_timestamp.out 
b/regression-test/data/datatype_p0/date/test_default_current_timestamp.out
new file mode 100644
index 0000000000..4ee136aef2
--- /dev/null
+++ b/regression-test/data/datatype_p0/date/test_default_current_timestamp.out
@@ -0,0 +1,4 @@
+-- This file is automatically generated. You should know what you did if you 
want to edit this
+-- !sql --
+2
+
diff --git 
a/regression-test/suites/datatype_p0/date/test_default_current_timestamp.groovy 
b/regression-test/suites/datatype_p0/date/test_default_current_timestamp.groovy
new file mode 100644
index 0000000000..1cc6ad8044
--- /dev/null
+++ 
b/regression-test/suites/datatype_p0/date/test_default_current_timestamp.groovy
@@ -0,0 +1,54 @@
+
+// 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_default_current_timestamp") {
+    def tbName = "test_default_current_timestamp"
+    sql "DROP TABLE IF EXISTS ${tbName}"
+    sql """
+            CREATE TABLE IF NOT EXISTS ${tbName} (
+                `house_id` bigint(20) NULL DEFAULT "-1" COMMENT '仓库id',
+                `pick_order_big_num` decimal(27, 9) NULL
+            )
+            UNIQUE KEY(house_id)
+            DISTRIBUTED BY HASH(house_id) BUCKETS 5 
properties("replication_num" = "1");
+        """
+    sql "insert into ${tbName} values(1,1.1)"
+    sql "insert into ${tbName} values(2,1.1)"
+
+    sql """ ALTER TABLE ${tbName} ADD COLUMN compute_time datetime NULL 
DEFAULT CURRENT_TIMESTAMP COMMENT '计算时间' AFTER pick_order_big_num; """
+
+    def getJobState = { tableName ->
+         def jobStateResult = sql """  SHOW ALTER TABLE COLUMN WHERE 
IndexName='${tableName}' ORDER BY createtime DESC LIMIT 1 """
+         return jobStateResult[0][9]
+    }
+    int max_try_time = 1000
+    while(max_try_time--){
+        String result = getJobState(tbName)
+        if (result == "FINISHED") {
+            break
+        } else {
+            sleep(100)
+            if (max_try_time < 1){
+                assertEquals(1,2)
+            }
+        }
+    }
+    sql """sync"""
+    qt_sql """ SELECT COUNT(*) FROM ${tbName} WHERE date(compute_time) = 
curdate() """
+    sql "DROP TABLE ${tbName}"
+}


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

Reply via email to