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

kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git

commit 446b188927798dee991aa7911eda5d8b68f94f66
Author: zclllyybb <zhaochan...@selectdb.com>
AuthorDate: Fri Aug 25 09:59:38 2023 +0800

    [fix](functions) fix function substitute for datetimeV1/V2 (#23344)
    
    * fix
    
    * function fe
---
 be/src/vec/functions/function_cast.h               |  4 +-
 be/src/vec/io/io_helper.h                          | 44 ++++++++++++++++++----
 .../main/java/org/apache/doris/catalog/Type.java   |  1 +
 .../main/java/org/apache/doris/analysis/Expr.java  |  2 +
 .../doris/analysis/TimestampArithmeticExpr.java    | 10 +++++
 .../datatype_p0/datetimev2/test_tz_streamload.out  |  9 ++++-
 .../datatype_p0/datetimev2/test_tz_streamload2.csv |  5 +++
 .../datetime_functions/test_date_function.out      |  3 ++
 .../datetime_functions/test_date_function.out      |  3 ++
 .../datetimev2/test_tz_streamload.groovy           | 40 ++++++++++++++++----
 .../datetime_functions/test_date_function.groovy   |  2 +
 .../datetime_functions/test_date_function.groovy   |  2 +
 12 files changed, 108 insertions(+), 17 deletions(-)

diff --git a/be/src/vec/functions/function_cast.h 
b/be/src/vec/functions/function_cast.h
index 528ba75a21..9133e1d724 100644
--- a/be/src/vec/functions/function_cast.h
+++ b/be/src/vec/functions/function_cast.h
@@ -844,11 +844,11 @@ bool try_parse_impl(typename DataType::FieldType& x, 
ReadBuffer& rb,
                     const cctz::time_zone& local_time_zone, ZoneList& 
time_zone_cache,
                     Additions additions [[maybe_unused]] = Additions()) {
     if constexpr (IsDateTimeType<DataType>) {
-        return try_read_datetime_text(x, rb);
+        return try_read_datetime_text(x, rb, local_time_zone, time_zone_cache);
     }
 
     if constexpr (IsDateType<DataType>) {
-        return try_read_date_text(x, rb);
+        return try_read_date_text(x, rb, local_time_zone, time_zone_cache);
     }
 
     if constexpr (IsDateV2Type<DataType>) {
diff --git a/be/src/vec/io/io_helper.h b/be/src/vec/io/io_helper.h
index 5f07d8ced1..4d8b69d1fd 100644
--- a/be/src/vec/io/io_helper.h
+++ b/be/src/vec/io/io_helper.h
@@ -269,6 +269,33 @@ bool read_int_text_impl(T& x, ReadBuffer& buf) {
     return true;
 }
 
+template <typename T>
+bool read_date_text_impl(T& x, ReadBuffer& buf) {
+    static_assert(std::is_same_v<Int64, T>);
+    auto dv = binary_cast<Int64, VecDateTimeValue>(x);
+    auto ans = dv.from_date_str(buf.position(), buf.count());
+    dv.cast_to_date();
+
+    // only to match the is_all_read() check to prevent return null
+    buf.position() = buf.end();
+    x = binary_cast<VecDateTimeValue, Int64>(dv);
+    return ans;
+}
+
+template <typename T>
+bool read_date_text_impl(T& x, ReadBuffer& buf, const cctz::time_zone& 
local_time_zone,
+                         ZoneList& time_zone_cache) {
+    static_assert(std::is_same_v<Int64, T>);
+    auto dv = binary_cast<Int64, VecDateTimeValue>(x);
+    auto ans = dv.from_date_str(buf.position(), buf.count(), local_time_zone, 
time_zone_cache);
+    dv.cast_to_date();
+
+    // only to match the is_all_read() check to prevent return null
+    buf.position() = buf.end();
+    x = binary_cast<VecDateTimeValue, Int64>(dv);
+    return ans;
+}
+
 template <typename T>
 bool read_datetime_text_impl(T& x, ReadBuffer& buf) {
     static_assert(std::is_same_v<Int64, T>);
@@ -283,11 +310,12 @@ bool read_datetime_text_impl(T& x, ReadBuffer& buf) {
 }
 
 template <typename T>
-bool read_date_text_impl(T& x, ReadBuffer& buf) {
+bool read_datetime_text_impl(T& x, ReadBuffer& buf, const cctz::time_zone& 
local_time_zone,
+                             ZoneList& time_zone_cache) {
     static_assert(std::is_same_v<Int64, T>);
     auto dv = binary_cast<Int64, VecDateTimeValue>(x);
-    auto ans = dv.from_date_str(buf.position(), buf.count());
-    dv.cast_to_date();
+    auto ans = dv.from_date_str(buf.position(), buf.count(), local_time_zone, 
time_zone_cache);
+    dv.to_datetime();
 
     // only to match the is_all_read() check to prevent return null
     buf.position() = buf.end();
@@ -422,13 +450,15 @@ bool try_read_decimal_text(T& x, ReadBuffer& in, UInt32 
precision, UInt32 scale)
 }
 
 template <typename T>
-bool try_read_datetime_text(T& x, ReadBuffer& in) {
-    return read_datetime_text_impl<T>(x, in);
+bool try_read_datetime_text(T& x, ReadBuffer& in, const cctz::time_zone& 
local_time_zone,
+                            ZoneList& time_zone_cache) {
+    return read_datetime_text_impl<T>(x, in, local_time_zone, time_zone_cache);
 }
 
 template <typename T>
-bool try_read_date_text(T& x, ReadBuffer& in) {
-    return read_date_text_impl<T>(x, in);
+bool try_read_date_text(T& x, ReadBuffer& in, const cctz::time_zone& 
local_time_zone,
+                        ZoneList& time_zone_cache) {
+    return read_date_text_impl<T>(x, in, local_time_zone, time_zone_cache);
 }
 
 template <typename T>
diff --git a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java 
b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
index 436b5e951e..b9c17ce455 100644
--- a/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
+++ b/fe/fe-common/src/main/java/org/apache/doris/catalog/Type.java
@@ -90,6 +90,7 @@ public abstract class Type {
     public static final ScalarType DEFAULT_DECIMALV3 = DEFAULT_DECIMAL32;
     public static final ScalarType DEFAULT_DATETIMEV2 = 
ScalarType.createDatetimeV2Type(0);
     public static final ScalarType DATETIMEV2 = DEFAULT_DATETIMEV2;
+    public static final ScalarType DATETIMEV2_WITH_MAX_SCALAR = 
ScalarType.createDatetimeV2Type(6);
     public static final ScalarType DEFAULT_TIMEV2 = 
ScalarType.createTimeV2Type(0);
     public static final ScalarType DECIMALV2 = DEFAULT_DECIMALV2;
     public static final ScalarType DECIMAL32 = DEFAULT_DECIMAL32;
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
index 24031bfb89..08f6d5b2f1 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Expr.java
@@ -2476,6 +2476,8 @@ public abstract class Expr extends TreeNode<Expr> 
implements ParseNode, Cloneabl
             return Type.DECIMAL128;
         } else if (originType.getPrimitiveType() == PrimitiveType.DATETIMEV2) {
             return Type.DATETIMEV2;
+        } else if (originType.getPrimitiveType() == PrimitiveType.DATEV2) {
+            return Type.DATEV2;
         } else if (originType.getPrimitiveType() == PrimitiveType.VARCHAR) {
             return Type.VARCHAR;
         } else if (originType.getPrimitiveType() == PrimitiveType.CHAR) {
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java
 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java
index e344a674f3..e8960f7e89 100644
--- 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java
+++ 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/TimestampArithmeticExpr.java
@@ -24,6 +24,7 @@ import org.apache.doris.catalog.PrimitiveType;
 import org.apache.doris.catalog.ScalarType;
 import org.apache.doris.catalog.Type;
 import org.apache.doris.common.AnalysisException;
+import org.apache.doris.common.Config;
 import org.apache.doris.common.ErrorCode;
 import org.apache.doris.common.ErrorReport;
 import org.apache.doris.thrift.TExprNode;
@@ -146,6 +147,15 @@ public class TimestampArithmeticExpr extends Expr {
             return Type.DATEV2;
         }
         if (PrimitiveType.isImplicitCast(t1, PrimitiveType.DATETIME)) {
+            if (Config.enable_date_conversion) {
+                if (t1 == PrimitiveType.NULL_TYPE) {
+                    getChild(0).type = Type.DATETIMEV2_WITH_MAX_SCALAR;
+                }
+                return Type.DATETIMEV2_WITH_MAX_SCALAR;
+            }
+            if (t1 == PrimitiveType.NULL_TYPE) {
+                getChild(0).type = Type.DATETIME;
+            }
             return Type.DATETIME;
         }
         return Type.INVALID;
diff --git a/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out 
b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out
index 3fc4fb93b6..cc87e0fdfa 100644
--- a/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out
+++ b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload.out
@@ -1,5 +1,5 @@
 -- This file is automatically generated. You should know what you did if you 
want to edit this
--- !all --
+-- !table1 --
 2022-01-01T01:02:55    2022-01-01
 2022-02-01T03:02:55    2022-02-01
 2022-02-28T19:02:55    2022-03-01
@@ -9,3 +9,10 @@
 2022-06-30T20:02:55    2022-07-01
 2022-07-31T21:00       2022-08-01
 
+-- !table2 --
+1      2023-08-17T17:41:18
+2      2023-08-17T17:41:18
+3      2023-08-17T17:41:18
+4      2023-08-17T14:41:18
+5      2023-08-17T09:41:18
+
diff --git 
a/regression-test/data/datatype_p0/datetimev2/test_tz_streamload2.csv 
b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload2.csv
new file mode 100644
index 0000000000..9d94561af4
--- /dev/null
+++ b/regression-test/data/datatype_p0/datetimev2/test_tz_streamload2.csv
@@ -0,0 +1,5 @@
+1,2023-08-17T01:41:18Z
+2,2023-08-17T01:41:18uTc
+3,2023-08-17T01:41:18UTC
+4,2023-08-17T01:41:18UTC+3
+5,2023-08-17T01:41:18Asia/Shanghai
\ No newline at end of file
diff --git 
a/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function.out
 
b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function.out
index 617d55e6af..43eff1b302 100644
--- 
a/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function.out
+++ 
b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_date_function.out
@@ -609,3 +609,6 @@ true
 2022-02-21     2022-02-21      2022-02-21      2022-02-21
 2022-02-28     2022-02-28      2022-02-28      2022-02-28
 
+-- !sql --
+2023-08-17T17:41:18
+
diff --git 
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out
 
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out
index 2f9cc35e4e..abfeacc037 100644
--- 
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out
+++ 
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_function.out
@@ -662,3 +662,6 @@ true
 -- !sql --
 2022-01-20T00:00       2023-01-20T00:00
 
+-- !sql --
+2023-08-17T17:41:18
+
diff --git 
a/regression-test/suites/datatype_p0/datetimev2/test_tz_streamload.groovy 
b/regression-test/suites/datatype_p0/datetimev2/test_tz_streamload.groovy
index c4b0cdf051..359f432bd5 100644
--- a/regression-test/suites/datatype_p0/datetimev2/test_tz_streamload.groovy
+++ b/regression-test/suites/datatype_p0/datetimev2/test_tz_streamload.groovy
@@ -16,12 +16,12 @@
 // under the License.
 
 suite("test_tz_streamload") {
-    def dbName = "tz_streamload"
-    def tableName = "timezone"
+    def table1 = "timezone"
+    def table2 = "datetime"
 
-    sql "drop table if exists ${tableName}"
+    sql "drop table if exists ${table1}"
     sql """
-    CREATE TABLE IF NOT EXISTS ${tableName} (
+    CREATE TABLE IF NOT EXISTS ${table1} (
       `k1` datetimev2(3) NULL,
       `k2` datev2 NULL
     ) ENGINE=OLAP
@@ -32,14 +32,40 @@ suite("test_tz_streamload") {
     )
     """
 
+    sql "drop table if exists ${table2}"
+    sql """
+    CREATE TABLE ${table2} (
+        id int NULL,
+        createTime datetime NULL
+    )ENGINE=OLAP
+    UNIQUE KEY(`id`)
+    COMMENT "OLAP"
+    DISTRIBUTED BY HASH(`id`) BUCKETS 3
+    PROPERTIES (
+        "replication_num" = "1",
+        "colocate_with" = "lineitem_orders",
+        "enable_unique_key_merge_on_write" = "true"
+    );
+    """
+
     streamLoad {
-        table "${tableName}"
+        table "${table1}"
         set 'column_separator', ','
         set 'time_zone', '+02:00'
         file "test_tz_streamload.csv"
-        time 10000
+        time 20000
     }
     sql "sync"
+    qt_table1 "select * from ${table1} order by k1"
 
-    qt_all "select * from ${tableName} order by k1"
+    streamLoad {
+        table "${table2}"
+        set 'column_separator', ','
+        set 'columns', 'id,createTime,createTime=date_add(createTime, INTERVAL 
8 HOUR)'
+        // use default timezone for this
+        file "test_tz_streamload2.csv"
+        time 20000
+    }
+    sql "sync"
+    qt_table2 "select * from ${table2} order by id"
 }
diff --git 
a/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function.groovy
 
b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function.groovy
index 8d74e47d98..073c5dc725 100644
--- 
a/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function.groovy
+++ 
b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_date_function.groovy
@@ -640,4 +640,6 @@ suite("test_date_function") {
         sql "select cast('20230631' as date), cast('20230632' as date)"
         result([[null, null]])
     }
+
+    qt_sql """ select date_add("2023-08-17T01:41:18Z", interval 8 hour) """
 }
diff --git 
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy
 
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy
index ed8f4d032e..1ca3124e4c 100644
--- 
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy
+++ 
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy
@@ -715,4 +715,6 @@ suite("test_date_function") {
     
     res = sql "explain select date_trunc('2022-04-24', 'day'), 
date_trunc('1999-03-12 00:31:23', 'hour')"
     assertFalse(res.contains("date_trunc"))
+
+    qt_sql """ select date_add("2023-08-17T01:41:18Z", interval 8 hour) """
 }


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

Reply via email to