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 3bcab8bbef [feature](function) support now/current_timestamp functions 
with precision (#12219)
3bcab8bbef is described below

commit 3bcab8bbef07fe0c79e7bd35f68881b4d335668b
Author: Gabriel <gabrielleeb...@gmail.com>
AuthorDate: Thu Sep 1 14:35:12 2022 +0800

    [feature](function) support now/current_timestamp functions with precision 
(#12219)
    
    * [feature](function) support now/current_timestamp functions with precision
---
 be/src/runtime/runtime_state.cpp                   |  19 ++-
 be/src/runtime/runtime_state.h                     |   2 +
 be/src/vec/data_types/data_type_time_v2.cpp        |   9 +-
 .../function_date_or_datetime_computation.cpp      |  22 ++-
 .../function_date_or_datetime_computation.h        | 166 +++++++++++++++++----
 be/src/vec/runtime/vdatetime_value.cpp             |  25 ++++
 be/src/vec/runtime/vdatetime_value.h               |   3 +
 .../java/org/apache/doris/analysis/Analyzer.java   |   2 +
 .../apache/doris/analysis/FunctionCallExpr.java    |  13 ++
 .../apache/doris/planner/StreamLoadPlanner.java    |   2 +
 .../main/java/org/apache/doris/qe/Coordinator.java |   2 +
 .../apache/doris/rewrite/FoldConstantsRule.java    |   2 +
 gensrc/script/doris_builtins_functions.py          |   3 +
 gensrc/thrift/PaloInternalService.thrift           |   4 +-
 .../datetime_functions/test_date_function.out      |   6 +
 .../datetime_functions/test_date_function.groovy   |   8 +
 16 files changed, 244 insertions(+), 44 deletions(-)

diff --git a/be/src/runtime/runtime_state.cpp b/be/src/runtime/runtime_state.cpp
index b07a8cda87..9f272eb6cf 100644
--- a/be/src/runtime/runtime_state.cpp
+++ b/be/src/runtime/runtime_state.cpp
@@ -107,9 +107,14 @@ RuntimeState::RuntimeState(const TQueryGlobals& 
query_globals)
           _is_cancelled(false),
           _per_fragment_instance_idx(0) {
     _query_options.batch_size = DEFAULT_BATCH_SIZE;
-    if (query_globals.__isset.time_zone) {
+    if (query_globals.__isset.time_zone && query_globals.__isset.nano_seconds) 
{
         _timezone = query_globals.time_zone;
         _timestamp_ms = query_globals.timestamp_ms;
+        _nano_seconds = query_globals.nano_seconds;
+    } else if (query_globals.__isset.time_zone) {
+        _timezone = query_globals.time_zone;
+        _timestamp_ms = query_globals.timestamp_ms;
+        _nano_seconds = 0;
     } else if (!query_globals.now_string.empty()) {
         _timezone = TimezoneUtils::default_time_zone;
         DateTimeValue dt;
@@ -117,10 +122,12 @@ RuntimeState::RuntimeState(const TQueryGlobals& 
query_globals)
         int64_t timestamp;
         dt.unix_timestamp(&timestamp, _timezone);
         _timestamp_ms = timestamp * 1000;
+        _nano_seconds = 0;
     } else {
         //Unit test may set into here
         _timezone = TimezoneUtils::default_time_zone;
         _timestamp_ms = 0;
+        _nano_seconds = 0;
     }
     TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
 }
@@ -135,6 +142,7 @@ RuntimeState::RuntimeState()
     _query_options.batch_size = DEFAULT_BATCH_SIZE;
     _timezone = TimezoneUtils::default_time_zone;
     _timestamp_ms = 0;
+    _nano_seconds = 0;
     TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
     _exec_env = ExecEnv::GetInstance();
 }
@@ -161,9 +169,14 @@ Status RuntimeState::init(const TUniqueId& 
fragment_instance_id, const TQueryOpt
                           const TQueryGlobals& query_globals, ExecEnv* 
exec_env) {
     _fragment_instance_id = fragment_instance_id;
     _query_options = query_options;
-    if (query_globals.__isset.time_zone) {
+    if (query_globals.__isset.time_zone && query_globals.__isset.nano_seconds) 
{
+        _timezone = query_globals.time_zone;
+        _timestamp_ms = query_globals.timestamp_ms;
+        _nano_seconds = query_globals.nano_seconds;
+    } else if (query_globals.__isset.time_zone) {
         _timezone = query_globals.time_zone;
         _timestamp_ms = query_globals.timestamp_ms;
+        _nano_seconds = 0;
     } else if (!query_globals.now_string.empty()) {
         _timezone = TimezoneUtils::default_time_zone;
         DateTimeValue dt;
@@ -171,10 +184,12 @@ Status RuntimeState::init(const TUniqueId& 
fragment_instance_id, const TQueryOpt
         int64_t timestamp;
         dt.unix_timestamp(&timestamp, _timezone);
         _timestamp_ms = timestamp * 1000;
+        _nano_seconds = 0;
     } else {
         //Unit test may set into here
         _timezone = TimezoneUtils::default_time_zone;
         _timestamp_ms = 0;
+        _nano_seconds = 0;
     }
     TimezoneUtils::find_cctz_time_zone(_timezone, _timezone_obj);
 
diff --git a/be/src/runtime/runtime_state.h b/be/src/runtime/runtime_state.h
index 9f2cff712c..8b49f0a161 100644
--- a/be/src/runtime/runtime_state.h
+++ b/be/src/runtime/runtime_state.h
@@ -114,6 +114,7 @@ public:
     int num_scanner_threads() const { return 
_query_options.num_scanner_threads; }
     TQueryType::type query_type() const { return _query_options.query_type; }
     int64_t timestamp_ms() const { return _timestamp_ms; }
+    int32_t nano_seconds() const { return _nano_seconds; }
     const std::string& timezone() const { return _timezone; }
     const cctz::time_zone& timezone_obj() const { return _timezone_obj; }
     const std::string& user() const { return _user; }
@@ -428,6 +429,7 @@ private:
 
     //Query-global timestamp_ms
     int64_t _timestamp_ms;
+    int32_t _nano_seconds;
     std::string _timezone;
     cctz::time_zone _timezone_obj;
 
diff --git a/be/src/vec/data_types/data_type_time_v2.cpp 
b/be/src/vec/data_types/data_type_time_v2.cpp
index 04e1789a45..a42c9be4aa 100644
--- a/be/src/vec/data_types/data_type_time_v2.cpp
+++ b/be/src/vec/data_types/data_type_time_v2.cpp
@@ -90,9 +90,10 @@ std::string DataTypeDateTimeV2::to_string(const IColumn& 
column, size_t row_num)
                     .get_data()[row_num];
     DateV2Value<DateTimeV2ValueType> val =
             binary_cast<UInt64, DateV2Value<DateTimeV2ValueType>>(int_val);
-    std::stringstream ss;
-    ss << val;
-    return ss.str();
+
+    char buf[64];
+    char* pos = val.to_string(buf, scale_);
+    return std::string(buf, pos - buf - 1);
 }
 
 void DataTypeDateTimeV2::to_string(const IColumn& column, size_t row_num,
@@ -104,7 +105,7 @@ void DataTypeDateTimeV2::to_string(const IColumn& column, 
size_t row_num,
             binary_cast<UInt64, DateV2Value<DateTimeV2ValueType>>(int_val);
 
     char buf[64];
-    char* pos = value.to_string(buf);
+    char* pos = value.to_string(buf, scale_);
     // DateTime to_string the end is /0
     ostr.write(buf, pos - buf - 1);
 }
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.cpp 
b/be/src/vec/functions/function_date_or_datetime_computation.cpp
index 11d773433e..f63b3d8be3 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.cpp
+++ b/be/src/vec/functions/function_date_or_datetime_computation.cpp
@@ -205,12 +205,22 @@ struct LocalTimestampFunctionName {
     static constexpr auto name = "localtimestamp";
 };
 
-using FunctionNow = 
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName>>;
+using FunctionNow = 
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName, false>>;
 using FunctionCurrentTimestamp =
-        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName>>;
-using FunctionLocalTime = 
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName>>;
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName, 
false>>;
+using FunctionLocalTime =
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName, 
false>>;
 using FunctionLocalTimestamp =
-        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName>>;
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName, 
false>>;
+
+using FunctionNowWithPrecision =
+        FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<NowFunctionName, 
true>>;
+using FunctionCurrentTimestampWithPrecision =
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<CurrentTimestampFunctionName, 
true>>;
+using FunctionLocalTimeWithPrecision =
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimeFunctionName, true>>;
+using FunctionLocalTimestampWithPrecision =
+        
FunctionCurrentDateOrDateTime<CurrentDateTimeImpl<LocalTimestampFunctionName, 
true>>;
 
 struct CurDateFunctionName {
     static constexpr auto name = "curdate";
@@ -337,6 +347,10 @@ void 
register_function_date_time_computation(SimpleFunctionFactory& factory) {
     factory.register_function<FunctionCurrentTimestamp>();
     factory.register_function<FunctionLocalTime>();
     factory.register_function<FunctionLocalTimestamp>();
+    factory.register_function<FunctionNowWithPrecision>();
+    factory.register_function<FunctionCurrentTimestampWithPrecision>();
+    factory.register_function<FunctionLocalTimeWithPrecision>();
+    factory.register_function<FunctionLocalTimestampWithPrecision>();
     factory.register_function(CurrentDateFunctionName::name,
                               &createCurrentDateFunctionBuilderFunction);
     factory.register_function(CurDateFunctionName::name, 
&createCurDateFunctionBuilderFunction);
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h 
b/be/src/vec/functions/function_date_or_datetime_computation.h
index 8a2d57292f..4d1002ed0e 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -579,6 +579,9 @@ public:
 template <typename FunctionImpl>
 class FunctionCurrentDateOrDateTime : public IFunction {
 public:
+    static constexpr bool has_variadic_argument =
+            
!std::is_void_v<decltype(has_variadic_argument_types(std::declval<FunctionImpl>()))>;
+
     static constexpr auto name = FunctionImpl::name;
     static FunctionPtr create() { return 
std::make_shared<FunctionCurrentDateOrDateTime>(); }
 
@@ -590,51 +593,148 @@ public:
         return std::make_shared<typename FunctionImpl::ReturnType>();
     }
 
+    bool is_variadic() const override { return true; }
+
+    DataTypes get_variadic_argument_types_impl() const override {
+        if constexpr (has_variadic_argument) return 
FunctionImpl::get_variadic_argument_types();
+        return {};
+    }
+
     Status execute_impl(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
                         size_t result, size_t input_rows_count) override {
-        DCHECK(arguments.empty());
-        return FunctionImpl::execute(context, block, result, input_rows_count);
+        return FunctionImpl::execute(context, block, arguments, result, 
input_rows_count);
     }
 };
 
-template <typename FunctionName>
+template <typename FunctionName, bool WithPrecision>
 struct CurrentDateTimeImpl {
-    using ReturnType = DataTypeDateTime;
     static constexpr auto name = FunctionName::name;
-    static Status execute(FunctionContext* context, Block& block, size_t 
result,
-                          size_t input_rows_count) {
+    using ReturnType = std::conditional_t<WithPrecision, DataTypeDateTimeV2, 
DataTypeDateTime>;
+
+    static DataTypes get_variadic_argument_types() {
+        if constexpr (WithPrecision) {
+            return {std::make_shared<DataTypeInt32>()};
+        } else {
+            return {};
+        }
+    }
+
+    static Status execute(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                          size_t result, size_t input_rows_count) {
         WhichDataType 
which(remove_nullable(block.get_by_position(result).type));
-        if (which.is_date_time_v2()) {
-            return executeImpl<DateV2Value<DateTimeV2ValueType>, 
UInt64>(context, block, result,
-                                                                         
input_rows_count);
-        } else if (which.is_date_v2()) {
-            return executeImpl<DateV2Value<DateV2ValueType>, UInt32>(context, 
block, result,
-                                                                     
input_rows_count);
+        if constexpr (WithPrecision) {
+            DCHECK(which.is_date_time_v2() || which.is_date_v2());
+            if (which.is_date_time_v2()) {
+                return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(
+                        context, block, arguments, result, input_rows_count);
+            } else {
+                return executeImpl<DateV2Value<DateV2ValueType>, 
UInt32>(context, block, arguments,
+                                                                         
result, input_rows_count);
+            }
         } else {
-            return executeImpl<VecDateTimeValue, Int64>(context, block, 
result, input_rows_count);
+            if (which.is_date_time_v2()) {
+                return executeImpl<DateV2Value<DateTimeV2ValueType>, UInt64>(
+                        context, block, arguments, result, input_rows_count);
+            } else if (which.is_date_v2()) {
+                return executeImpl<DateV2Value<DateV2ValueType>, 
UInt32>(context, block, arguments,
+                                                                         
result, input_rows_count);
+            } else {
+                return executeImpl<VecDateTimeValue, Int64>(context, block, 
arguments, result,
+                                                            input_rows_count);
+            }
         }
     }
 
     template <typename DateValueType, typename NativeType>
-    static Status executeImpl(FunctionContext* context, Block& block, size_t 
result,
+    static Status executeImpl(FunctionContext* context, Block& block,
+                              const ColumnNumbers& arguments, size_t result,
                               size_t input_rows_count) {
         auto col_to = ColumnVector<NativeType>::create();
         DateValueType dtv;
-        if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
-                              context->impl()->state()->timezone_obj())) {
-            if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
-                
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
-            }
-            auto date_packed_int = binary_cast<DateValueType, NativeType>(dtv);
-            for (int i = 0; i < input_rows_count; i++) {
-                col_to->insert_data(
-                        const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
+        if constexpr (WithPrecision) {
+            if (const ColumnConst* const_column = 
check_and_get_column<ColumnConst>(
+                        block.get_by_position(arguments[0]).column)) {
+                int scale = const_column->get_int(0);
+                if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() 
/ 1000,
+                                      context->impl()->state()->nano_seconds(),
+                                      
context->impl()->state()->timezone_obj(), scale)) {
+                    if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
+                        
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
+                    }
+                    auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                    for (int i = 0; i < input_rows_count; i++) {
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
+                    }
+                } else {
+                    auto invalid_val = 0;
+                    for (int i = 0; i < input_rows_count; i++) {
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                    }
+                }
+            } else if (const ColumnNullable* nullable_column = 
check_and_get_column<ColumnNullable>(
+                               block.get_by_position(arguments[0]).column)) {
+                const auto& null_map = nullable_column->get_null_map_data();
+                const auto& nested_column = 
nullable_column->get_nested_column_ptr();
+                for (int i = 0; i < input_rows_count; i++) {
+                    if (!null_map[i] &&
+                        
dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
+                                          
context->impl()->state()->nano_seconds(),
+                                          
context->impl()->state()->timezone_obj(),
+                                          nested_column->get64(i))) {
+                        if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
+                            
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
+                        }
+                        auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
+                    } else {
+                        auto invalid_val = 0;
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                    }
+                }
+            } else {
+                auto& int_column = block.get_by_position(arguments[0]).column;
+                for (int i = 0; i < input_rows_count; i++) {
+                    if 
(dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
+                                          
context->impl()->state()->nano_seconds(),
+                                          
context->impl()->state()->timezone_obj(),
+                                          int_column->get64(i))) {
+                        if constexpr (std::is_same_v<DateValueType, 
VecDateTimeValue>) {
+                            
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
+                        }
+                        auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)),
+                                0);
+                    } else {
+                        auto invalid_val = 0;
+                        col_to->insert_data(
+                                const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                    }
+                }
             }
         } else {
-            auto invalid_val = 0;
-            for (int i = 0; i < input_rows_count; i++) {
-                col_to->insert_data(const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)),
-                                    0);
+            if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 
1000,
+                                  context->impl()->state()->timezone_obj())) {
+                if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) 
{
+                    
reinterpret_cast<DateValueType*>(&dtv)->set_type(TIME_DATETIME);
+                }
+                auto date_packed_int = binary_cast<DateValueType, 
NativeType>(dtv);
+                for (int i = 0; i < input_rows_count; i++) {
+                    col_to->insert_data(
+                            const_cast<const 
char*>(reinterpret_cast<char*>(&date_packed_int)), 0);
+                }
+            } else {
+                auto invalid_val = 0;
+                for (int i = 0; i < input_rows_count; i++) {
+                    col_to->insert_data(
+                            const_cast<const 
char*>(reinterpret_cast<char*>(&invalid_val)), 0);
+                }
             }
         }
         block.get_by_position(result).column = std::move(col_to);
@@ -646,8 +746,8 @@ template <typename FunctionName, typename DateType, 
typename NativeType>
 struct CurrentDateImpl {
     using ReturnType = DateType;
     static constexpr auto name = FunctionName::name;
-    static Status execute(FunctionContext* context, Block& block, size_t 
result,
-                          size_t input_rows_count) {
+    static Status execute(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                          size_t result, size_t input_rows_count) {
         auto col_to = ColumnVector<NativeType>::create();
         if constexpr (std::is_same_v<DateType, DataTypeDateV2>) {
             DateV2Value<DateV2ValueType> dtv;
@@ -694,8 +794,8 @@ template <typename FunctionName>
 struct CurrentTimeImpl {
     using ReturnType = DataTypeFloat64;
     static constexpr auto name = FunctionName::name;
-    static Status execute(FunctionContext* context, Block& block, size_t 
result,
-                          size_t input_rows_count) {
+    static Status execute(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                          size_t result, size_t input_rows_count) {
         auto col_to = ColumnVector<Float64>::create();
         VecDateTimeValue dtv;
         if (dtv.from_unixtime(context->impl()->state()->timestamp_ms() / 1000,
@@ -719,8 +819,8 @@ struct CurrentTimeImpl {
 struct UtcTimestampImpl {
     using ReturnType = DataTypeDateTime;
     static constexpr auto name = "utc_timestamp";
-    static Status execute(FunctionContext* context, Block& block, size_t 
result,
-                          size_t input_rows_count) {
+    static Status execute(FunctionContext* context, Block& block, const 
ColumnNumbers& arguments,
+                          size_t result, size_t input_rows_count) {
         WhichDataType 
which(remove_nullable(block.get_by_position(result).type));
         if (which.is_date_time_v2()) {
             return executeImpl<DateV2Value<DateTimeV2ValueType>, 
UInt64>(context, block, result,
diff --git a/be/src/vec/runtime/vdatetime_value.cpp 
b/be/src/vec/runtime/vdatetime_value.cpp
index 5ac700d111..819952330d 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -2607,6 +2607,31 @@ bool DateV2Value<T>::from_unixtime(int64_t timestamp, 
const cctz::time_zone& ctz
     return true;
 }
 
+template <typename T>
+bool DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
+                                   const std::string& timezone, const int 
scale) {
+    cctz::time_zone ctz;
+    if (!TimezoneUtils::find_cctz_time_zone(timezone, ctz)) {
+        return false;
+    }
+    return from_unixtime(timestamp, nano_seconds, ctz, scale);
+}
+
+template <typename T>
+bool DateV2Value<T>::from_unixtime(int64_t timestamp, int32_t nano_seconds,
+                                   const cctz::time_zone& ctz, const int 
scale) {
+    static const cctz::time_point<cctz::sys_seconds> epoch =
+            std::chrono::time_point_cast<cctz::sys_seconds>(
+                    std::chrono::system_clock::from_time_t(0));
+    cctz::time_point<cctz::sys_seconds> t = epoch + cctz::seconds(timestamp);
+
+    const auto tp = cctz::convert(t, ctz);
+
+    set_time(tp.year(), tp.month(), tp.day(), tp.hour(), tp.minute(), 
tp.second(),
+             nano_seconds / std::pow(10, 9 - scale) * std::pow(10, 6 - scale));
+    return true;
+}
+
 template <typename T>
 const char* DateV2Value<T>::month_name() const {
     if (date_v2_value_.month_ < 1 || date_v2_value_.month_ > 12) {
diff --git a/be/src/vec/runtime/vdatetime_value.h 
b/be/src/vec/runtime/vdatetime_value.h
index e472d14e81..42ce3a173c 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -933,6 +933,9 @@ public:
     bool from_unixtime(int64_t, const std::string& timezone);
     bool from_unixtime(int64_t, const cctz::time_zone& ctz);
 
+    bool from_unixtime(int64_t, int32_t, const std::string& timezone, const 
int scale);
+    bool from_unixtime(int64_t, int32_t, const cctz::time_zone& ctz, const int 
scale);
+
     bool operator==(const DateV2Value<T>& other) const {
         // NOTE: This is not same with MySQL.
         // MySQL convert both to int with left value type and then compare
diff --git a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
index 5babfc90c4..079f3affd0 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/Analyzer.java
@@ -81,6 +81,7 @@ import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Calendar;
 import java.util.Collection;
@@ -550,6 +551,7 @@ public class Analyzer {
         Calendar currentDate = Calendar.getInstance();
         String nowStr = formatter.format(currentDate.getTime());
         queryGlobals.setNowString(nowStr);
+        queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
         return queryGlobals;
     }
 
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java 
b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
index 0505873c0e..1f2af19394 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/analysis/FunctionCallExpr.java
@@ -82,6 +82,10 @@ public class FunctionCallExpr extends Expr {
                     .addAll(DECIMAL_SAME_TYPE_SET)
                     .addAll(DECIMAL_WIDER_TYPE_SET)
                     .addAll(STDDEV_FUNCTION_SET).build();
+
+    private static final ImmutableSet<String> TIME_FUNCTIONS_WITH_PRECISION =
+            new ImmutableSortedSet.Builder(String.CASE_INSENSITIVE_ORDER)
+                    
.add("now").add("current_timestamp").add("localtime").add("localtimestamp").build();
     private static final int STDDEV_DECIMAL_SCALE = 9;
     private static final String ELEMENT_EXTRACT_FN_NAME = "%element_extract%";
 
@@ -1036,6 +1040,15 @@ public class FunctionCallExpr extends Expr {
             }
         }
 
+        if 
(TIME_FUNCTIONS_WITH_PRECISION.contains(fnName.getFunction().toLowerCase())
+                && fn != null && fn.getReturnType().isDatetimeV2()) {
+            if (children.size() == 1 && children.get(0) instanceof IntLiteral) 
{
+                fn.setReturnType(ScalarType.createDatetimeV2Type((int) 
((IntLiteral) children.get(0)).getLongValue()));
+            } else if (children.size() == 1) {
+                fn.setReturnType(ScalarType.createDatetimeV2Type(6));
+            }
+        }
+
         if (fnName.getFunction().equalsIgnoreCase("from_unixtime")
                 || fnName.getFunction().equalsIgnoreCase("date_format")) {
             // if has only one child, it has default time format: yyyy-MM-dd 
HH:mm:ss.SSSSSS
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/planner/StreamLoadPlanner.java 
b/fe/fe-core/src/main/java/org/apache/doris/planner/StreamLoadPlanner.java
index 0398fa43e2..0c0a41be24 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/planner/StreamLoadPlanner.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/planner/StreamLoadPlanner.java
@@ -61,6 +61,7 @@ import org.apache.logging.log4j.Logger;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.Date;
 import java.util.List;
 import java.util.Map;
@@ -204,6 +205,7 @@ public class StreamLoadPlanner {
         queryGlobals.setTimestampMs(System.currentTimeMillis());
         queryGlobals.setTimeZone(taskInfo.getTimezone());
         queryGlobals.setLoadZeroTolerance(taskInfo.getMaxFilterRatio() <= 0.0);
+        queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
 
         params.setQueryGlobals(queryGlobals);
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java 
b/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
index b409043eae..1d4d6f2b99 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/qe/Coordinator.java
@@ -115,6 +115,7 @@ import org.jetbrains.annotations.NotNull;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Date;
@@ -251,6 +252,7 @@ public class Coordinator {
 
         this.queryGlobals.setNowString(DATE_FORMAT.format(new Date()));
         this.queryGlobals.setTimestampMs(System.currentTimeMillis());
+        this.queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
         this.queryGlobals.setLoadZeroTolerance(false);
         if (context.getSessionVariable().getTimeZone().equals("CST")) {
             this.queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java 
b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
index 45d1786fc7..16dd084886 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/rewrite/FoldConstantsRule.java
@@ -55,6 +55,7 @@ import org.apache.logging.log4j.Logger;
 
 import java.text.DateFormat;
 import java.text.SimpleDateFormat;
+import java.time.LocalDateTime;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
@@ -353,6 +354,7 @@ public class FoldConstantsRule implements ExprRewriteRule {
             TQueryGlobals queryGlobals = new TQueryGlobals();
             queryGlobals.setNowString(DATE_FORMAT.format(new Date()));
             queryGlobals.setTimestampMs(System.currentTimeMillis());
+            queryGlobals.setNanoSeconds(LocalDateTime.now().getNano());
             queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
             if (context.getSessionVariable().getTimeZone().equals("CST")) {
                 queryGlobals.setTimeZone(TimeUtils.DEFAULT_TIME_ZONE);
diff --git a/gensrc/script/doris_builtins_functions.py 
b/gensrc/script/doris_builtins_functions.py
index ea53ea02c0..0ecde878c1 100755
--- a/gensrc/script/doris_builtins_functions.py
+++ b/gensrc/script/doris_builtins_functions.py
@@ -428,6 +428,9 @@ visible_functions = [
     [['now', 'current_timestamp', 'localtime', 'localtimestamp'], 'DATETIME', 
[],
         '_ZN5doris18TimestampFunctions3nowEPN9doris_udf15FunctionContextE',
         '', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
+    [['now', 'current_timestamp', 'localtime', 'localtimestamp'], 
'DATETIMEV2', ['INT'],
+     '_ZN5doris18TimestampFunctions3nowEPN9doris_udf15FunctionContextE',
+     '', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
     [['curtime', 'current_time'], 'TIME', [],
         '_ZN5doris18TimestampFunctions7curtimeEPN9doris_udf15FunctionContextE',
         '', '', 'vec', 'ALWAYS_NOT_NULLABLE'],
diff --git a/gensrc/thrift/PaloInternalService.thrift 
b/gensrc/thrift/PaloInternalService.thrift
index 94f61376d4..c1c9f97d07 100644
--- a/gensrc/thrift/PaloInternalService.thrift
+++ b/gensrc/thrift/PaloInternalService.thrift
@@ -260,7 +260,9 @@ struct TQueryGlobals {
   3: optional string time_zone
 
   // Set to true if in a load plan, the max_filter_ratio is 0.0
-  4: optional bool load_zero_tolerance = false;
+  4: optional bool load_zero_tolerance = false
+
+  5: optional i32 nano_seconds
 }
 
 
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 b6c261cb03..765a203061 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
@@ -383,3 +383,9 @@ true
 -- !sql --
 2018-04-02T15:03:28
 
+-- !sql --
+19     19      21      22      23      24      25      26
+
+-- !sql --
+19     19      21      22      23      24      25      26
+
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 7b2894c3f6..668d880b14 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
@@ -303,4 +303,12 @@ suite("test_date_function") {
     qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e 
%H:%i:%s %Y'); """
     qt_sql """ select STR_TO_DATE('Tue Jul 12 20:00:45 CST 2022', '%a %b %e %T 
CST %Y'); """
     qt_sql """ select STR_TO_DATE('2018-4-2 15:3:28','%Y-%m-%d %H:%i:%s'); """
+
+    qt_sql """ select length(cast(now() as string)), length(cast(now(0) as 
string)), length(cast(now(1) as string)),
+                      length(cast(now(2) as string)), length(cast(now(3) as 
string)), length(cast(now(4) as string)),
+                      length(cast(now(5) as string)), length(cast(now(6) as 
string)); """
+    qt_sql """ select length(cast(current_timestamp() as string)), 
length(cast(current_timestamp(0) as string)),
+                      length(cast(current_timestamp(1) as string)), 
length(cast(current_timestamp(2) as string)),
+                      length(cast(current_timestamp(3) as string)), 
length(cast(current_timestamp(4) as string)),
+                      length(cast(current_timestamp(5) as string)), 
length(cast(current_timestamp(6) as string)); """
 }


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

Reply via email to