From 7b394da3743ae146cbff636504b5abd116b026c8 Mon Sep 17 00:00:00 2001 From: Mryange <2319153948@qq.com> Date: Fri, 13 Oct 2023 13:27:00 +0800 Subject: [PATCH] update --- .../function_datetime_floor_ceil.cpp | 656 +++++++++++++----- be/src/vec/runtime/vdatetime_value.h | 2 +- 2 files changed, 473 insertions(+), 185 deletions(-) diff --git a/be/src/vec/functions/function_datetime_floor_ceil.cpp b/be/src/vec/functions/function_datetime_floor_ceil.cpp index ea45f01c141eeb..ab36ec62df0186 100644 --- a/be/src/vec/functions/function_datetime_floor_ceil.cpp +++ b/be/src/vec/functions/function_datetime_floor_ceil.cpp @@ -150,19 +150,20 @@ class FunctionDateTimeFloorCeil : public IFunction { null_map->get_data().resize_fill(input_rows_count, false); if constexpr (ArgNum == 1) { - Impl::template vector(sources->get_data(), col_to->get_data(), - null_map->get_data()); + Impl::template vector(sources->get_data(), col_to->get_data()); } else if constexpr (ArgNum == 2) { const IColumn& delta_column = *block.get_by_position(arguments[1]).column; if (const auto* delta_const_column = typeid_cast(&delta_column)) { if (block.get_by_position(arguments[1]).type->get_type_id() != TypeIndex::Int32) { + // time_round(datetime, const(origin)) Impl::template vector_constant( sources->get_data(), delta_const_column->get_field().get(), - col_to->get_data(), null_map->get_data()); + col_to->get_data()); } else { + // time_round(datetime,const(period)) Impl::template vector_constant_delta( sources->get_data(), delta_const_column->get_field().get(), col_to->get_data(), null_map->get_data()); @@ -170,31 +171,64 @@ class FunctionDateTimeFloorCeil : public IFunction { } else { if (const auto* delta_vec_column0 = check_and_get_column>(delta_column)) { + // time_round(datetime, origin) Impl::vector_vector(sources->get_data(), delta_vec_column0->get_data(), - col_to->get_data(), null_map->get_data()); + col_to->get_data()); } else { const auto* delta_vec_column1 = check_and_get_column>(delta_column); DCHECK(delta_vec_column1 != nullptr); + // time_round(datetime, period) Impl::vector_vector(sources->get_data(), delta_vec_column1->get_data(), col_to->get_data(), null_map->get_data()); } } } else { - auto arg1_column_ptr = block.get_by_position(arguments[1]) - .column->convert_to_full_column_if_const(); - auto arg2_column_ptr = block.get_by_position(arguments[2]) - .column->convert_to_full_column_if_const(); - - const auto arg1_column = - check_and_get_column>(*arg1_column_ptr); - const auto arg2_column = - check_and_get_column>(*arg2_column_ptr); - DCHECK(arg1_column != nullptr); - DCHECK(arg2_column != nullptr); - Impl::template vector_vector( - sources->get_data(), arg1_column->get_data(), arg2_column->get_data(), - col_to->get_data(), null_map->get_data()); + ColumnPtr arg1_col, arg2_col; + bool arg1_const, arg2_const; + std::tie(arg1_col, arg1_const) = + unpack_if_const(block.get_by_position(arguments[1]).column); + std::tie(arg2_col, arg2_const) = + unpack_if_const(block.get_by_position(arguments[2]).column); + if (arg1_const && arg2_const) { + Field arg1, arg2; + arg1_col->get(0, arg1); + arg2_col->get(0, arg2); + // time_round(datetime,const(period) , const(origin)) + Impl::template vector_const_const( + sources->get_data(), arg1.get(), arg2.get(), + col_to->get_data(), null_map->get_data()); + + } else if (arg1_const && !arg2_const) { + Field arg1; + arg1_col->get(0, arg1); + const auto arg2_column = + check_and_get_column>(*arg2_col); + // time_round(datetime,const(period) , origin) + Impl::template vector_const_vector( + sources->get_data(), arg1.get(), arg2_column->get_data(), + col_to->get_data(), null_map->get_data()); + } else if (!arg1_const && arg2_const) { + Field arg2; + arg2_col->get(0, arg2); + const auto arg1_column = + check_and_get_column>(*arg1_col); + // time_round(datetime, period , const(origin)) + Impl::template vector_vector_const( + sources->get_data(), arg1_column->get_data(), arg2.get(), + col_to->get_data(), null_map->get_data()); + } else { + const auto arg1_column = + check_and_get_column>(*arg1_col); + const auto arg2_column = + check_and_get_column>(*arg2_col); + DCHECK(arg1_column != nullptr); + DCHECK(arg2_column != nullptr); + // time_round(datetime, period, origin) + Impl::template vector_vector( + sources->get_data(), arg1_column->get_data(), arg2_column->get_data(), + col_to->get_data(), null_map->get_data()); + } } block.get_by_position(result).column = @@ -213,35 +247,34 @@ struct FloorCeilImpl { static constexpr auto name = Impl::name; template - static void vector(const PaddedPODArray& dates, PaddedPODArray& res, - NullMap& null_map) { - // vector_constant_delta(dates, Int32(1), res, null_map); + static void vector(const PaddedPODArray& dates, PaddedPODArray& res) { + // time_round(datetime) for (int i = 0; i < dates.size(); ++i) { if constexpr (std::is_same_v) { - Impl::template time_round>(dates[i], res[i], - null_map[i]); + Impl::template time_round>(dates[i], res[i]); } else if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], res[i], null_map[i]); + Impl::template time_round>(dates[i], + res[i]); } else { - Impl::template time_round(dates[i], res[i], null_map[i]); + Impl::template time_round(dates[i], res[i]); } } } template static void vector_constant(const PaddedPODArray& dates, NativeType origin_date, - PaddedPODArray& res, NullMap& null_map) { + PaddedPODArray& res) { + // time_round(datetime, const(origin)) for (int i = 0; i < dates.size(); ++i) { if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], Int32(1), origin_date, res[i], null_map[i]); + Impl::template time_round_with_constant_optimization< + UInt32, DateV2Value, 1>(dates[i], origin_date, res[i]); } else if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], Int32(1), origin_date, res[i], null_map[i]); + Impl::template time_round_with_constant_optimization< + UInt64, DateV2Value, 1>(dates[i], origin_date, res[i]); } else { - Impl::template time_round(dates[i], Int32(1), origin_date, - res[i], null_map[i]); + Impl::template time_round_with_constant_optimization( + dates[i], origin_date, res[i]); } } } @@ -249,16 +282,170 @@ struct FloorCeilImpl { template static void vector_constant_delta(const PaddedPODArray& dates, DeltaType period, PaddedPODArray& res, NullMap& null_map) { + // time_round(datetime,const(period)) + if (period < 1) { + null_map.resize_fill(dates.size(), true); + return; + } + for (int i = 0; i < dates.size(); ++i) { + if constexpr (std::is_same_v) { + Impl::template time_round>(dates[i], period, + res[i]); + } else if constexpr (std::is_same_v) { + Impl::template time_round>(dates[i], + period, res[i]); + } else { + Impl::template time_round(dates[i], period, res[i]); + } + } + } + + template + static void vector_const_const_with_constant_optimization( + const PaddedPODArray& dates, NativeType origin_date, + PaddedPODArray& res) { + for (int i = 0; i < dates.size(); ++i) { + if constexpr (std::is_same_v) { + Impl::template time_round_with_constant_optimization< + UInt32, DateV2Value, period>(dates[i], origin_date, + res[i]); + } else if constexpr (std::is_same_v) { + Impl::template time_round_with_constant_optimization< + UInt64, DateV2Value, period>(dates[i], origin_date, + res[i]); + } else { + Impl::template time_round_with_constant_optimization(dates[i], origin_date, + res[i]); + } + } + } + template + static void vector_const_const(const PaddedPODArray& dates, const DeltaType period, + NativeType origin_date, PaddedPODArray& res, + NullMap& null_map) { + if (period < 1) { + null_map.resize_fill(dates.size(), true); + return; + } + switch (period) { + case 1: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 2: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 3: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 4: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 5: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 6: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 7: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 8: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 9: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 10: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 11: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + case 12: { + vector_const_const_with_constant_optimization( + dates, origin_date, res); + break; + } + default: + for (int i = 0; i < dates.size(); ++i) { + if constexpr (std::is_same_v) { + Impl::template time_round>( + dates[i], period, origin_date, res[i]); + } else if constexpr (std::is_same_v) { + Impl::template time_round>( + dates[i], period, origin_date, res[i]); + } else { + Impl::template time_round(dates[i], period, + origin_date, res[i]); + } + } + } + } + + template + static void vector_const_vector(const PaddedPODArray& dates, const DeltaType period, + const PaddedPODArray& origin_dates, + PaddedPODArray& res, NullMap& null_map) { + if (period < 1) { + null_map.resize_fill(dates.size(), true); + return; + } for (int i = 0; i < dates.size(); ++i) { if constexpr (std::is_same_v) { Impl::template time_round>( - dates[i], period, res[i], null_map[i]); + dates[i], period, origin_dates[i], res[i]); } else if constexpr (std::is_same_v) { Impl::template time_round>( - dates[i], period, res[i], null_map[i]); + dates[i], period, origin_dates[i], res[i]); } else { - Impl::template time_round(dates[i], period, res[i], - null_map[i]); + Impl::template time_round(dates[i], period, + origin_dates[i], res[i]); + } + } + } + + template + static void vector_vector_const(const PaddedPODArray& dates, + const PaddedPODArray& periods, + NativeType origin_date, PaddedPODArray& res, + NullMap& null_map) { + for (int i = 0; i < dates.size(); ++i) { + if (periods[i] < 1) { + null_map[i] = true; + continue; + } + if constexpr (std::is_same_v) { + Impl::template time_round>( + dates[i], periods[i], origin_date, res[i]); + } else if constexpr (std::is_same_v) { + Impl::template time_round>( + dates[i], periods[i], origin_date, res[i]); + } else { + Impl::template time_round(dates[i], periods[i], + origin_date, res[i]); } } } @@ -266,17 +453,19 @@ struct FloorCeilImpl { template static void vector_vector(const PaddedPODArray& dates, const PaddedPODArray& origin_dates, - PaddedPODArray& res, NullMap& null_map) { + PaddedPODArray& res) { + // time_round(datetime, origin) for (int i = 0; i < dates.size(); ++i) { if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], Int32(1), origin_dates[i], res[i], null_map[i]); + Impl::template time_round_with_constant_optimization< + UInt32, DateV2Value, 1>(dates[i], origin_dates[i], res[i]); } else if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], Int32(1), origin_dates[i], res[i], null_map[i]); + Impl::template time_round_with_constant_optimization< + UInt64, DateV2Value, 1>(dates[i], origin_dates[i], + res[i]); } else { - Impl::template time_round( - dates[i], Int32(1), origin_dates[i], res[i], null_map[i]); + Impl::template time_round_with_constant_optimization( + dates[i], origin_dates[i], res[i]); } } } @@ -285,16 +474,20 @@ struct FloorCeilImpl { static void vector_vector(const PaddedPODArray& dates, const PaddedPODArray& periods, PaddedPODArray& res, NullMap& null_map) { + // time_round(datetime, period) for (int i = 0; i < dates.size(); ++i) { + if (periods[i] < 1) { + null_map[i] = true; + continue; + } if constexpr (std::is_same_v) { - Impl::template time_round>( - dates[i], periods[i], res[i], null_map[i]); + Impl::template time_round>(dates[i], + periods[i], res[i]); } else if constexpr (std::is_same_v) { Impl::template time_round>( - dates[i], periods[i], res[i], null_map[i]); + dates[i], periods[i], res[i]); } else { - Impl::template time_round(dates[i], periods[i], res[i], - null_map[i]); + Impl::template time_round(dates[i], periods[i], res[i]); } } } @@ -304,16 +497,135 @@ struct FloorCeilImpl { const PaddedPODArray& periods, const PaddedPODArray& origin_dates, PaddedPODArray& res, NullMap& null_map) { + // time_round(datetime, period, origin) for (int i = 0; i < dates.size(); ++i) { + if (periods[i] < 1) { + null_map[i] = true; + continue; + } if constexpr (std::is_same_v) { Impl::template time_round>( - dates[i], periods[i], origin_dates[i], res[i], null_map[i]); + dates[i], periods[i], origin_dates[i], res[i]); } else if constexpr (std::is_same_v) { Impl::template time_round>( - dates[i], periods[i], origin_dates[i], res[i], null_map[i]); + dates[i], periods[i], origin_dates[i], res[i]); } else { - Impl::template time_round( - dates[i], periods[i], origin_dates[i], res[i], null_map[i]); + Impl::template time_round(dates[i], periods[i], + origin_dates[i], res[i]); + } + } + } +}; + +#define FLOOR 0 +#define CEIL 1 + +template +struct TimeRoundOpt { + constexpr static bool can_use_optimize(int period) { + if constexpr (!std::is_same_v && Impl::Type == FLOOR) { + if constexpr (Impl::Unit == YEAR || Impl::Unit == DAY) { + return period == 1; + } + if constexpr (Impl::Unit == MONTH) { + return period <= 11 && 12 % period == 0; + } + if constexpr (Impl::Unit == HOUR) { + return period <= 23 && 24 % period == 0; + } + if constexpr (Impl::Unit == MINUTE) { + return period <= 59 && 60 % period == 0; + } + if constexpr (Impl::Unit == SECOND) { + return period <= 59 && 60 % period == 0; + } + } + return false; + } + + static void floor_opt(const DateValueType& ts2, DateValueType& ts1, int period) { + if (period == 1) { + floor_opt_one_period(ts2, ts1); + } else { + static constexpr uint64_t MASK_HOUR_FLOOR = + 0b1111111111111111111111111111111100000000000000000000000000000000; + static constexpr uint64_t MASK_MINUTE_FLOOR = + 0b1111111111111111111111111111111111111100000000000000000000000000; + static constexpr uint64_t MASK_SECOND_FLOOR = + 0b1111111111111111111111111111111111111111111100000000000000000000; + // Optimize the performance of the datetimev2 type on the floor operation. + // Now supports unit month hour minute seconde + if constexpr (Impl::Unit == MONTH && !std::is_same_v) { + int month = ts2.month() - 1; + int new_month = month / period * period; + if (new_month >= 12) { + new_month = new_month % 12; + } + ts1.set_time(ts2.year(), ts2.month(), 1, 0, 0, 0); + ts1.template set_time_unit(new_month + 1); + } + if constexpr (Impl::Unit == HOUR && !std::is_same_v) { + int hour = ts2.hour(); + int new_hour = hour / period * period; + if (new_hour >= 24) { + new_hour = new_hour % 24; + } + ts1.set_int_val(ts2.to_date_int_val() & MASK_HOUR_FLOOR); + ts1.template set_time_unit(new_hour); + } + if constexpr (Impl::Unit == MINUTE && + !std::is_same_v) { + int minute = ts2.minute(); + int new_minute = minute / period * period; + if (new_minute >= 60) { + new_minute = new_minute % 60; + } + ts1.set_int_val(ts2.to_date_int_val() & MASK_MINUTE_FLOOR); + ts1.template set_time_unit(new_minute); + } + if constexpr (Impl::Unit == SECOND && + !std::is_same_v) { + int second = ts2.second(); + int new_second = second / period * period; + if (new_second >= 60) { + new_second = new_second % 60; + } + ts1.set_int_val(ts2.to_date_int_val() & MASK_SECOND_FLOOR); + ts1.template set_time_unit(new_second); + } + } + } + + static void floor_opt_one_period(const DateValueType& ts2, DateValueType& ts1) { + if constexpr (Impl::Unit == YEAR) { + ts1.set_time(ts2.year(), 1, 1, 0, 0, 0); + } + if constexpr (Impl::Unit == MONTH) { + ts1.set_time(ts2.year(), ts2.month(), 1, 0, 0, 0); + } + if constexpr (Impl::Unit == DAY) { + ts1.set_time(ts2.year(), ts2.month(), ts2.day(), 0, 0, 0); + } + + // only DateTimeV2ValueType type have hour minute second + if constexpr (std::is_same_v>) { + static constexpr uint64_t MASK_HOUR_FLOOR = + 0b1111111111111111111111111111111100000000000000000000000000000000; + static constexpr uint64_t MASK_MINUTE_FLOOR = + 0b1111111111111111111111111111111111111100000000000000000000000000; + static constexpr uint64_t MASK_SECOND_FLOOR = + 0b1111111111111111111111111111111111111111111100000000000000000000; + + // Optimize the performance of the datetimev2 type on the floor operation. + // Now supports unit biger than SECOND + if constexpr (Impl::Unit == HOUR) { + ts1.set_int_val(ts2.to_date_int_val() & MASK_HOUR_FLOOR); + } + if constexpr (Impl::Unit == MINUTE) { + ts1.set_int_val(ts2.to_date_int_val() & MASK_MINUTE_FLOOR); + } + if constexpr (Impl::Unit == SECOND) { + ts1.set_int_val(ts2.to_date_int_val() & MASK_SECOND_FLOOR); } } } @@ -324,23 +636,18 @@ struct TimeRound { static constexpr auto name = Impl::name; static constexpr uint64_t FIRST_DAY = 19700101000000; static constexpr uint64_t FIRST_SUNDAY = 19700104000000; - static constexpr int8_t FLOOR = 0; - static constexpr int8_t CEIL = 1; static constexpr uint32_t MASK_YEAR_FOR_DATEV2 = ((uint32_t)-1) >> 23; static constexpr uint32_t MASK_YEAR_MONTH_FOR_DATEV2 = ((uint32_t)-1) >> 27; static constexpr uint64_t MASK_YEAR_FOR_DATETIMEV2 = ((uint64_t)-1) >> 18; static constexpr uint64_t MASK_YEAR_MONTH_FOR_DATETIMEV2 = ((uint64_t)-1) >> 22; + static constexpr uint64_t MASK_YEAR_MONTH_DAY_FOR_DATETIMEV2 = ((uint64_t)-1) >> 27; + static constexpr uint64_t MASK_YEAR_MONTH_DAY_HOUR_FOR_DATETIMEV2 = ((uint64_t)-1) >> 32; + static constexpr uint64_t MASK_YEAR_MONTH_DAY_HOUR_MINUTE_FOR_DATETIMEV2 = ((uint64_t)-1) >> 38; - template - static void time_round(const DateValueType& ts2, Int32 period, DateValueType& ts1, - UInt8& is_null) { - if (period < 1) { - is_null = true; - return; - } - + template + static void time_round(const DateValueType& ts2, const Int32 period, DateValueType& ts1) { int64_t diff; int64_t trivial_part_ts1; int64_t trivial_part_ts2; @@ -442,24 +749,26 @@ struct TimeRound { } if constexpr (Impl::Unit == DAY) { diff = ts2.daynr() - ts1.daynr(); - trivial_part_ts2 = ts2.hour() * 3600 + ts2.minute() * 60 + ts2.second(); - trivial_part_ts1 = ts1.hour() * 3600 + ts1.minute() * 60 + ts1.second(); + trivial_part_ts2 = ts2.to_date_int_val() & MASK_YEAR_MONTH_DAY_FOR_DATETIMEV2; + trivial_part_ts1 = ts1.to_date_int_val() & MASK_YEAR_MONTH_DAY_FOR_DATETIMEV2; } if constexpr (Impl::Unit == HOUR) { diff = (ts2.daynr() - ts1.daynr()) * 24 + (ts2.hour() - ts1.hour()); - trivial_part_ts2 = ts2.minute() * 60 + ts2.second(); - trivial_part_ts1 = ts1.minute() * 60 + ts1.second(); + trivial_part_ts2 = ts2.to_date_int_val() & MASK_YEAR_MONTH_DAY_HOUR_FOR_DATETIMEV2; + trivial_part_ts1 = ts1.to_date_int_val() & MASK_YEAR_MONTH_DAY_HOUR_FOR_DATETIMEV2; } if constexpr (Impl::Unit == MINUTE) { diff = (ts2.daynr() - ts1.daynr()) * 24 * 60 + (ts2.hour() - ts1.hour()) * 60 + (ts2.minute() - ts1.minute()); - trivial_part_ts2 = ts2.second(); - trivial_part_ts1 = ts1.second(); + trivial_part_ts2 = + ts2.to_date_int_val() & MASK_YEAR_MONTH_DAY_HOUR_MINUTE_FOR_DATETIMEV2; + trivial_part_ts1 = + ts1.to_date_int_val() & MASK_YEAR_MONTH_DAY_HOUR_MINUTE_FOR_DATETIMEV2; } if constexpr (Impl::Unit == SECOND) { diff = ts2.second_diff(ts1); - trivial_part_ts1 = 0; - trivial_part_ts2 = 0; + trivial_part_ts2 = ts2.microsecond(); + trivial_part_ts1 = ts1.microsecond(); } } @@ -482,134 +791,113 @@ struct TimeRound { : count); bool is_neg = step < 0; TimeInterval interval(Impl::Unit, is_neg ? -step : step, is_neg); - is_null = !ts1.template date_add_interval(interval); + ts1.template date_add_interval(interval); } - static constexpr uint64_t MASK_DAY_FLOOR = - 0b1111111111111111111111111110000000000000000000000000000000000000; - static constexpr uint64_t MASK_HOUR_FLOOR = - 0b1111111111111111111111111111111100000000000000000000000000000000; - static constexpr uint64_t MASK_MINUTE_FLOOR = - 0b1111111111111111111111111111111111111100000000000000000000000000; - static constexpr uint64_t MASK_SECOND_FLOOR = - 0b1111111111111111111111111111111111111111111100000000000000000000; - - static constexpr bool USE_OPTIMIZE_FLOOR = - Impl::Unit == DAY || Impl::Unit == HOUR || Impl::Unit == MINUTE || Impl::Unit == SECOND; - template - static void datetimev2_floor(const DateValueType& ts2, DateValueType& ts1) { - // Optimize the performance of the datetimev2 type on the floor operation. - // Now supports days, hours, minutes, and seconds. - if constexpr (Impl::Unit == DAY) { - ts1.set_int_val(ts2.to_date_int_val() & MASK_DAY_FLOOR); - } - if constexpr (Impl::Unit == HOUR) { - ts1.set_int_val(ts2.to_date_int_val() & MASK_HOUR_FLOOR); - } - if constexpr (Impl::Unit == MINUTE) { - ts1.set_int_val(ts2.to_date_int_val() & MASK_MINUTE_FLOOR); - } - if constexpr (Impl::Unit == SECOND) { - ts1.set_int_val(ts2.to_date_int_val() & MASK_SECOND_FLOOR); - } + template + static void time_round_with_constant_optimization(const DateValueType& ts2, + DateValueType& ts1) { + time_round(ts2, period, ts1); } - template - static void time_round(const DateValueType& ts2, DateValueType& ts1, UInt8& is_null) { + + template + static void time_round(const DateValueType& ts2, DateValueType& ts1) { static_assert(Impl::Unit != WEEK); - if constexpr (std::is_same_v> && - Impl::Type == FLOOR && USE_OPTIMIZE_FLOOR) { - datetimev2_floor(ts2, ts1); - is_null = false; - return; - }; - if constexpr (std::is_same_v) { - ts1.reset_zero_by_type(ts2.type()); - } - int64_t diff; - int64_t part; - if constexpr (Impl::Unit == YEAR) { - diff = ts2.year(); - part = (ts2.month() - 1) + (ts2.day() - 1) + ts2.hour() + ts2.minute() + ts2.second(); - } - if constexpr (Impl::Unit == MONTH) { - diff = ts2.year() * 12 + ts2.month() - 1; - part = (ts2.day() - 1) + ts2.hour() + ts2.minute() + ts2.second(); - } - if constexpr (Impl::Unit == DAY) { - diff = ts2.daynr(); - part = ts2.hour() + ts2.minute() + ts2.second(); - } - if constexpr (Impl::Unit == HOUR) { - diff = ts2.daynr() * 24 + ts2.hour(); - part = ts2.minute() + ts2.second(); - } - if constexpr (Impl::Unit == MINUTE) { - diff = ts2.daynr() * 24L * 60 + ts2.hour() * 60 + ts2.minute(); - part = ts2.second(); - } - if constexpr (Impl::Unit == SECOND) { - diff = ts2.daynr() * 24L * 60 * 60 + ts2.hour() * 60L * 60 + ts2.minute() * 60L + - ts2.second(); - part = 0; - if constexpr (std::is_same_v>) { - part = ts2.microsecond(); + if constexpr (TimeRoundOpt::can_use_optimize(1)) { + TimeRoundOpt::floor_opt_one_period(ts2, ts1); + } else { + if constexpr (std::is_same_v) { + ts1.reset_zero_by_type(ts2.type()); + } + int64_t diff; + int64_t part; + if constexpr (Impl::Unit == YEAR) { + diff = ts2.year(); + part = (ts2.month() - 1) + (ts2.day() - 1) + ts2.hour() + ts2.minute() + + ts2.second(); + } + if constexpr (Impl::Unit == MONTH) { + diff = ts2.year() * 12 + ts2.month() - 1; + part = (ts2.day() - 1) + ts2.hour() + ts2.minute() + ts2.second(); + } + if constexpr (Impl::Unit == DAY) { + diff = ts2.daynr(); + part = ts2.hour() + ts2.minute() + ts2.second(); + } + if constexpr (Impl::Unit == HOUR) { + diff = ts2.daynr() * 24 + ts2.hour(); + part = ts2.minute() + ts2.second(); + } + if constexpr (Impl::Unit == MINUTE) { + diff = ts2.daynr() * 24L * 60 + ts2.hour() * 60 + ts2.minute(); + part = ts2.second(); + } + if constexpr (Impl::Unit == SECOND) { + diff = ts2.daynr() * 24L * 60 * 60 + ts2.hour() * 60L * 60 + ts2.minute() * 60L + + ts2.second(); + part = 0; + if constexpr (std::is_same_v>) { + part = ts2.microsecond(); + } } - } - if constexpr (Impl::Type == CEIL) { - if (part) { - diff++; + if constexpr (Impl::Type == CEIL) { + if (part) { + diff++; + } } + TimeInterval interval(Impl::Unit, diff, 1); + ts1.template date_set_interval(interval); } - TimeInterval interval(Impl::Unit, diff, 1); - is_null = !ts1.template date_set_interval(interval); } template - static void time_round(NativeType date, Int32 period, NativeType origin_date, NativeType& res, - UInt8& is_null) { + static void time_round(NativeType date, Int32 period, NativeType origin_date, NativeType& res) { res = origin_date; auto ts2 = binary_cast(date); auto& ts1 = (DateValueType&)(res); - if (!ts2.is_valid_date() || !ts1.is_valid_date()) { - is_null = true; - return; - } - TimeRound::template time_round(ts2, period, ts1, is_null); + TimeRound::template time_round(ts2, period, ts1); + } + + template + static void time_round_with_constant_optimization(NativeType date, NativeType origin_date, + NativeType& res) { + res = origin_date; + auto ts2 = binary_cast(date); + auto& ts1 = (DateValueType&)(res); + TimeRound::template time_round_with_constant_optimization(ts2, + ts1); } template - static void time_round(NativeType date, Int32 period, NativeType& res, UInt8& is_null) { + static void time_round(NativeType date, Int32 period, NativeType& res) { auto ts2 = binary_cast(date); - if (!ts2.is_valid_date()) { - is_null = true; - return; - } auto& ts1 = (DateValueType&)(res); - if constexpr (Impl::Unit != WEEK) { - ts1.from_olap_datetime(FIRST_DAY); + + if (TimeRoundOpt::can_use_optimize(period)) { + TimeRoundOpt::floor_opt(ts2, ts1, period); } else { - // Only week use the FIRST SUNDAY - ts1.from_olap_datetime(FIRST_SUNDAY); - } + if constexpr (Impl::Unit != WEEK) { + ts1.from_olap_datetime(FIRST_DAY); + } else { + // Only week use the FIRST SUNDAY + ts1.from_olap_datetime(FIRST_SUNDAY); + } - TimeRound::template time_round(ts2, period, ts1, is_null); + TimeRound::template time_round(ts2, period, ts1); + } } template - static void time_round(NativeType date, NativeType& res, UInt8& is_null) { + static void time_round(NativeType date, NativeType& res) { auto ts2 = binary_cast(date); - if (!ts2.is_valid_date()) { - is_null = true; - return; - } auto& ts1 = (DateValueType&)(res); if constexpr (Impl::Unit != WEEK) { - TimeRound::template time_round(ts2, ts1, is_null); + TimeRound::template time_round(ts2, ts1); } else { // Only week use the FIRST SUNDAY ts1.from_olap_datetime(FIRST_SUNDAY); - TimeRound::template time_round(ts2, 1, ts1, is_null); + TimeRound::template time_round(ts2, 1, ts1); } } }; @@ -662,21 +950,21 @@ struct TimeRound { FunctionDateTimeFloorCeil>, VecDateTimeValue, Int32, 2, \ true>; -TIME_ROUND(YearFloor, year_floor, YEAR, false); -TIME_ROUND(MonthFloor, month_floor, MONTH, false); -TIME_ROUND(WeekFloor, week_floor, WEEK, false); -TIME_ROUND(DayFloor, day_floor, DAY, false); -TIME_ROUND(HourFloor, hour_floor, HOUR, false); -TIME_ROUND(MinuteFloor, minute_floor, MINUTE, false); -TIME_ROUND(SecondFloor, second_floor, SECOND, false); - -TIME_ROUND(YearCeil, year_ceil, YEAR, true); -TIME_ROUND(MonthCeil, month_ceil, MONTH, true); -TIME_ROUND(WeekCeil, week_ceil, WEEK, true); -TIME_ROUND(DayCeil, day_ceil, DAY, true); -TIME_ROUND(HourCeil, hour_ceil, HOUR, true); -TIME_ROUND(MinuteCeil, minute_ceil, MINUTE, true); -TIME_ROUND(SecondCeil, second_ceil, SECOND, true); +TIME_ROUND(YearFloor, year_floor, YEAR, FLOOR); +TIME_ROUND(MonthFloor, month_floor, MONTH, FLOOR); +TIME_ROUND(WeekFloor, week_floor, WEEK, FLOOR); +TIME_ROUND(DayFloor, day_floor, DAY, FLOOR); +TIME_ROUND(HourFloor, hour_floor, HOUR, FLOOR); +TIME_ROUND(MinuteFloor, minute_floor, MINUTE, FLOOR); +TIME_ROUND(SecondFloor, second_floor, SECOND, FLOOR); + +TIME_ROUND(YearCeil, year_ceil, YEAR, CEIL); +TIME_ROUND(MonthCeil, month_ceil, MONTH, CEIL); +TIME_ROUND(WeekCeil, week_ceil, WEEK, CEIL); +TIME_ROUND(DayCeil, day_ceil, DAY, CEIL); +TIME_ROUND(HourCeil, hour_ceil, HOUR, CEIL); +TIME_ROUND(MinuteCeil, minute_ceil, MINUTE, CEIL); +TIME_ROUND(SecondCeil, second_ceil, SECOND, CEIL); void register_function_datetime_floor_ceil(SimpleFunctionFactory& factory) { #define REGISTER_FUNC_WITH_DELTA_TYPE(CLASS, DELTA) \ diff --git a/be/src/vec/runtime/vdatetime_value.h b/be/src/vec/runtime/vdatetime_value.h index 55b95e4955d7a6..b3cc110529a95d 100644 --- a/be/src/vec/runtime/vdatetime_value.h +++ b/be/src/vec/runtime/vdatetime_value.h @@ -763,7 +763,7 @@ class DateV2Value { } void set_time(uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, - uint8_t second, uint32_t microsecond); + uint8_t second, uint32_t microsecond = 0); void set_time(uint8_t hour, uint8_t minute, uint8_t second, uint32_t microsecond);