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 <[email protected]>
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: [email protected]
For additional commands, e-mail: [email protected]