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(×tamp, _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(×tamp, _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