From 30c4719f7bdc990e98252c14713e13dff9ed69f9 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Wed, 21 Sep 2022 12:58:57 +0000 Subject: [PATCH 01/21] Add FunctionDateOrDateTimeToDateTimeOrDateTime64; function toStartOfHour works --- src/Functions/DateTimeTransforms.h | 5 + ...tionDateOrDateTimeToDateTimeOrDateTime64.h | 93 +++++++++++++++++++ src/Functions/toStartOfHour.cpp | 4 +- 3 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index fbe8e4bfcfe..aa814c189d7 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -654,6 +654,11 @@ struct ToStartOfHourImpl return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toStartOfHour(Int64(t.whole)), 0}; + } + using FactorTransform = ZeroTransform; }; diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h new file mode 100644 index 00000000000..b7825f9b716 --- /dev/null +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -0,0 +1,93 @@ +#pragma once +#include + +namespace DB +{ + +namespace ErrorCodes +{ + extern const int ILLEGAL_TYPE_OF_ARGUMENT; +} + +template +class FunctionDateOrDateTimeToDateTimeOrDateTime64 : public IFunctionDateOrDateTime, WithContext +{ +public: + const bool enable_extended_results_for_datetime_functions = false; + + static FunctionPtr create(ContextPtr context_) + { + return std::make_shared(context_); + } + + explicit FunctionDateOrDateTimeToDateTimeOrDateTime64(ContextPtr context_) + : WithContext(context_) + , enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) + { + } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + this->checkArguments(arguments, /*is_result_type_date_or_date32*/ true); + + const IDataType * from_type = arguments[0].type.get(); + WhichDataType which(from_type); + + /// If the time zone is specified but empty, throw an exception. + /// only validate the time_zone part if the number of arguments is 2. + if ((which.isDateTime() || which.isDateTime64()) && arguments.size() == 2 + && extractTimeZoneNameFromFunctionArguments(arguments, 1, 0).empty()) + throw Exception( + "Function " + this->getName() + " supports a 2nd argument (optional) that must be non-empty and be a valid time zone", + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + + if ((which.isDate32() || which.isDateTime64()) && enable_extended_results_for_datetime_functions) + { + Int64 scale = DataTypeDateTime64::default_scale; + if (which.isDateTime64()) + { + if (const auto * dt64 = checkAndGetDataType(arguments[0].type.get())) + scale = dt64->getScale(); + } + return std::make_shared(scale, extractTimeZoneNameFromFunctionArguments(arguments, 1, 0)); + } + else + return std::make_shared(); + } + + ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override + { + const IDataType * from_type = arguments[0].type.get(); + WhichDataType which(from_type); + // if (which.isDate()) + // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + // else if (which.isDate32()) + // if (enable_extended_results_for_datetime_functions) + // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + // else + // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + // else + if (which.isDateTime()) + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + else if (which.isDateTime64()) + { + const auto scale = static_cast(from_type)->getScale(); + + const TransformDateTime64 transformer(scale); + if (enable_extended_results_for_datetime_functions) + { + const auto result_scale = static_cast(result_type.get())->getScale(); + assert(result_scale>=0); + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); + } + else + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); + } + else + throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), + ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + +}; + +} diff --git a/src/Functions/toStartOfHour.cpp b/src/Functions/toStartOfHour.cpp index d12b37ab7b6..fcd5cb8b85b 100644 --- a/src/Functions/toStartOfHour.cpp +++ b/src/Functions/toStartOfHour.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfHour = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfHour = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfHour) { From f6ebd94ce1b638e436e776343a7a454c104ade79 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 22 Sep 2022 07:07:04 +0000 Subject: [PATCH 02/21] Add execute_extended_result for Date32 argument --- src/Functions/DateTimeTransforms.h | 5 +++++ ...tionDateOrDateTimeToDateTimeOrDateTime64.h | 20 ++++++++----------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index aa814c189d7..3b305a86d97 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -659,6 +659,11 @@ struct ToStartOfHourImpl return {time_zone.toStartOfHour(Int64(t.whole)), 0}; } + static inline UInt32 execute_extended_result(Int32, const DateLUTImpl &) + { + return dateIsNotSupported(name); + } + using FactorTransform = ZeroTransform; }; diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h index b7825f9b716..974f3e14d2e 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -59,14 +59,14 @@ public: { const IDataType * from_type = arguments[0].type.get(); WhichDataType which(from_type); - // if (which.isDate()) - // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); - // else if (which.isDate32()) - // if (enable_extended_results_for_datetime_functions) - // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); - // else - // return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); - // else + if (which.isDate()) + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + else if (which.isDate32()) + if (enable_extended_results_for_datetime_functions) + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + else + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + else if (which.isDateTime()) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDateTime64()) @@ -75,11 +75,7 @@ public: const TransformDateTime64 transformer(scale); if (enable_extended_results_for_datetime_functions) - { - const auto result_scale = static_cast(result_type.get())->getScale(); - assert(result_scale>=0); return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); - } else return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); } From 49b0da0273234240bb1b2cd62f5f98acb5fb7321 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 22 Sep 2022 07:15:03 +0000 Subject: [PATCH 03/21] Add date32IsNotSupported() --- src/Functions/DateTimeTransforms.h | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 3b305a86d97..ac2768c9501 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -46,6 +46,11 @@ namespace ErrorCodes throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } + static inline Int64 date32IsNotSupported(const char * name) + { + throw Exception("Illegal type Date32 of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + } + /// This factor transformation will say that the function is monotone everywhere. struct ZeroTransform { @@ -659,9 +664,9 @@ struct ToStartOfHourImpl return {time_zone.toStartOfHour(Int64(t.whole)), 0}; } - static inline UInt32 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) { - return dateIsNotSupported(name); + return date32IsNotSupported(name); } using FactorTransform = ZeroTransform; From 4ddd6f3c607bf33b6c6de682063c8a229cea474d Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 22 Sep 2022 09:19:22 +0000 Subject: [PATCH 04/21] Fix timeSlot(); partial fix StartOfDay --- src/Functions/DateTimeTransforms.h | 26 ++++++++++++++++++++++++-- src/Functions/timeSlot.cpp | 4 ++-- src/Functions/toStartOfDay.cpp | 4 ++-- 3 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index ac2768c9501..bfae119b18f 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -113,7 +113,6 @@ struct ToStartOfDayImpl { static constexpr auto name = "toStartOfDay"; - //TODO: right now it is hardcoded to produce DateTime only, needs fixing later. See date_and_time_type_details::ResultDataTypeMap for deduction of result type example. static inline UInt32 execute(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { if (t.whole < 0 || (t.whole >= 0 && t.fractional < 0)) @@ -141,6 +140,19 @@ struct ToStartOfDayImpl auto date_time = time_zone.fromDayNum(ExtendedDayNum(d)); return date_time < 0xffffffff ? date_time : time_zone.toDate(0xffffffff); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toDate(t.whole), 0}; + } + static inline Int64 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.fromDayNum(ExtendedDayNum(d)); + } + // static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & ) + // { + // // return time_zone.fromDayNum(ExtendedDayNum(d)); + // return {t.whole, 0}; + // } using FactorTransform = ZeroTransform; }; @@ -629,6 +641,16 @@ struct TimeSlotImpl return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) + { + return {t.whole / 1800 * 1800, 0}; + } + + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + { + return date32IsNotSupported(name); + } + using FactorTransform = ZeroTransform; }; @@ -661,7 +683,7 @@ struct ToStartOfHourImpl static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { - return {time_zone.toStartOfHour(Int64(t.whole)), 0}; + return {time_zone.toStartOfHour(t.whole), 0}; } static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) diff --git a/src/Functions/timeSlot.cpp b/src/Functions/timeSlot.cpp index 697d2234db2..aca37bd66db 100644 --- a/src/Functions/timeSlot.cpp +++ b/src/Functions/timeSlot.cpp @@ -1,14 +1,14 @@ #include #include #include -#include +#include #include namespace DB { -using FunctionTimeSlot = FunctionDateOrDateTimeToSomething; +using FunctionTimeSlot = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(TimeSlot) { diff --git a/src/Functions/toStartOfDay.cpp b/src/Functions/toStartOfDay.cpp index 0f3304c2283..6b9dddb5e46 100644 --- a/src/Functions/toStartOfDay.cpp +++ b/src/Functions/toStartOfDay.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfDay = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfDay = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfDay) { From cdd20241bfe17ea763d7f7c333252ff4e5e27e43 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 22 Sep 2022 13:16:46 +0000 Subject: [PATCH 05/21] Finish toStartOfDay; fix toStartOfMinute --- src/Common/DateLUTImpl.h | 2 +- src/Functions/DateTimeTransforms.h | 15 +++++++++------ src/Functions/toStartOfMinute.cpp | 4 ++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Common/DateLUTImpl.h b/src/Common/DateLUTImpl.h index 564d09aff6e..d052d2a7694 100644 --- a/src/Common/DateLUTImpl.h +++ b/src/Common/DateLUTImpl.h @@ -1030,7 +1030,7 @@ public: template DateOrTime toStartOfMinuteInterval(DateOrTime t, UInt64 minutes) const { - UInt64 divisor = 60 * minutes; + Int64 divisor = 60 * minutes; if (likely(offset_is_whole_number_of_minutes_during_epoch)) { if (likely(t >= 0)) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index bfae119b18f..ecd1264fbe8 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -146,13 +146,8 @@ struct ToStartOfDayImpl } static inline Int64 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) { - return time_zone.fromDayNum(ExtendedDayNum(d)); + return time_zone.fromDayNum(ExtendedDayNum(d)) * DecimalUtils::scaleMultiplier(DataTypeDateTime64::default_scale); } - // static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & ) - // { - // // return time_zone.fromDayNum(ExtendedDayNum(d)); - // return {t.whole, 0}; - // } using FactorTransform = ZeroTransform; }; @@ -373,6 +368,14 @@ struct ToStartOfMinuteImpl { return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toStartOfMinute(t.whole), 0}; + } + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + { + return date32IsNotSupported(name); + } using FactorTransform = ZeroTransform; }; diff --git a/src/Functions/toStartOfMinute.cpp b/src/Functions/toStartOfMinute.cpp index dddfaee93ec..24f00300022 100644 --- a/src/Functions/toStartOfMinute.cpp +++ b/src/Functions/toStartOfMinute.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfMinute = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfMinute = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfMinute) { From 348f28a3e7cd1a22c9108404b0e47f56272c9e45 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 22 Sep 2022 13:30:40 +0000 Subject: [PATCH 06/21] Fix toStartOfFiveMinutes, toStartOfTenMinutes, toStartOfFifteenMinutes --- src/Functions/DateTimeTransforms.h | 24 +++++++++++++++++++++++ src/Functions/toStartOfFifteenMinutes.cpp | 4 ++-- src/Functions/toStartOfFiveMinutes.cpp | 4 ++-- src/Functions/toStartOfTenMinutes.cpp | 4 ++-- 4 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index ecd1264fbe8..15d92c49990 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -566,6 +566,14 @@ struct ToStartOfFiveMinutesImpl { return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toStartOfFiveMinutes(t.whole), 0}; + } + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + { + return date32IsNotSupported(name); + } using FactorTransform = ZeroTransform; }; @@ -590,6 +598,14 @@ struct ToStartOfTenMinutesImpl { return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toStartOfTenMinutes(t.whole), 0}; + } + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + { + return date32IsNotSupported(name); + } using FactorTransform = ZeroTransform; }; @@ -614,6 +630,14 @@ struct ToStartOfFifteenMinutesImpl { return dateIsNotSupported(name); } + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + { + return {time_zone.toStartOfFifteenMinutes(t.whole), 0}; + } + static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + { + return date32IsNotSupported(name); + } using FactorTransform = ZeroTransform; }; diff --git a/src/Functions/toStartOfFifteenMinutes.cpp b/src/Functions/toStartOfFifteenMinutes.cpp index a103c4ff0eb..77bc7c47c4e 100644 --- a/src/Functions/toStartOfFifteenMinutes.cpp +++ b/src/Functions/toStartOfFifteenMinutes.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfFifteenMinutes = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfFifteenMinutes = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfFifteenMinutes) { diff --git a/src/Functions/toStartOfFiveMinutes.cpp b/src/Functions/toStartOfFiveMinutes.cpp index 17db95841e7..feb844d813f 100644 --- a/src/Functions/toStartOfFiveMinutes.cpp +++ b/src/Functions/toStartOfFiveMinutes.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfFiveMinutes = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfFiveMinutes = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfFiveMinutes) { diff --git a/src/Functions/toStartOfTenMinutes.cpp b/src/Functions/toStartOfTenMinutes.cpp index 8f05e080b92..02b7bf2bad0 100644 --- a/src/Functions/toStartOfTenMinutes.cpp +++ b/src/Functions/toStartOfTenMinutes.cpp @@ -1,12 +1,12 @@ #include #include -#include +#include namespace DB { -using FunctionToStartOfTenMinutes = FunctionDateOrDateTimeToSomething; +using FunctionToStartOfTenMinutes = FunctionDateOrDateTimeToDateTimeOrDateTime64; REGISTER_FUNCTION(ToStartOfTenMinutes) { From 2a92c2aae9c3a0f2e3d91c99abf6a3b86156c4f3 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Mon, 26 Sep 2022 15:26:07 +0300 Subject: [PATCH 07/21] Fix timeSlot() for DateTime64 argument --- src/Functions/DateTimeTransforms.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 15d92c49990..483393ce6f3 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -668,9 +668,9 @@ struct TimeSlotImpl return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) + static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { - return {t.whole / 1800 * 1800, 0}; + return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; } static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) From 36274baba91d0e4738cfb2cf395c2bbfdf08aeeb Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Mon, 26 Sep 2022 15:36:32 +0300 Subject: [PATCH 08/21] Code cleanup --- src/Functions/DateTimeTransforms.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 483393ce6f3..6640f632c8c 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -647,7 +647,6 @@ struct TimeSlotImpl { static constexpr auto name = "timeSlot"; - //static inline DecimalUtils::DecimalComponents execute(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) static inline UInt32 execute(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) { return t.whole / 1800 * 1800; From d50dcf331489d25de3dfac3aa4f9354372736e55 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Wed, 28 Sep 2022 12:26:20 +0000 Subject: [PATCH 09/21] Add tests for DateTime64 --- ...d_results_for_datetime_functions.reference | 32 +++++++++++++++++++ ...nded_results_for_datetime_functions.sql.j2 | 7 +++- 2 files changed, 38 insertions(+), 1 deletion(-) diff --git a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference index aa950215f59..3b33aed565d 100644 --- a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference +++ b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference @@ -26,6 +26,22 @@ toLastDayOfMonth;toDate32;true 1920-02-29 type;toLastDayOfMonth;toDate32;true Date32 toLastDayOfMonth;toDateTime64;true 1920-02-29 type;toLastDayOfMonth;toDateTime64;true Date32 +toStartOfDay;toDateTime64;true 1920-02-02 00:00:00.000 +type;toStartOfDay;toDateTime64;true DateTime64(3) +toStartOfHour;toDateTime64;true 1920-02-02 10:00:00.000 +type;toStartOfHour;toDateTime64;true DateTime64(3) +toStartOfMinute;toDateTime64;true 1920-02-02 10:23:00.000 +type;toStartOfMinute;toDateTime64;true DateTime64(3) +toStartOfFiveMinutes;toDateTime64;true 1920-02-02 10:20:00.000 +type;toStartOfFiveMinutes;toDateTime64;true DateTime64(3) +toStartOfTenMinutes;toDateTime64;true 1920-02-02 10:20:00.000 +type;toStartOfTenMinutes;toDateTime64;true DateTime64(3) +toStartOfFifteenMinutes;toDateTime64;true 1920-02-02 10:15:00.000 +type;toStartOfFifteenMinutes;toDateTime64;true DateTime64(3) +timeSlot;toDateTime64;true 1920-02-02 10:00:00.000 +type;timeSlot;toDateTime64;true DateTime64(3) +toStartOfDay;toDate32;true 1920-02-02 00:00:00.000 +type;toStartOfDay;toDate32;true DateTime64(3) toStartOfYear;toDate32;false 1970-01-01 type;toStartOfYear;toDate32;false Date toStartOfYear;toDateTime64;false 1970-01-01 @@ -54,3 +70,19 @@ toLastDayOfMonth;toDate32;false 1970-01-01 type;toLastDayOfMonth;toDate32;false Date toLastDayOfMonth;toDateTime64;false 1970-01-01 type;toLastDayOfMonth;toDateTime64;false Date +toStartOfDay;toDateTime64;false 1970-01-01 00:00:00 +type;toStartOfDay;toDateTime64;false DateTime +toStartOfHour;toDateTime64;false 1970-01-01 00:00:00 +type;toStartOfHour;toDateTime64;false DateTime +toStartOfMinute;toDateTime64;false 1970-01-01 00:00:00 +type;toStartOfMinute;toDateTime64;false DateTime +toStartOfFiveMinutes;toDateTime64;false 2056-03-09 16:48:16 +type;toStartOfFiveMinutes;toDateTime64;false DateTime +toStartOfTenMinutes;toDateTime64;false 2056-03-09 16:48:16 +type;toStartOfTenMinutes;toDateTime64;false DateTime +toStartOfFifteenMinutes;toDateTime64;false 2056-03-09 16:43:16 +type;toStartOfFifteenMinutes;toDateTime64;false DateTime +timeSlot;toDateTime64;false 2056-03-09 16:58:16 +type;timeSlot;toDateTime64;false DateTime +toStartOfDay;toDate32;false 1970-01-01 00:00:00 +type;toStartOfDay;toDate32;false DateTime diff --git a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 index 70c07c7792a..5c575b8f352 100644 --- a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 +++ b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 @@ -5,5 +5,10 @@ SELECT 'type;{{ date_fun }};toDate32;{{ option_value }}', toTypeName({{ date_fun SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3)) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} +{% for date_fun in ['toStartOfDay', 'toStartOfHour', 'toStartOfMinute', 'toStartOfFiveMinutes', 'toStartOfTenMinutes', 'toStartOfFifteenMinutes', 'timeSlot'] -%} +SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:23:33.789', 3)) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +{% endfor -%} +SELECT 'toStartOfDay;toDate32;{{ option_value }}', toStartOfDay(toDate32('1920-02-02')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;toStartOfDay;toDate32;{{ option_value }}', toTypeName(toStartOfDay(toDate32('1920-02-02'))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} - From 109c5ee1a18c1230b6941e271014fd7c5f1b0b79 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Wed, 28 Sep 2022 12:49:58 +0000 Subject: [PATCH 10/21] Update docs for DateTime64 return types. --- docs/en/operations/settings/settings.md | 8 +++++--- docs/ru/operations/settings/settings.md | 8 +++++--- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/en/operations/settings/settings.md b/docs/en/operations/settings/settings.md index dde40acb91a..bdef47099c2 100644 --- a/docs/en/operations/settings/settings.md +++ b/docs/en/operations/settings/settings.md @@ -3147,12 +3147,14 @@ Result: ## enable_extended_results_for_datetime_functions {#enable-extended-results-for-datetime-functions} -Enables or disables returning results of type `Date32` with extended range (compared to type `Date`) for functions [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) and [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). +Enables or disables returning results of type: +- `Date32` with extended range (compared to type `Date`) for functions [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) and [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). +- `DateTime64` with extended range (compared to type `DateTime`) for functions [toStartOfDay](../../sql-reference/functions/date-time-functions.md#tostartofday), [toStartOfHour](../../sql-reference/functions/date-time-functions.md#tostartofhour), [toStartOfMinute](../../sql-reference/functions/date-time-functions.md#tostartofminute), [toStartOfFiveMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffiveminutes), [toStartOfTenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoftenminutes), [toStartOfFifteenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffifteenminutes) and [timeSlot](../../sql-reference/functions/date-time-functions.md#timeslot). Possible values: -- 0 — Functions return `Date` for all types of arguments. -- 1 — Functions return `Date32` for `Date32` or `DateTime64` arguments and `Date` otherwise. +- 0 — Functions return `Date` or `DateTime` for all types of arguments. +- 1 — Functions return `Date32` or `DateTime64` for `Date32` or `DateTime64` arguments and `Date` or `DateTime` otherwise. Default value: `0`. diff --git a/docs/ru/operations/settings/settings.md b/docs/ru/operations/settings/settings.md index 0d4f0c63210..8e5ffdddf7c 100644 --- a/docs/ru/operations/settings/settings.md +++ b/docs/ru/operations/settings/settings.md @@ -3801,12 +3801,14 @@ Exception: Total regexp lengths too large. ## enable_extended_results_for_datetime_functions {#enable-extended-results-for-datetime-functions} -Включает или отключает возвращение результатов типа `Date32` с расширенным диапазоном (по сравнению с типом `Date`) для функций [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) и [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). +Включает или отключает возвращение результатов типа: +- `Date32` с расширенным диапазоном (по сравнению с типом `Date`) для функций [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) и [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). +- `DateTime64` с расширенным диапазоном (по сравнению с типом `DateTime`) для функций [toStartOfDay](../../sql-reference/functions/date-time-functions.md#tostartofday), [toStartOfHour](../../sql-reference/functions/date-time-functions.md#tostartofhour), [toStartOfMinute](../../sql-reference/functions/date-time-functions.md#tostartofminute), [toStartOfFiveMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffiveminutes), [toStartOfTenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoftenminutes), [toStartOfFifteenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffifteenminutes) и [timeSlot](../../sql-reference/functions/date-time-functions.md#timeslot). Возможные значения: -- 0 — Функции возвращают результаты типа `Date` для всех типов аргументов. -- 1 — Функции возвращают результаты типа `Date32` для аргументов типа `Date32` или `DateTime64` и возвращают `Date` в других случаях. +- 0 — Функции возвращают результаты типа `Date` или `DateTime` для всех типов аргументов. +- 1 — Функции возвращают результаты типа `Date32` или `DateTime64` для аргументов типа `Date32` или `DateTime64` и возвращают `Date` или `DateTime` в других случаях. Значение по умолчанию: `0`. From a551e8d9503e303d6e1770ccec26b4e5953b2373 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Wed, 28 Sep 2022 13:00:52 +0000 Subject: [PATCH 11/21] Fix example in documentation --- docs/ru/operations/settings/settings.md | 26 ++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/docs/ru/operations/settings/settings.md b/docs/ru/operations/settings/settings.md index 8e5ffdddf7c..3d765b03d58 100644 --- a/docs/ru/operations/settings/settings.md +++ b/docs/ru/operations/settings/settings.md @@ -3799,19 +3799,6 @@ Exception: Total regexp lengths too large. Значение по умолчанию: `1`. -## enable_extended_results_for_datetime_functions {#enable-extended-results-for-datetime-functions} - -Включает или отключает возвращение результатов типа: -- `Date32` с расширенным диапазоном (по сравнению с типом `Date`) для функций [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) и [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). -- `DateTime64` с расширенным диапазоном (по сравнению с типом `DateTime`) для функций [toStartOfDay](../../sql-reference/functions/date-time-functions.md#tostartofday), [toStartOfHour](../../sql-reference/functions/date-time-functions.md#tostartofhour), [toStartOfMinute](../../sql-reference/functions/date-time-functions.md#tostartofminute), [toStartOfFiveMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffiveminutes), [toStartOfTenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoftenminutes), [toStartOfFifteenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffifteenminutes) и [timeSlot](../../sql-reference/functions/date-time-functions.md#timeslot). - -Возможные значения: - -- 0 — Функции возвращают результаты типа `Date` или `DateTime` для всех типов аргументов. -- 1 — Функции возвращают результаты типа `Date32` или `DateTime64` для аргументов типа `Date32` или `DateTime64` и возвращают `Date` или `DateTime` в других случаях. - -Значение по умолчанию: `0`. - **Пример** Запрос: @@ -3834,6 +3821,19 @@ SELECT * FROM positional_arguments ORDER BY 2,3; └─────┴─────┴───────┘ ``` +## enable_extended_results_for_datetime_functions {#enable-extended-results-for-datetime-functions} + +Включает или отключает возвращение результатов типа: +- `Date32` с расширенным диапазоном (по сравнению с типом `Date`) для функций [toStartOfYear](../../sql-reference/functions/date-time-functions.md#tostartofyear), [toStartOfISOYear](../../sql-reference/functions/date-time-functions.md#tostartofisoyear), [toStartOfQuarter](../../sql-reference/functions/date-time-functions.md#tostartofquarter), [toStartOfMonth](../../sql-reference/functions/date-time-functions.md#tostartofmonth), [toStartOfWeek](../../sql-reference/functions/date-time-functions.md#tostartofweek), [toMonday](../../sql-reference/functions/date-time-functions.md#tomonday) и [toLastDayOfMonth](../../sql-reference/functions/date-time-functions.md#tolastdayofmonth). +- `DateTime64` с расширенным диапазоном (по сравнению с типом `DateTime`) для функций [toStartOfDay](../../sql-reference/functions/date-time-functions.md#tostartofday), [toStartOfHour](../../sql-reference/functions/date-time-functions.md#tostartofhour), [toStartOfMinute](../../sql-reference/functions/date-time-functions.md#tostartofminute), [toStartOfFiveMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffiveminutes), [toStartOfTenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoftenminutes), [toStartOfFifteenMinutes](../../sql-reference/functions/date-time-functions.md#tostartoffifteenminutes) и [timeSlot](../../sql-reference/functions/date-time-functions.md#timeslot). + +Возможные значения: + +- 0 — Функции возвращают результаты типа `Date` или `DateTime` для всех типов аргументов. +- 1 — Функции возвращают результаты типа `Date32` или `DateTime64` для аргументов типа `Date32` или `DateTime64` и возвращают `Date` или `DateTime` в других случаях. + +Значение по умолчанию: `0`. + ## optimize_move_to_prewhere {#optimize_move_to_prewhere} Включает или отключает автоматическую оптимизацию [PREWHERE](../../sql-reference/statements/select/prewhere.md) в запросах [SELECT](../../sql-reference/statements/select/index.md). From e66e70870a43e931fcbbd9bcffb362cf29755197 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Wed, 28 Sep 2022 16:05:59 +0000 Subject: [PATCH 12/21] Fix timezone issues --- .../FunctionDateOrDateTimeToDateTimeOrDateTime64.h | 11 ++++++----- src/Functions/IFunctionDateOrDateTime.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h index 974f3e14d2e..83f3620c3bd 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -28,15 +28,16 @@ public: DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override { - this->checkArguments(arguments, /*is_result_type_date_or_date32*/ true); + this->checkArguments(arguments, /*is_result_type_date_or_date32*/ false); const IDataType * from_type = arguments[0].type.get(); WhichDataType which(from_type); + std::string time_zone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0); + /// If the time zone is specified but empty, throw an exception. /// only validate the time_zone part if the number of arguments is 2. - if ((which.isDateTime() || which.isDateTime64()) && arguments.size() == 2 - && extractTimeZoneNameFromFunctionArguments(arguments, 1, 0).empty()) + if (arguments.size() == 2 && time_zone.empty()) throw Exception( "Function " + this->getName() + " supports a 2nd argument (optional) that must be non-empty and be a valid time zone", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); @@ -49,10 +50,10 @@ public: if (const auto * dt64 = checkAndGetDataType(arguments[0].type.get())) scale = dt64->getScale(); } - return std::make_shared(scale, extractTimeZoneNameFromFunctionArguments(arguments, 1, 0)); + return std::make_shared(scale, time_zone); } else - return std::make_shared(); + return std::make_shared(time_zone); } ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override diff --git a/src/Functions/IFunctionDateOrDateTime.h b/src/Functions/IFunctionDateOrDateTime.h index 1efe89c7fe9..990e92a46c8 100644 --- a/src/Functions/IFunctionDateOrDateTime.h +++ b/src/Functions/IFunctionDateOrDateTime.h @@ -102,7 +102,7 @@ protected: "Function " + getName() + " supports 1 or 2 arguments. The optional 2nd argument must be " "a constant string with a timezone name", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); - if ((isDate(arguments[0].type) || isDate32(arguments[0].type)) && is_result_type_date_or_date32) + if (isDateOrDate32(arguments[0].type) && is_result_type_date_or_date32) throw Exception( "The timezone argument of function " + getName() + " is allowed only when the 1st argument has the type DateTime or DateTime64", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); From 22ccce6946e9f1f83782d6e57e512859c81bd05f Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 09:29:07 +0000 Subject: [PATCH 13/21] Remove WithContext; Rename execute_extended_result to executeExtendedResult --- src/Functions/CustomWeekTransforms.h | 6 +-- src/Functions/DateTimeTransforms.h | 54 +++++++++---------- .../FunctionDateOrDateTimeToDateOrDate32.h | 5 +- ...tionDateOrDateTimeToDateTimeOrDateTime64.h | 6 +-- src/Functions/TransformDateTime64.h | 12 ++--- 5 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/Functions/CustomWeekTransforms.h b/src/Functions/CustomWeekTransforms.h index 5fa51d5f5e0..7e5e3458fc2 100644 --- a/src/Functions/CustomWeekTransforms.h +++ b/src/Functions/CustomWeekTransforms.h @@ -82,11 +82,11 @@ struct ToStartOfWeekImpl { return time_zone.toFirstDayNumOfWeek(DayNum(d), week_mode); } - static inline Int64 execute_extended_result(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, UInt8 week_mode, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t), week_mode); } - static inline Int32 execute_extended_result(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, UInt8 week_mode, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d), week_mode); } @@ -139,7 +139,7 @@ struct WeekTransformer for (size_t i = 0; i < size; ++i) if constexpr (is_extended_result) - vec_to[i] = transform.execute_extended_result(vec_from[i], week_mode, time_zone); + vec_to[i] = transform.executeExtendedResult(vec_from[i], week_mode, time_zone); else vec_to[i] = transform.execute(vec_from[i], week_mode, time_zone); } diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 6640f632c8c..23c8c57ca50 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -140,11 +140,11 @@ struct ToStartOfDayImpl auto date_time = time_zone.fromDayNum(ExtendedDayNum(d)); return date_time < 0xffffffff ? date_time : time_zone.toDate(0xffffffff); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toDate(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.fromDayNum(ExtendedDayNum(d)) * DecimalUtils::scaleMultiplier(DataTypeDateTime64::default_scale); } @@ -173,11 +173,11 @@ struct ToMondayImpl { return time_zone.toFirstDayNumOfWeek(DayNum(d)); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d)); } @@ -204,11 +204,11 @@ struct ToStartOfMonthImpl { return time_zone.toFirstDayNumOfMonth(DayNum(d)); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfMonth(ExtendedDayNum(d)); } @@ -245,11 +245,11 @@ struct ToLastDayOfMonthImpl /// 0xFFF9 is Int value for 2149-05-31 -- the last day where we can actually find LastDayOfMonth. This will also be the return value. return time_zone.toLastDayNumOfMonth(DayNum(std::min(d, UInt16(0xFFF9)))); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toLastDayNumOfMonth(ExtendedDayNum(d)); } @@ -276,11 +276,11 @@ struct ToStartOfQuarterImpl { return time_zone.toFirstDayNumOfQuarter(DayNum(d)); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(d)); } @@ -307,11 +307,11 @@ struct ToStartOfYearImpl { return time_zone.toFirstDayNumOfYear(DayNum(d)); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfYear(ExtendedDayNum(d)); } @@ -368,11 +368,11 @@ struct ToStartOfMinuteImpl { return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfMinute(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -566,11 +566,11 @@ struct ToStartOfFiveMinutesImpl { return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfFiveMinutes(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -598,11 +598,11 @@ struct ToStartOfTenMinutesImpl { return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfTenMinutes(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -630,11 +630,11 @@ struct ToStartOfFifteenMinutesImpl { return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfFifteenMinutes(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -667,12 +667,12 @@ struct TimeSlotImpl return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -707,12 +707,12 @@ struct ToStartOfHourImpl return dateIsNotSupported(name); } - static inline DecimalUtils::DecimalComponents execute_extended_result(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfHour(t.whole), 0}; } - static inline Int64 execute_extended_result(Int32, const DateLUTImpl &) + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); } @@ -1007,11 +1007,11 @@ struct ToStartOfISOYearImpl { return time_zone.toFirstDayNumOfISOYear(DayNum(d)); } - static inline Int64 execute_extended_result(Int64 t, const DateLUTImpl & time_zone) + static inline Int64 executeExtendedResult(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t)); } - static inline Int32 execute_extended_result(Int32 d, const DateLUTImpl & time_zone) + static inline Int32 executeExtendedResult(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(d)); } @@ -1320,7 +1320,7 @@ struct Transformer for (size_t i = 0; i < size; ++i) if constexpr (is_extended_result) - vec_to[i] = transform.execute_extended_result(vec_from[i], time_zone); + vec_to[i] = transform.executeExtendedResult(vec_from[i], time_zone); else vec_to[i] = transform.execute(vec_from[i], time_zone); } diff --git a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h index 3ff90cb57fb..1e6e79da672 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h +++ b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h @@ -10,7 +10,7 @@ namespace ErrorCodes } template -class FunctionDateOrDateTimeToDateOrDate32 : public IFunctionDateOrDateTime, WithContext +class FunctionDateOrDateTimeToDateOrDate32 : public IFunctionDateOrDateTime { public: const bool enable_extended_results_for_datetime_functions = false; @@ -21,8 +21,7 @@ public: } explicit FunctionDateOrDateTimeToDateOrDate32(ContextPtr context_) - : WithContext(context_) - , enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) + : enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) { } diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h index 83f3620c3bd..454538f4948 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -10,7 +10,7 @@ namespace ErrorCodes } template -class FunctionDateOrDateTimeToDateTimeOrDateTime64 : public IFunctionDateOrDateTime, WithContext +class FunctionDateOrDateTimeToDateTimeOrDateTime64 : public IFunctionDateOrDateTime { public: const bool enable_extended_results_for_datetime_functions = false; @@ -21,8 +21,7 @@ public: } explicit FunctionDateOrDateTimeToDateTimeOrDateTime64(ContextPtr context_) - : WithContext(context_) - , enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) + : enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) { } @@ -31,6 +30,7 @@ public: this->checkArguments(arguments, /*is_result_type_date_or_date32*/ false); const IDataType * from_type = arguments[0].type.get(); + WhichDataType which(from_type); std::string time_zone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0); diff --git a/src/Functions/TransformDateTime64.h b/src/Functions/TransformDateTime64.h index fbe7e2e8250..cb4b3fbb71d 100644 --- a/src/Functions/TransformDateTime64.h +++ b/src/Functions/TransformDateTime64.h @@ -89,20 +89,20 @@ public: template - inline auto NO_SANITIZE_UNDEFINED execute_extended_result(const DateTime64 & t, Args && ... args) const + inline auto NO_SANITIZE_UNDEFINED executeExtendedResult(const DateTime64 & t, Args && ... args) const { /// Type conversion from float to integer may be required. /// We are Ok with implementation specific result for out of range and denormals conversion. if constexpr (TransformHasExecuteOverload_v) { - return wrapped_transform.execute_extended_result(t, scale_multiplier, std::forward(args)...); + return wrapped_transform.executeExtendedResult(t, scale_multiplier, std::forward(args)...); } else if constexpr (TransformHasExecuteOverload_v, Args...>) { auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier); - const auto result = wrapped_transform.execute_extended_result(components, std::forward(args)...); + const auto result = wrapped_transform.executeExtendedResult(components, std::forward(args)...); using ResultType = std::decay_t; if constexpr (std::is_same_v, ResultType>) @@ -117,14 +117,14 @@ public: else { const auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier); - return wrapped_transform.execute_extended_result(static_cast(components.whole), std::forward(args)...); + return wrapped_transform.executeExtendedResult(static_cast(components.whole), std::forward(args)...); } } template >> - inline auto execute_extended_result(const T & t, Args && ... args) const + inline auto executeExtendedResult(const T & t, Args && ... args) const { - return wrapped_transform.execute_extended_result(t, std::forward(args)...); + return wrapped_transform.executeExtendedResult(t, std::forward(args)...); } private: From 53b34c7e0a2b5a86fd4554b4d27e8d5e6e9c06df Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 11:04:13 +0000 Subject: [PATCH 14/21] Put enable_extended_results_for_datetime_functions into private; correct if/else braces --- src/Functions/FunctionCustomWeekToDateOrDate32.h | 10 ++++++---- src/Functions/FunctionDateOrDateTimeToDateOrDate32.h | 5 ++++- .../FunctionDateOrDateTimeToDateTimeOrDateTime64.h | 8 +++++--- 3 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/Functions/FunctionCustomWeekToDateOrDate32.h b/src/Functions/FunctionCustomWeekToDateOrDate32.h index 0b91fbb3bbe..5d2b8837c43 100644 --- a/src/Functions/FunctionCustomWeekToDateOrDate32.h +++ b/src/Functions/FunctionCustomWeekToDateOrDate32.h @@ -10,19 +10,19 @@ namespace ErrorCodes } template -class FunctionCustomWeekToDateOrDate32 : public IFunctionCustomWeek, WithContext +class FunctionCustomWeekToDateOrDate32 : public IFunctionCustomWeek { -public: +private: const bool enable_extended_results_for_datetime_functions = false; +public: static FunctionPtr create(ContextPtr context_) { return std::make_shared(context_); } explicit FunctionCustomWeekToDateOrDate32(ContextPtr context_) - : WithContext(context_) - , enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) + : enable_extended_results_for_datetime_functions(context_->getSettingsRef().enable_extended_results_for_datetime_functions) { } @@ -47,12 +47,14 @@ public: return CustomWeekTransformImpl::execute( arguments, result_type, input_rows_count, Transform{}); else if (which.isDate32()) + { if (enable_extended_results_for_datetime_functions) return CustomWeekTransformImpl::execute( arguments, result_type, input_rows_count, Transform{}); else return CustomWeekTransformImpl::execute( arguments, result_type, input_rows_count, Transform{}); + } else if (which.isDateTime()) return CustomWeekTransformImpl::execute( arguments, result_type, input_rows_count, Transform{}); diff --git a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h index 1e6e79da672..a4348fd7308 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h +++ b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h @@ -12,9 +12,10 @@ namespace ErrorCodes template class FunctionDateOrDateTimeToDateOrDate32 : public IFunctionDateOrDateTime { -public: +private: const bool enable_extended_results_for_datetime_functions = false; +public: static FunctionPtr create(ContextPtr context_) { return std::make_shared(context_); @@ -54,10 +55,12 @@ public: if (which.isDate()) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDate32()) + { if (enable_extended_results_for_datetime_functions) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + } else if (which.isDateTime()) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDateTime64()) diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h index 454538f4948..787cab85d73 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -12,9 +12,10 @@ namespace ErrorCodes template class FunctionDateOrDateTimeToDateTimeOrDateTime64 : public IFunctionDateOrDateTime { -public: +private: const bool enable_extended_results_for_datetime_functions = false; +public: static FunctionPtr create(ContextPtr context_) { return std::make_shared(context_); @@ -63,12 +64,13 @@ public: if (which.isDate()) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDate32()) + { if (enable_extended_results_for_datetime_functions) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); - else - if (which.isDateTime()) + } + else if (which.isDateTime()) return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDateTime64()) { From 9d84d3de8923f9b856e26e6438f3d0d868efcd73 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 13:23:31 +0000 Subject: [PATCH 15/21] Fix timezone in test --- ...d_results_for_datetime_functions.reference | 32 +++++++++---------- ...nded_results_for_datetime_functions.sql.j2 | 8 ++--- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference index 3b33aed565d..5773810bf64 100644 --- a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference +++ b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.reference @@ -27,21 +27,21 @@ type;toLastDayOfMonth;toDate32;true Date32 toLastDayOfMonth;toDateTime64;true 1920-02-29 type;toLastDayOfMonth;toDateTime64;true Date32 toStartOfDay;toDateTime64;true 1920-02-02 00:00:00.000 -type;toStartOfDay;toDateTime64;true DateTime64(3) +type;toStartOfDay;toDateTime64;true DateTime64(3, \'UTC\') toStartOfHour;toDateTime64;true 1920-02-02 10:00:00.000 -type;toStartOfHour;toDateTime64;true DateTime64(3) +type;toStartOfHour;toDateTime64;true DateTime64(3, \'UTC\') toStartOfMinute;toDateTime64;true 1920-02-02 10:23:00.000 -type;toStartOfMinute;toDateTime64;true DateTime64(3) +type;toStartOfMinute;toDateTime64;true DateTime64(3, \'UTC\') toStartOfFiveMinutes;toDateTime64;true 1920-02-02 10:20:00.000 -type;toStartOfFiveMinutes;toDateTime64;true DateTime64(3) +type;toStartOfFiveMinutes;toDateTime64;true DateTime64(3, \'UTC\') toStartOfTenMinutes;toDateTime64;true 1920-02-02 10:20:00.000 -type;toStartOfTenMinutes;toDateTime64;true DateTime64(3) +type;toStartOfTenMinutes;toDateTime64;true DateTime64(3, \'UTC\') toStartOfFifteenMinutes;toDateTime64;true 1920-02-02 10:15:00.000 -type;toStartOfFifteenMinutes;toDateTime64;true DateTime64(3) +type;toStartOfFifteenMinutes;toDateTime64;true DateTime64(3, \'UTC\') timeSlot;toDateTime64;true 1920-02-02 10:00:00.000 -type;timeSlot;toDateTime64;true DateTime64(3) +type;timeSlot;toDateTime64;true DateTime64(3, \'UTC\') toStartOfDay;toDate32;true 1920-02-02 00:00:00.000 -type;toStartOfDay;toDate32;true DateTime64(3) +type;toStartOfDay;toDate32;true DateTime64(3, \'UTC\') toStartOfYear;toDate32;false 1970-01-01 type;toStartOfYear;toDate32;false Date toStartOfYear;toDateTime64;false 1970-01-01 @@ -71,18 +71,18 @@ type;toLastDayOfMonth;toDate32;false Date toLastDayOfMonth;toDateTime64;false 1970-01-01 type;toLastDayOfMonth;toDateTime64;false Date toStartOfDay;toDateTime64;false 1970-01-01 00:00:00 -type;toStartOfDay;toDateTime64;false DateTime +type;toStartOfDay;toDateTime64;false DateTime(\'UTC\') toStartOfHour;toDateTime64;false 1970-01-01 00:00:00 -type;toStartOfHour;toDateTime64;false DateTime +type;toStartOfHour;toDateTime64;false DateTime(\'UTC\') toStartOfMinute;toDateTime64;false 1970-01-01 00:00:00 -type;toStartOfMinute;toDateTime64;false DateTime +type;toStartOfMinute;toDateTime64;false DateTime(\'UTC\') toStartOfFiveMinutes;toDateTime64;false 2056-03-09 16:48:16 -type;toStartOfFiveMinutes;toDateTime64;false DateTime +type;toStartOfFiveMinutes;toDateTime64;false DateTime(\'UTC\') toStartOfTenMinutes;toDateTime64;false 2056-03-09 16:48:16 -type;toStartOfTenMinutes;toDateTime64;false DateTime +type;toStartOfTenMinutes;toDateTime64;false DateTime(\'UTC\') toStartOfFifteenMinutes;toDateTime64;false 2056-03-09 16:43:16 -type;toStartOfFifteenMinutes;toDateTime64;false DateTime +type;toStartOfFifteenMinutes;toDateTime64;false DateTime(\'UTC\') timeSlot;toDateTime64;false 2056-03-09 16:58:16 -type;timeSlot;toDateTime64;false DateTime +type;timeSlot;toDateTime64;false DateTime(\'UTC\') toStartOfDay;toDate32;false 1970-01-01 00:00:00 -type;toStartOfDay;toDate32;false DateTime +type;toStartOfDay;toDate32;false DateTime(\'UTC\') diff --git a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 index 5c575b8f352..38d1094fe62 100644 --- a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 +++ b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 @@ -6,9 +6,9 @@ SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTi SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} {% for date_fun in ['toStartOfDay', 'toStartOfHour', 'toStartOfMinute', 'toStartOfFiveMinutes', 'toStartOfTenMinutes', 'toStartOfFifteenMinutes', 'timeSlot'] -%} -SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:23:33.789', 3)) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; -SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:23:33.789', 3), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} -SELECT 'toStartOfDay;toDate32;{{ option_value }}', toStartOfDay(toDate32('1920-02-02')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; -SELECT 'type;toStartOfDay;toDate32;{{ option_value }}', toTypeName(toStartOfDay(toDate32('1920-02-02'))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'toStartOfDay;toDate32;{{ option_value }}', toStartOfDay(toDate32('1920-02-02'), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;toStartOfDay;toDate32;{{ option_value }}', toTypeName(toStartOfDay(toDate32('1920-02-02'), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} From e0099d52def5c3f02ebc778671661d78e50cf9de Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 14:07:02 +0000 Subject: [PATCH 16/21] Use C++20 format() syntax for exceptions --- .../FunctionCustomWeekToDateOrDate32.h | 6 +- src/Functions/FunctionCustomWeekToSomething.h | 6 +- .../FunctionDateOrDateTimeToDateOrDate32.h | 11 ++-- ...tionDateOrDateTimeToDateTimeOrDateTime64.h | 11 ++-- .../FunctionDateOrDateTimeToSomething.h | 11 ++-- src/Functions/IFunctionCustomWeek.h | 55 ++++++++----------- src/Functions/IFunctionDateOrDateTime.h | 33 +++++------ 7 files changed, 63 insertions(+), 70 deletions(-) diff --git a/src/Functions/FunctionCustomWeekToDateOrDate32.h b/src/Functions/FunctionCustomWeekToDateOrDate32.h index 5d2b8837c43..cb1ae77de99 100644 --- a/src/Functions/FunctionCustomWeekToDateOrDate32.h +++ b/src/Functions/FunctionCustomWeekToDateOrDate32.h @@ -70,9 +70,9 @@ public: TransformDateTime64{assert_cast(from_type)->getScale()}); } else - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", + arguments[0].type->getName(), this->getName()); } }; diff --git a/src/Functions/FunctionCustomWeekToSomething.h b/src/Functions/FunctionCustomWeekToSomething.h index eb65d562221..7a23747d8a0 100644 --- a/src/Functions/FunctionCustomWeekToSomething.h +++ b/src/Functions/FunctionCustomWeekToSomething.h @@ -45,9 +45,9 @@ public: TransformDateTime64{assert_cast(from_type)->getScale()}); } else - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", + arguments[0].type->getName(), this->getName()); } }; diff --git a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h index a4348fd7308..8e006b93b98 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h +++ b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h @@ -37,9 +37,9 @@ public: /// only validate the time_zone part if the number of arguments is 2. if ((which.isDateTime() || which.isDateTime64()) && arguments.size() == 2 && extractTimeZoneNameFromFunctionArguments(arguments, 1, 0).empty()) - throw Exception( - "Function " + this->getName() + " supports a 2nd argument (optional) that must be non-empty and be a valid time zone", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Function {} supports a 2nd argument (optional) that must be a valid time zone", + this->getName()); if ((which.isDate32() || which.isDateTime64()) && enable_extended_results_for_datetime_functions) return std::make_shared(); @@ -74,8 +74,9 @@ public: return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); } else - throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", + arguments[0].type->getName(), this->getName()); } }; diff --git a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h index 787cab85d73..3d1f0f192cf 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h +++ b/src/Functions/FunctionDateOrDateTimeToDateTimeOrDateTime64.h @@ -39,9 +39,9 @@ public: /// If the time zone is specified but empty, throw an exception. /// only validate the time_zone part if the number of arguments is 2. if (arguments.size() == 2 && time_zone.empty()) - throw Exception( - "Function " + this->getName() + " supports a 2nd argument (optional) that must be non-empty and be a valid time zone", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Function {} supports a 2nd argument (optional) that must be a valid time zone", + this->getName()); if ((which.isDate32() || which.isDateTime64()) && enable_extended_results_for_datetime_functions) { @@ -83,8 +83,9 @@ public: return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); } else - throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", + arguments[0].type->getName(), this->getName()); } }; diff --git a/src/Functions/FunctionDateOrDateTimeToSomething.h b/src/Functions/FunctionDateOrDateTimeToSomething.h index 5c1c54c1b84..47433d13e0b 100644 --- a/src/Functions/FunctionDateOrDateTimeToSomething.h +++ b/src/Functions/FunctionDateOrDateTimeToSomething.h @@ -28,9 +28,9 @@ public: /// only validate the time_zone part if the number of arguments is 2. This is mainly /// to accommodate functions like toStartOfDay(today()), toStartOfDay(yesterday()) etc. if (arguments.size() == 2 && time_zone.empty()) - throw Exception( - "Function " + this->getName() + " supports a 2nd argument (optional) that must be non-empty and be a valid time zone", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Function {} supports a 2nd argument (optional) that must be a valid time zone", + this->getName()); return std::make_shared(time_zone); } if constexpr (std::is_same_v) @@ -78,8 +78,9 @@ public: return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); } else - throw Exception("Illegal type " + arguments[0].type->getName() + " of argument of function " + this->getName(), - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}", + arguments[0].type->getName(), this->getName()); } }; diff --git a/src/Functions/IFunctionCustomWeek.h b/src/Functions/IFunctionCustomWeek.h index 1bc4e44655a..e620793ea6c 100644 --- a/src/Functions/IFunctionCustomWeek.h +++ b/src/Functions/IFunctionCustomWeek.h @@ -70,51 +70,44 @@ protected: if (arguments.size() == 1) { if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type)) - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() - + ". Must be Date, Date32, DateTime or DateTime64.", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}. Must be Date, Date32, DateTime or DateTime64.", + arguments[0].type->getName(), getName()); } else if (arguments.size() == 2) { if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type)) - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of 1st argument of function " + getName() - + ". Must be Date, Date32, DateTime or DateTime64.", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of 1st argument of function {}. Must be Date, Date32, DateTime or DateTime64.", + arguments[0].type->getName(), getName()); if (!isUInt8(arguments[1].type)) - throw Exception( - "Illegal type of 2nd (optional) argument of function " + getName() - + ". Must be constant UInt8 (week mode).", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type of 2nd (optional) argument of function {}. Must be constant UInt8 (week mode).", + getName()); } else if (arguments.size() == 3) { if (!isDate(arguments[0].type) && !isDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type)) - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() - + ". Must be Date, Date32, DateTime or DateTime64", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}. Must be Date, Date32, DateTime or DateTime64", + arguments[0].type->getName(), getName()); if (!isUInt8(arguments[1].type)) - throw Exception( - "Illegal type of 2nd (optional) argument of function " + getName() - + ". Must be constant UInt8 (week mode).", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type of 2nd (optional) argument of function {}. Must be constant UInt8 (week mode).", + getName()); if (!isString(arguments[2].type)) - throw Exception( - "Illegal type of 3rd (optional) argument of function " + getName() - + ". Must be constant string (timezone name).", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type of 3rd (optional) argument of function {}. Must be constant string (timezone name).", + getName()); if ((isDate(arguments[0].type) || isDate32(arguments[0].type)) && is_result_type_date_or_date32) - throw Exception( - "The timezone argument of function " + getName() + " is allowed only when the 1st argument is DateTime or DateTime64.", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "The timezone argument of function {} is allowed only when the 1st argument is DateTime or DateTime64.", + getName()); } else - throw Exception( - "Number of arguments for function " + getName() + " doesn't match: passed " + toString(arguments.size()) - + ", expected 1, 2 or 3.", - ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, + "Number of arguments for function {} doesn't match: passed {}, expected 1, 2 or 3.", + getName(), arguments.size()); } }; diff --git a/src/Functions/IFunctionDateOrDateTime.h b/src/Functions/IFunctionDateOrDateTime.h index 990e92a46c8..343511f0f91 100644 --- a/src/Functions/IFunctionDateOrDateTime.h +++ b/src/Functions/IFunctionDateOrDateTime.h @@ -85,33 +85,30 @@ protected: if (arguments.size() == 1) { if (!isDateOrDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type)) - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() - + ". Should be Date, Date32, DateTime or DateTime64", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}. Should be Date, Date32, DateTime or DateTime64", + arguments[0].type->getName(), getName()); } else if (arguments.size() == 2) { if (!isDateOrDate32(arguments[0].type) && !isDateTime(arguments[0].type) && !isDateTime64(arguments[0].type)) - throw Exception( - "Illegal type " + arguments[0].type->getName() + " of argument of function " + getName() - + ". Should be Date, Date32, DateTime or DateTime64", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Illegal type {} of argument of function {}. Should be Date, Date32, DateTime or DateTime64", + arguments[0].type->getName(), getName()); if (!isString(arguments[1].type)) - throw Exception( - "Function " + getName() + " supports 1 or 2 arguments. The optional 2nd argument must be " + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "Function {} supports 1 or 2 arguments. The optional 2nd argument must be " "a constant string with a timezone name", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + getName()); if (isDateOrDate32(arguments[0].type) && is_result_type_date_or_date32) - throw Exception( - "The timezone argument of function " + getName() + " is allowed only when the 1st argument has the type DateTime or DateTime64", - ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, + "The timezone argument of function {} is allowed only when the 1st argument has the type DateTime or DateTime64", + getName()); } else - throw Exception( - "Number of arguments for function " + getName() + " doesn't match: passed " + toString(arguments.size()) - + ", should be 1 or 2", - ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); + throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, + "Number of arguments for function {} doesn't match: passed {}, should be 1 or 2", + getName(), arguments.size()); } }; From 9dfb2d058c841daa7441b8cadc6501a2782f2e6a Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 14:23:50 +0000 Subject: [PATCH 17/21] Add DateTime64 returing functions in Note box --- docs/en/sql-reference/functions/date-time-functions.md | 8 +++++--- docs/ru/sql-reference/functions/date-time-functions.md | 9 ++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/docs/en/sql-reference/functions/date-time-functions.md b/docs/en/sql-reference/functions/date-time-functions.md index 001c7822433..829dc49f42a 100644 --- a/docs/en/sql-reference/functions/date-time-functions.md +++ b/docs/en/sql-reference/functions/date-time-functions.md @@ -268,15 +268,17 @@ Result: ``` :::note -The return type of `toStartOf*`, `toLastDayOfMonth`, `toMonday` functions described below is determined by the configuration parameter [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) which is `0` by default. +The return type of `toStartOf*`, `toLastDayOfMonth`, `toMonday`, `timeSlot` functions described below is determined by the configuration parameter [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) which is `0` by default. Behavior for -* `enable_extended_results_for_datetime_functions = 0`: Functions `toStartOf*`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime`. Though these functions can take values of the extended types `Date32` and `DateTime64` as an argument, passing them a time outside the normal range (year 1970 to 2149 for `Date` / 2106 for `DateTime`) will produce wrong results. In case argument is out of normal range: +* `enable_extended_results_for_datetime_functions = 0`: Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime`. Functions `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` return `DateTime`. Though these functions can take values of the extended types `Date32` and `DateTime64` as an argument, passing them a time outside the normal range (year 1970 to 2149 for `Date` / 2106 for `DateTime`) will produce wrong results. In case argument is out of normal range: * If the argument is smaller than 1970, the result will be calculated from the argument `1970-01-01 (00:00:00)` instead. * If the return type is `DateTime` and the argument is larger than `2106-02-07 08:28:15`, the result will be calculated from the argument `2106-02-07 08:28:15` instead. * If the return type is `Date` and the argument is larger than `2149-06-06`, the result will be calculated from the argument `2149-06-06` instead. * If `toLastDayOfMonth` is called with an argument greater then `2149-05-31`, the result will be calculated from the argument `2149-05-31` instead. -* `enable_extended_results_for_datetime_functions = 1`: Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime` if their argument is a `Date` or `DateTime`, and they return `Date32` or `DateTime64` if their argument is a `Date32` or `DateTime64`. +* `enable_extended_results_for_datetime_functions = 1`: + * Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime` if their argument is a `Date` or `DateTime`, and they return `Date32` or `DateTime64` if their argument is a `Date32` or `DateTime64`. + * Functions `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` return `DateTime` if their argument is a `Date` or `DateTime`, and they return `DateTime64` if their argument is a `Date32` or `DateTime64`. ::: ## toStartOfYear diff --git a/docs/ru/sql-reference/functions/date-time-functions.md b/docs/ru/sql-reference/functions/date-time-functions.md index 27689426cbe..f9b223dfd33 100644 --- a/docs/ru/sql-reference/functions/date-time-functions.md +++ b/docs/ru/sql-reference/functions/date-time-functions.md @@ -268,16 +268,19 @@ SELECT toUnixTimestamp('2017-11-05 08:07:47', 'Asia/Tokyo') AS unix_timestamp; ``` :::note -Тип возвращаемого значения описанными далее функциями `toStartOf*`, `toLastDayOfMonth`, `toMonday` определяется конфигурационным параметром [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) имеющим по умолчанию значение `0`. +Тип возвращаемого значения описанными далее функциями `toStartOf*`, `toLastDayOfMonth`, `toMonday`, `timeSlot` определяется конфигурационным параметром [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) имеющим по умолчанию значение `0`. Поведение для -* `enable_extended_results_for_datetime_functions = 0`: Функции `toStartOf*`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime`. Хотя эти функции могут принимать значения типа `Date32` или `DateTime64` в качестве аргумента, при обработке аргумента вне нормального диапазона значений (`1970` - `2148` для `Date` и `1970-01-01 00:00:00`-`2106-02-07 08:28:15` для `DateTime`) будет получен некорректный результат. +* `enable_extended_results_for_datetime_functions = 0`: Функции `toStartOf*`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime`. Функции `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` возвращают `DateTime`. Хотя эти функции могут принимать значения типа `Date32` или `DateTime64` в качестве аргумента, при обработке аргумента вне нормального диапазона значений (`1970` - `2148` для `Date` и `1970-01-01 00:00:00`-`2106-02-07 08:28:15` для `DateTime`) будет получен некорректный результат. В случае если значение аргумента вне нормального диапазона: * `1970-01-01 (00:00:00)` будет возвращён для моментов времени до 1970 года, * `2106-02-07 08:28:15` будет взят в качестве аргумента, если полученный аргумент превосходит данное значение и возвращаемый тип - `DateTime`, * `2149-06-06` будет взят в качестве аргумента, если полученный аргумент превосходит данное значение и возвращаемый тип - `Date`, * `2149-05-31` будет результатом функции `toLastDayOfMonth` при обработке аргумента больше `2149-05-31`. -* `enable_extended_results_for_datetime_functions = 1`: Функции `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `Date32` или `DateTime64` если их аргумент `Date32` или `DateTime64`. +* `enable_extended_results_for_datetime_functions = 1`: + * Функции `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `Date32` или `DateTime64` если их аргумент `Date32` или `DateTime64`. + * Функции `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` возвращают `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `DateTime64` если их аргумент `Date32` или `DateTime64`. + ::: ## toStartOfYear {#tostartofyear} From e8348accbfefbaaf03d2bf70a0c71578c38b9553 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 14:57:27 +0000 Subject: [PATCH 18/21] Fix timezone argument in test --- ..._enable_extended_results_for_datetime_functions.sql.j2 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 index 38d1094fe62..00a1a0030aa 100644 --- a/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 +++ b/tests/queries/0_stateless/02403_enable_extended_results_for_datetime_functions.sql.j2 @@ -6,9 +6,9 @@ SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTi SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3))) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} {% for date_fun in ['toStartOfDay', 'toStartOfHour', 'toStartOfMinute', 'toStartOfFiveMinutes', 'toStartOfTenMinutes', 'toStartOfFifteenMinutes', 'timeSlot'] -%} -SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:23:33.789', 3), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; -SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT '{{ date_fun }};toDateTime64;{{ option_value }}', {{ date_fun }}(toDateTime64('1920-02-02 10:23:33.789', 3, 'UTC'), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;{{ date_fun }};toDateTime64;{{ option_value }}', toTypeName({{ date_fun }}(toDateTime64('1920-02-02 10:20:30', 3, 'UTC'), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} -SELECT 'toStartOfDay;toDate32;{{ option_value }}', toStartOfDay(toDate32('1920-02-02'), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; -SELECT 'type;toStartOfDay;toDate32;{{ option_value }}', toTypeName(toStartOfDay(toDate32('1920-02-02'), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'toStartOfDay;toDate32;{{ option_value }}', toStartOfDay(toDate32('1920-02-02', 'UTC'), 'UTC') SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; +SELECT 'type;toStartOfDay;toDate32;{{ option_value }}', toTypeName(toStartOfDay(toDate32('1920-02-02', 'UTC'), 'UTC')) SETTINGS enable_extended_results_for_datetime_functions = {{ option_value }}; {% endfor -%} From 02e08fa3016edd9af5d4f80b499d6d3a570bd4a5 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 15:44:56 +0000 Subject: [PATCH 19/21] Use another approach for timeSlot() --- src/Functions/DateTimeTransforms.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 23c8c57ca50..94c32bc7ed9 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -667,11 +667,27 @@ struct TimeSlotImpl return dateIsNotSupported(name); } + /* static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) { return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; } + static inline Int64 executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) + { + // return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; + return t.whole / 1800 * 1800; + } + + */ + + static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) + { + if (likely(t.whole >= 0)) + return {t.whole / 1800 * 1800, 0}; + return {(t.whole + 1 - 1800) / 1800 * 1800, 0}; + } + static inline Int64 executeExtendedResult(Int32, const DateLUTImpl &) { return date32IsNotSupported(name); From c6fda60f32a89ea6ecadbfca7b1082d461189d9e Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Thu, 29 Sep 2022 15:45:49 +0000 Subject: [PATCH 20/21] Cleanup code --- src/Functions/DateTimeTransforms.h | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 94c32bc7ed9..454cdef1ddd 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -667,20 +667,6 @@ struct TimeSlotImpl return dateIsNotSupported(name); } - /* - static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl & time_zone) - { - return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; - } - - static inline Int64 executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) - { - // return {time_zone.toStartOfMinuteInterval(t.whole, 30), 0}; - return t.whole / 1800 * 1800; - } - - */ - static inline DecimalUtils::DecimalComponents executeExtendedResult(const DecimalUtils::DecimalComponents & t, const DateLUTImpl &) { if (likely(t.whole >= 0)) From f716fc2fe5689b31839578d0927284bfae9e95b6 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Fri, 30 Sep 2022 07:54:35 +0000 Subject: [PATCH 21/21] Put list of functions in correct order in docs; Use new formatting in exception messages. --- .../functions/date-time-functions.md | 4 ++-- .../functions/date-time-functions.md | 4 ++-- src/Functions/CustomWeekTransforms.h | 7 +++--- src/Functions/DateTimeTransforms.h | 22 +++++++++---------- 4 files changed, 18 insertions(+), 19 deletions(-) diff --git a/docs/en/sql-reference/functions/date-time-functions.md b/docs/en/sql-reference/functions/date-time-functions.md index 829dc49f42a..76f66db924f 100644 --- a/docs/en/sql-reference/functions/date-time-functions.md +++ b/docs/en/sql-reference/functions/date-time-functions.md @@ -271,14 +271,14 @@ Result: The return type of `toStartOf*`, `toLastDayOfMonth`, `toMonday`, `timeSlot` functions described below is determined by the configuration parameter [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) which is `0` by default. Behavior for -* `enable_extended_results_for_datetime_functions = 0`: Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime`. Functions `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` return `DateTime`. Though these functions can take values of the extended types `Date32` and `DateTime64` as an argument, passing them a time outside the normal range (year 1970 to 2149 for `Date` / 2106 for `DateTime`) will produce wrong results. In case argument is out of normal range: +* `enable_extended_results_for_datetime_functions = 0`: Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime`. Functions `toStartOfDay`, `toStartOfHour`, `toStartOfFifteenMinutes`, `toStartOfTenMinutes`, `toStartOfFiveMinutes`, `toStartOfMinute`, `timeSlot` return `DateTime`. Though these functions can take values of the extended types `Date32` and `DateTime64` as an argument, passing them a time outside the normal range (year 1970 to 2149 for `Date` / 2106 for `DateTime`) will produce wrong results. In case argument is out of normal range: * If the argument is smaller than 1970, the result will be calculated from the argument `1970-01-01 (00:00:00)` instead. * If the return type is `DateTime` and the argument is larger than `2106-02-07 08:28:15`, the result will be calculated from the argument `2106-02-07 08:28:15` instead. * If the return type is `Date` and the argument is larger than `2149-06-06`, the result will be calculated from the argument `2149-06-06` instead. * If `toLastDayOfMonth` is called with an argument greater then `2149-05-31`, the result will be calculated from the argument `2149-05-31` instead. * `enable_extended_results_for_datetime_functions = 1`: * Functions `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` return `Date` or `DateTime` if their argument is a `Date` or `DateTime`, and they return `Date32` or `DateTime64` if their argument is a `Date32` or `DateTime64`. - * Functions `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` return `DateTime` if their argument is a `Date` or `DateTime`, and they return `DateTime64` if their argument is a `Date32` or `DateTime64`. + * Functions `toStartOfDay`, `toStartOfHour`, `toStartOfFifteenMinutes`, `toStartOfTenMinutes`, `toStartOfFiveMinutes`, `toStartOfMinute`, `timeSlot` return `DateTime` if their argument is a `Date` or `DateTime`, and they return `DateTime64` if their argument is a `Date32` or `DateTime64`. ::: ## toStartOfYear diff --git a/docs/ru/sql-reference/functions/date-time-functions.md b/docs/ru/sql-reference/functions/date-time-functions.md index f9b223dfd33..897c4b3e86a 100644 --- a/docs/ru/sql-reference/functions/date-time-functions.md +++ b/docs/ru/sql-reference/functions/date-time-functions.md @@ -271,7 +271,7 @@ SELECT toUnixTimestamp('2017-11-05 08:07:47', 'Asia/Tokyo') AS unix_timestamp; Тип возвращаемого значения описанными далее функциями `toStartOf*`, `toLastDayOfMonth`, `toMonday`, `timeSlot` определяется конфигурационным параметром [enable_extended_results_for_datetime_functions](../../operations/settings/settings#enable-extended-results-for-datetime-functions) имеющим по умолчанию значение `0`. Поведение для -* `enable_extended_results_for_datetime_functions = 0`: Функции `toStartOf*`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime`. Функции `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` возвращают `DateTime`. Хотя эти функции могут принимать значения типа `Date32` или `DateTime64` в качестве аргумента, при обработке аргумента вне нормального диапазона значений (`1970` - `2148` для `Date` и `1970-01-01 00:00:00`-`2106-02-07 08:28:15` для `DateTime`) будет получен некорректный результат. +* `enable_extended_results_for_datetime_functions = 0`: Функции `toStartOf*`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime`. Функции `toStartOfDay`, `toStartOfHour`, `toStartOfFifteenMinutes`, `toStartOfTenMinutes`, `toStartOfFiveMinutes`, `toStartOfMinute`, `timeSlot` возвращают `DateTime`. Хотя эти функции могут принимать значения типа `Date32` или `DateTime64` в качестве аргумента, при обработке аргумента вне нормального диапазона значений (`1970` - `2148` для `Date` и `1970-01-01 00:00:00`-`2106-02-07 08:28:15` для `DateTime`) будет получен некорректный результат. В случае если значение аргумента вне нормального диапазона: * `1970-01-01 (00:00:00)` будет возвращён для моментов времени до 1970 года, * `2106-02-07 08:28:15` будет взят в качестве аргумента, если полученный аргумент превосходит данное значение и возвращаемый тип - `DateTime`, @@ -279,7 +279,7 @@ SELECT toUnixTimestamp('2017-11-05 08:07:47', 'Asia/Tokyo') AS unix_timestamp; * `2149-05-31` будет результатом функции `toLastDayOfMonth` при обработке аргумента больше `2149-05-31`. * `enable_extended_results_for_datetime_functions = 1`: * Функции `toStartOfYear`, `toStartOfISOYear`, `toStartOfQuarter`, `toStartOfMonth`, `toStartOfWeek`, `toLastDayOfMonth`, `toMonday` возвращают `Date` или `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `Date32` или `DateTime64` если их аргумент `Date32` или `DateTime64`. - * Функции `toStartOfDay`, `toStartOfHour`, `toStartOfMinute`, `toStartOfFiveMinutes`, `toStartOfTenMinutes`, `toStartOfFifteenMinutes`, `timeSlot` возвращают `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `DateTime64` если их аргумент `Date32` или `DateTime64`. + * Функции `toStartOfDay`, `toStartOfHour`, `toStartOfFifteenMinutes`, `toStartOfTenMinutes`, `toStartOfFiveMinutes`, `toStartOfMinute`, `timeSlot` возвращают `DateTime` если их аргумент `Date` или `DateTime` и они возвращают `DateTime64` если их аргумент `Date32` или `DateTime64`. ::: diff --git a/src/Functions/CustomWeekTransforms.h b/src/Functions/CustomWeekTransforms.h index 7e5e3458fc2..b690463d456 100644 --- a/src/Functions/CustomWeekTransforms.h +++ b/src/Functions/CustomWeekTransforms.h @@ -174,10 +174,9 @@ struct CustomWeekTransformImpl } else { - throw Exception( - "Illegal column " + arguments[0].column->getName() + " of first argument of function " - + Transform::name, - ErrorCodes::ILLEGAL_COLUMN); + throw Exception(ErrorCodes::ILLEGAL_COLUMN, + "Illegal column {} of first argument of function {}", + arguments[0].column->getName(), Transform::name); } } }; diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 454cdef1ddd..2687b380534 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -38,17 +38,17 @@ namespace ErrorCodes static inline UInt32 dateIsNotSupported(const char * name) { - throw Exception("Illegal type Date of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type Date of argument for function {}", name); } static inline UInt32 dateTimeIsNotSupported(const char * name) { - throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name); } static inline Int64 date32IsNotSupported(const char * name) { - throw Exception("Illegal type Date32 of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type Date32 of argument for function {}", name); } /// This factor transformation will say that the function is monotone everywhere. @@ -405,7 +405,7 @@ struct ToStartOfSecondImpl static inline UInt32 execute(UInt32, const DateLUTImpl &) { - throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name); } static inline UInt32 execute(Int32, const DateLUTImpl &) { @@ -452,7 +452,7 @@ struct ToStartOfMillisecondImpl static inline UInt32 execute(UInt32, const DateLUTImpl &) { - throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name); } static inline UInt32 execute(Int32, const DateLUTImpl &) { @@ -495,7 +495,7 @@ struct ToStartOfMicrosecondImpl static inline UInt32 execute(UInt32, const DateLUTImpl &) { - throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name); } static inline UInt32 execute(Int32, const DateLUTImpl &) { @@ -526,13 +526,13 @@ struct ToStartOfNanosecondImpl } else { - throw Exception("Illegal type of argument for function " + std::string(name) + ", DateTime64 expected", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type of argument for function {}, DateTime64 expected", name); } } static inline UInt32 execute(UInt32, const DateLUTImpl &) { - throw Exception("Illegal type DateTime of argument for function " + std::string(name), ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal type DateTime of argument for function {}", name); } static inline UInt32 execute(Int32, const DateLUTImpl &) { @@ -1363,9 +1363,9 @@ struct DateTimeTransformImpl } else { - throw Exception("Illegal column " + arguments[0].column->getName() - + " of first argument of function " + Transform::name, - ErrorCodes::ILLEGAL_COLUMN); + throw Exception(ErrorCodes::ILLEGAL_COLUMN, + "Illegal column {} of first argument of function {}", + arguments[0].column->getName(), Transform::name); } } };