From b03a0a724fa39b1d86aa1af9b9fe12a29a424046 Mon Sep 17 00:00:00 2001 From: Roman Vasin Date: Fri, 9 Sep 2022 13:25:52 +0000 Subject: [PATCH] Enable Date32 results for toStartOfYear, toStartOfISOYear, toStartOfQuarter, toStartOfMonth, toMonday, toLastDayOfMonth --- src/Functions/DateTimeTransforms.h | 87 +++++++++++++++---- .../FunctionDateOrDateTimeToDateOrDate32.h | 4 +- src/Functions/TransformDateTime64.h | 40 +++++++++ 3 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/Functions/DateTimeTransforms.h b/src/Functions/DateTimeTransforms.h index 0191cd704f8..6d5402fdec7 100644 --- a/src/Functions/DateTimeTransforms.h +++ b/src/Functions/DateTimeTransforms.h @@ -144,7 +144,7 @@ struct ToMondayImpl { static constexpr auto name = "toMonday"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { return t < 0 ? 0 : time_zone.toFirstDayNumOfWeek(ExtendedDayNum( std::min(Int32(time_zone.toDayNum(t)), Int32(DATE_LUT_MAX_DAY_NUM)))); @@ -153,7 +153,7 @@ struct ToMondayImpl { return time_zone.toFirstDayNumOfWeek(t); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { return d < 0 ? 0 : time_zone.toFirstDayNumOfWeek(ExtendedDayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -161,7 +161,15 @@ struct ToMondayImpl { return time_zone.toFirstDayNumOfWeek(DayNum(d)); } - + static inline Int64 execute_compat(Int64 t, const DateLUTImpl & time_zone) + { + //return time_zone.toFirstDayNumOfWeek(time_zone.toDayNum(t)); + return time_zone.toFirstDayNumOfWeek(t); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfWeek(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -169,7 +177,7 @@ struct ToStartOfMonthImpl { static constexpr auto name = "toStartOfMonth"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { return t < 0 ? 0 : time_zone.toFirstDayNumOfMonth(ExtendedDayNum(std::min(Int32(time_zone.toDayNum(t)), Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -177,7 +185,7 @@ struct ToStartOfMonthImpl { return time_zone.toFirstDayNumOfMonth(ExtendedDayNum(time_zone.toDayNum(t))); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { return d < 0 ? 0 : time_zone.toFirstDayNumOfMonth(ExtendedDayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -185,6 +193,14 @@ struct ToStartOfMonthImpl { return time_zone.toFirstDayNumOfMonth(DayNum(d)); } + static inline Int64 execute_compat(Int64 t, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfMonth(time_zone.toDayNum(t)); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfMonth(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -193,7 +209,7 @@ struct ToLastDayOfMonthImpl { static constexpr auto name = "toLastDayOfMonth"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { if (t < 0) return 0; @@ -205,7 +221,7 @@ struct ToLastDayOfMonthImpl { return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t)); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { if (d < 0) return 0; @@ -218,7 +234,14 @@ 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_compat(Int64 t, const DateLUTImpl & time_zone) + { + return time_zone.toLastDayNumOfMonth(time_zone.toDayNum(t)); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toLastDayNumOfMonth(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -226,7 +249,7 @@ struct ToStartOfQuarterImpl { static constexpr auto name = "toStartOfQuarter"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { return t < 0 ? 0 : time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(std::min(Int64(time_zone.toDayNum(t)), Int64(DATE_LUT_MAX_DAY_NUM)))); } @@ -234,7 +257,7 @@ struct ToStartOfQuarterImpl { return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t)); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { return d < 0 ? 0 : time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -242,7 +265,14 @@ struct ToStartOfQuarterImpl { return time_zone.toFirstDayNumOfQuarter(DayNum(d)); } - + static inline Int64 execute_compat(Int64 t, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfQuarter(time_zone.toDayNum(t)); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfQuarter(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -250,7 +280,7 @@ struct ToStartOfYearImpl { static constexpr auto name = "toStartOfYear"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { return t < 0 ? 0 : time_zone.toFirstDayNumOfYear(ExtendedDayNum(std::min(Int32(time_zone.toDayNum(t)), Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -258,7 +288,7 @@ struct ToStartOfYearImpl { return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t)); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { return d < 0 ? 0 : time_zone.toFirstDayNumOfYear(ExtendedDayNum(std::min(d, Int32(DATE_LUT_MAX_DAY_NUM)))); } @@ -266,6 +296,14 @@ struct ToStartOfYearImpl { return time_zone.toFirstDayNumOfYear(DayNum(d)); } + static inline Int64 execute_compat(Int64 t, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfYear(time_zone.toDayNum(t)); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfYear(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -891,7 +929,7 @@ struct ToStartOfISOYearImpl { static constexpr auto name = "toStartOfISOYear"; - static inline Int64 execute(Int64 t, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int64 t, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t)); } @@ -899,7 +937,7 @@ struct ToStartOfISOYearImpl { return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t)); } - static inline Int32 execute(Int32 d, const DateLUTImpl & time_zone) + static inline UInt16 execute(Int32 d, const DateLUTImpl & time_zone) { return time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(d)); } @@ -907,6 +945,14 @@ struct ToStartOfISOYearImpl { return time_zone.toFirstDayNumOfISOYear(DayNum(d)); } + static inline Int64 execute_compat(Int64 t, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfISOYear(time_zone.toDayNum(t)); + } + static inline Int32 execute_compat(Int32 d, const DateLUTImpl & time_zone) + { + return time_zone.toFirstDayNumOfISOYear(ExtendedDayNum(d)); + } using FactorTransform = ZeroTransform; }; @@ -1201,7 +1247,7 @@ struct ToYYYYMMDDhhmmssImpl }; -template +template struct Transformer { template @@ -1211,18 +1257,21 @@ struct Transformer vec_to.resize(size); for (size_t i = 0; i < size; ++i) - vec_to[i] = transform.execute(vec_from[i], time_zone); + if constexpr (is_compat) + vec_to[i] = transform.execute_compat(vec_from[i], time_zone); + else + vec_to[i] = transform.execute(vec_from[i], time_zone); } }; -template +template struct DateTimeTransformImpl { static ColumnPtr execute( const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t /*input_rows_count*/, const Transform & transform = {}) { - using Op = Transformer; + using Op = Transformer; const ColumnPtr source_col = arguments[0].column; if (const auto * sources = checkAndGetColumn(source_col.get())) diff --git a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h index 30add9dd316..0846ef8ac59 100644 --- a/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h +++ b/src/Functions/FunctionDateOrDateTimeToDateOrDate32.h @@ -56,7 +56,7 @@ public: return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDate32()) if (enable_date32_results) - return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count); else if (which.isDateTime()) @@ -67,7 +67,7 @@ public: const TransformDateTime64 transformer(scale); if (enable_date32_results) - return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); + return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); else return DateTimeTransformImpl::execute(arguments, result_type, input_rows_count, transformer); } diff --git a/src/Functions/TransformDateTime64.h b/src/Functions/TransformDateTime64.h index 9ac28118b8f..b3ced333d9d 100644 --- a/src/Functions/TransformDateTime64.h +++ b/src/Functions/TransformDateTime64.h @@ -87,6 +87,46 @@ public: return wrapped_transform.execute(t, std::forward(args)...); } + + template + inline auto NO_SANITIZE_UNDEFINED execute_compat(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_compat(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_compat(components, std::forward(args)...); + using ResultType = std::decay_t; + + if constexpr (std::is_same_v, ResultType>) + { + return DecimalUtils::decimalFromComponentsWithMultiplier(result, scale_multiplier); + } + else + { + return result; + } + } + else + { + const auto components = DecimalUtils::splitWithScaleMultiplier(t, scale_multiplier); + return wrapped_transform.execute_compat(static_cast(components.whole), std::forward(args)...); + } + } + + template >> + inline auto execute_compat(const T & t, Args && ... args) const + { + return wrapped_transform.execute_compat(t, std::forward(args)...); + } + private: DateTime64::NativeType scale_multiplier = 1; Transform wrapped_transform = {};