This is an automated email from the ASF dual-hosted git repository.

kxiao pushed a commit to branch branch-2.0
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/branch-2.0 by this push:
     new d5d68839d18 [Opt](performance) Optimize timeround with minute / second 
#25073 (#25404)
d5d68839d18 is described below

commit d5d68839d18431561d03f7d3c5c62edc4fd452d3
Author: Mryange <[email protected]>
AuthorDate: Fri Oct 13 18:33:49 2023 +0800

    [Opt](performance) Optimize timeround with minute / second #25073 (#25404)
---
 .../vec/functions/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 ea45f01c141..ab36ec62df0 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 @@ public:
             null_map->get_data().resize_fill(input_rows_count, false);
 
             if constexpr (ArgNum == 1) {
-                Impl::template vector<NativeType>(sources->get_data(), 
col_to->get_data(),
-                                                  null_map->get_data());
+                Impl::template vector<NativeType>(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<const ColumnConst*>(&delta_column)) {
                     if 
(block.get_by_position(arguments[1]).type->get_type_id() !=
                         TypeIndex::Int32) {
+                        // time_round(datetime, const(origin))
                         Impl::template vector_constant<NativeType>(
                                 sources->get_data(),
                                 
delta_const_column->get_field().get<NativeType>(),
-                                col_to->get_data(), null_map->get_data());
+                                col_to->get_data());
                     } else {
+                        // time_round(datetime,const(period))
                         Impl::template vector_constant_delta<NativeType, 
DeltaValueType>(
                                 sources->get_data(), 
delta_const_column->get_field().get<Int32>(),
                                 col_to->get_data(), null_map->get_data());
@@ -170,31 +171,64 @@ public:
                 } else {
                     if (const auto* delta_vec_column0 =
                                 
check_and_get_column<ColumnVector<NativeType>>(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<ColumnVector<DeltaValueType>>(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<ColumnVector<DeltaValueType>>(*arg1_column_ptr);
-                const auto arg2_column =
-                        
check_and_get_column<ColumnVector<NativeType>>(*arg2_column_ptr);
-                DCHECK(arg1_column != nullptr);
-                DCHECK(arg2_column != nullptr);
-                Impl::template vector_vector<NativeType, DeltaValueType>(
-                        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<NativeType, 
DeltaValueType>(
+                            sources->get_data(), arg1.get<Int32>(), 
arg2.get<NativeType>(),
+                            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<ColumnVector<NativeType>>(*arg2_col);
+                    // time_round(datetime,const(period) , origin)
+                    Impl::template vector_const_vector<NativeType, 
DeltaValueType>(
+                            sources->get_data(), arg1.get<Int32>(), 
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<ColumnVector<DeltaValueType>>(*arg1_col);
+                    // time_round(datetime, period , const(origin))
+                    Impl::template vector_vector_const<NativeType, 
DeltaValueType>(
+                            sources->get_data(), arg1_column->get_data(), 
arg2.get<NativeType>(),
+                            col_to->get_data(), null_map->get_data());
+                } else {
+                    const auto arg1_column =
+                            
check_and_get_column<ColumnVector<DeltaValueType>>(*arg1_col);
+                    const auto arg2_column =
+                            
check_and_get_column<ColumnVector<NativeType>>(*arg2_col);
+                    DCHECK(arg1_column != nullptr);
+                    DCHECK(arg2_column != nullptr);
+                    // time_round(datetime, period, origin)
+                    Impl::template vector_vector<NativeType, DeltaValueType>(
+                            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 <typename NativeType>
-    static void vector(const PaddedPODArray<NativeType>& dates, 
PaddedPODArray<NativeType>& res,
-                       NullMap& null_map) {
-        // vector_constant_delta<NativeType, Int32>(dates, Int32(1), res, 
null_map);
+    static void vector(const PaddedPODArray<NativeType>& dates, 
PaddedPODArray<NativeType>& res) {
+        // time_round(datetime)
         for (int i = 0; i < dates.size(); ++i) {
             if constexpr (std::is_same_v<NativeType, UInt32>) {
-                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(dates[i], res[i],
-                                                                               
 null_map[i]);
+                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(dates[i], res[i]);
             } else if constexpr (std::is_same_v<NativeType, UInt64>) {
-                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        dates[i], res[i], null_map[i]);
+                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(dates[i],
+                                                                               
     res[i]);
             } else {
-                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
res[i], null_map[i]);
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
res[i]);
             }
         }
     }
 
     template <typename NativeType>
     static void vector_constant(const PaddedPODArray<NativeType>& dates, 
NativeType origin_date,
-                                PaddedPODArray<NativeType>& res, NullMap& 
null_map) {
+                                PaddedPODArray<NativeType>& res) {
+        // time_round(datetime, const(origin))
         for (int i = 0; i < dates.size(); ++i) {
             if constexpr (std::is_same_v<NativeType, UInt32>) {
-                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
-                        dates[i], Int32(1), origin_date, res[i], null_map[i]);
+                Impl::template time_round_with_constant_optimization<
+                        UInt32, DateV2Value<DateV2ValueType>, 1>(dates[i], 
origin_date, res[i]);
             } else if constexpr (std::is_same_v<NativeType, UInt64>) {
-                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        dates[i], Int32(1), origin_date, res[i], null_map[i]);
+                Impl::template time_round_with_constant_optimization<
+                        UInt64, DateV2Value<DateTimeV2ValueType>, 1>(dates[i], 
origin_date, res[i]);
             } else {
-                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
Int32(1), origin_date,
-                                                                   res[i], 
null_map[i]);
+                Impl::template time_round_with_constant_optimization<Int64, 
VecDateTimeValue, 1>(
+                        dates[i], origin_date, res[i]);
             }
         }
     }
@@ -249,16 +282,170 @@ struct FloorCeilImpl {
     template <typename NativeType, typename DeltaType>
     static void vector_constant_delta(const PaddedPODArray<NativeType>& dates, 
DeltaType period,
                                       PaddedPODArray<NativeType>& 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<NativeType, UInt32>) {
+                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(dates[i], period,
+                                                                               
 res[i]);
+            } else if constexpr (std::is_same_v<NativeType, UInt64>) {
+                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(dates[i],
+                                                                               
     period, res[i]);
+            } else {
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
period, res[i]);
+            }
+        }
+    }
+
+    template <typename NativeType, typename DeltaType, UInt32 period>
+    static void vector_const_const_with_constant_optimization(
+            const PaddedPODArray<NativeType>& dates, NativeType origin_date,
+            PaddedPODArray<NativeType>& res) {
+        for (int i = 0; i < dates.size(); ++i) {
+            if constexpr (std::is_same_v<NativeType, UInt32>) {
+                Impl::template time_round_with_constant_optimization<
+                        UInt32, DateV2Value<DateV2ValueType>, 
period>(dates[i], origin_date,
+                                                                      res[i]);
+            } else if constexpr (std::is_same_v<NativeType, UInt64>) {
+                Impl::template time_round_with_constant_optimization<
+                        UInt64, DateV2Value<DateTimeV2ValueType>, 
period>(dates[i], origin_date,
+                                                                          
res[i]);
+            } else {
+                Impl::template time_round_with_constant_optimization<Int64, 
VecDateTimeValue,
+                                                                     
period>(dates[i], origin_date,
+                                                                             
res[i]);
+            }
+        }
+    }
+    template <typename NativeType, typename DeltaType>
+    static void vector_const_const(const PaddedPODArray<NativeType>& dates, 
const DeltaType period,
+                                   NativeType origin_date, 
PaddedPODArray<NativeType>& 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<NativeType, 
DeltaType, 1>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 2: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 2>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 3: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 3>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 4: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 4>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 5: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 5>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 6: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 6>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 7: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 7>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 8: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 8>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 9: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 9>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 10: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 10>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 11: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 11>(
+                    dates, origin_date, res);
+            break;
+        }
+        case 12: {
+            vector_const_const_with_constant_optimization<NativeType, 
DeltaType, 12>(
+                    dates, origin_date, res);
+            break;
+        }
+        default:
+            for (int i = 0; i < dates.size(); ++i) {
+                if constexpr (std::is_same_v<NativeType, UInt32>) {
+                    Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
+                            dates[i], period, origin_date, res[i]);
+                } else if constexpr (std::is_same_v<NativeType, UInt64>) {
+                    Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
+                            dates[i], period, origin_date, res[i]);
+                } else {
+                    Impl::template time_round<Int64, 
VecDateTimeValue>(dates[i], period,
+                                                                       
origin_date, res[i]);
+                }
+            }
+        }
+    }
+
+    template <typename NativeType, typename DeltaType>
+    static void vector_const_vector(const PaddedPODArray<NativeType>& dates, 
const DeltaType period,
+                                    const PaddedPODArray<NativeType>& 
origin_dates,
+                                    PaddedPODArray<NativeType>& 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<NativeType, UInt32>) {
                 Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
-                        dates[i], period, res[i], null_map[i]);
+                        dates[i], period, origin_dates[i], res[i]);
             } else if constexpr (std::is_same_v<NativeType, UInt64>) {
                 Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        dates[i], period, res[i], null_map[i]);
+                        dates[i], period, origin_dates[i], res[i]);
             } else {
-                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
period, res[i],
-                                                                   
null_map[i]);
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
period,
+                                                                   
origin_dates[i], res[i]);
+            }
+        }
+    }
+
+    template <typename NativeType, typename DeltaType>
+    static void vector_vector_const(const PaddedPODArray<NativeType>& dates,
+                                    const PaddedPODArray<DeltaType>& periods,
+                                    NativeType origin_date, 
PaddedPODArray<NativeType>& 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<NativeType, UInt32>) {
+                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
+                        dates[i], periods[i], origin_date, res[i]);
+            } else if constexpr (std::is_same_v<NativeType, UInt64>) {
+                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
+                        dates[i], periods[i], origin_date, res[i]);
+            } else {
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
periods[i],
+                                                                   
origin_date, res[i]);
             }
         }
     }
@@ -266,17 +453,19 @@ struct FloorCeilImpl {
     template <typename NativeType>
     static void vector_vector(const PaddedPODArray<NativeType>& dates,
                               const PaddedPODArray<NativeType>& origin_dates,
-                              PaddedPODArray<NativeType>& res, NullMap& 
null_map) {
+                              PaddedPODArray<NativeType>& res) {
+        // time_round(datetime, origin)
         for (int i = 0; i < dates.size(); ++i) {
             if constexpr (std::is_same_v<NativeType, UInt32>) {
-                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
-                        dates[i], Int32(1), origin_dates[i], res[i], 
null_map[i]);
+                Impl::template time_round_with_constant_optimization<
+                        UInt32, DateV2Value<DateV2ValueType>, 1>(dates[i], 
origin_dates[i], res[i]);
             } else if constexpr (std::is_same_v<NativeType, UInt64>) {
-                Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        dates[i], Int32(1), origin_dates[i], res[i], 
null_map[i]);
+                Impl::template time_round_with_constant_optimization<
+                        UInt64, DateV2Value<DateTimeV2ValueType>, 1>(dates[i], 
origin_dates[i],
+                                                                     res[i]);
             } else {
-                Impl::template time_round<Int64, VecDateTimeValue>(
-                        dates[i], Int32(1), origin_dates[i], res[i], 
null_map[i]);
+                Impl::template time_round_with_constant_optimization<Int64, 
VecDateTimeValue, 1>(
+                        dates[i], origin_dates[i], res[i]);
             }
         }
     }
@@ -285,16 +474,20 @@ struct FloorCeilImpl {
     static void vector_vector(const PaddedPODArray<NativeType>& dates,
                               const PaddedPODArray<DeltaType>& periods,
                               PaddedPODArray<NativeType>& 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<NativeType, UInt32>) {
-                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
-                        dates[i], periods[i], res[i], null_map[i]);
+                Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(dates[i],
+                                                                               
 periods[i], res[i]);
             } else if constexpr (std::is_same_v<NativeType, UInt64>) {
                 Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        dates[i], periods[i], res[i], null_map[i]);
+                        dates[i], periods[i], res[i]);
             } else {
-                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
periods[i], res[i],
-                                                                   
null_map[i]);
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
periods[i], res[i]);
             }
         }
     }
@@ -304,16 +497,135 @@ struct FloorCeilImpl {
                               const PaddedPODArray<DeltaType>& periods,
                               const PaddedPODArray<NativeType>& origin_dates,
                               PaddedPODArray<NativeType>& 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<NativeType, UInt32>) {
                 Impl::template time_round<UInt32, 
DateV2Value<DateV2ValueType>>(
-                        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<NativeType, UInt64>) {
                 Impl::template time_round<UInt64, 
DateV2Value<DateTimeV2ValueType>>(
-                        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<Int64, VecDateTimeValue>(
-                        dates[i], periods[i], origin_dates[i], res[i], 
null_map[i]);
+                Impl::template time_round<Int64, VecDateTimeValue>(dates[i], 
periods[i],
+                                                                   
origin_dates[i], res[i]);
+            }
+        }
+    }
+};
+
+#define FLOOR 0
+#define CEIL 1
+
+template <typename Impl, typename DateValueType>
+struct TimeRoundOpt {
+    constexpr static bool can_use_optimize(int period) {
+        if constexpr (!std::is_same_v<DateValueType, VecDateTimeValue> && 
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<DateValueType, VecDateTimeValue>) {
+                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<TimeUnit::MONTH>(new_month + 1);
+            }
+            if constexpr (Impl::Unit == HOUR && !std::is_same_v<DateValueType, 
VecDateTimeValue>) {
+                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<TimeUnit::HOUR>(new_hour);
+            }
+            if constexpr (Impl::Unit == MINUTE &&
+                          !std::is_same_v<DateValueType, VecDateTimeValue>) {
+                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<TimeUnit::MINUTE>(new_minute);
+            }
+            if constexpr (Impl::Unit == SECOND &&
+                          !std::is_same_v<DateValueType, VecDateTimeValue>) {
+                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<TimeUnit::SECOND>(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<DateValueType, 
DateV2Value<DateTimeV2ValueType>>) {
+            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 <typename NativeType, typename DateValueType>
-    static void time_round(const DateValueType& ts2, Int32 period, 
DateValueType& ts1,
-                           UInt8& is_null) {
-        if (period < 1) {
-            is_null = true;
-            return;
-        }
-
+    template <typename DateValueType>
+    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<Impl::Unit>(interval);
+        ts1.template date_add_interval<Impl::Unit>(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 <typename NativeType, typename DateValueType>
-    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 <typename DateValueType, Int32 period>
+    static void time_round_with_constant_optimization(const DateValueType& ts2,
+                                                      DateValueType& ts1) {
+        time_round<DateValueType>(ts2, period, ts1);
     }
-    template <typename NativeType, typename DateValueType>
-    static void time_round(const DateValueType& ts2, DateValueType& ts1, 
UInt8& is_null) {
+
+    template <typename DateValueType>
+    static void time_round(const DateValueType& ts2, DateValueType& ts1) {
         static_assert(Impl::Unit != WEEK);
-        if constexpr (std::is_same_v<DateValueType, 
DateV2Value<DateTimeV2ValueType>> &&
-                      Impl::Type == FLOOR && USE_OPTIMIZE_FLOOR) {
-            datetimev2_floor<NativeType, DateValueType>(ts2, ts1);
-            is_null = false;
-            return;
-        };
-        if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
-            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<DateValueType, 
DateV2Value<DateTimeV2ValueType>>) {
-                part = ts2.microsecond();
+        if constexpr (TimeRoundOpt<Impl, DateValueType>::can_use_optimize(1)) {
+            TimeRoundOpt<Impl, DateValueType>::floor_opt_one_period(ts2, ts1);
+        } else {
+            if constexpr (std::is_same_v<DateValueType, VecDateTimeValue>) {
+                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<DateValueType, 
DateV2Value<DateTimeV2ValueType>>) {
+                    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<Impl::Unit>(interval);
         }
-        TimeInterval interval(Impl::Unit, diff, 1);
-        is_null = !ts1.template date_set_interval<Impl::Unit>(interval);
     }
 
     template <typename NativeType, typename DateValueType>
-    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<NativeType, DateValueType>(date);
         auto& ts1 = (DateValueType&)(res);
-        if (!ts2.is_valid_date() || !ts1.is_valid_date()) {
-            is_null = true;
-            return;
-        }
-        TimeRound<Impl>::template time_round<NativeType, DateValueType>(ts2, 
period, ts1, is_null);
+        TimeRound<Impl>::template time_round<DateValueType>(ts2, period, ts1);
+    }
+
+    template <typename NativeType, typename DateValueType, Int32 period>
+    static void time_round_with_constant_optimization(NativeType date, 
NativeType origin_date,
+                                                      NativeType& res) {
+        res = origin_date;
+        auto ts2 = binary_cast<NativeType, DateValueType>(date);
+        auto& ts1 = (DateValueType&)(res);
+        TimeRound<Impl>::template 
time_round_with_constant_optimization<DateValueType, period>(ts2,
+                                                                               
                ts1);
     }
 
     template <typename NativeType, typename DateValueType>
-    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<NativeType, DateValueType>(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<Impl, DateValueType>::can_use_optimize(period)) {
+            TimeRoundOpt<Impl, DateValueType>::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<Impl>::template time_round<NativeType, DateValueType>(ts2, 
period, ts1, is_null);
+            TimeRound<Impl>::template time_round<DateValueType>(ts2, period, 
ts1);
+        }
     }
 
     template <typename NativeType, typename DateValueType>
-    static void time_round(NativeType date, NativeType& res, UInt8& is_null) {
+    static void time_round(NativeType date, NativeType& res) {
         auto ts2 = binary_cast<NativeType, DateValueType>(date);
-        if (!ts2.is_valid_date()) {
-            is_null = true;
-            return;
-        }
         auto& ts1 = (DateValueType&)(res);
         if constexpr (Impl::Unit != WEEK) {
-            TimeRound<Impl>::template time_round<NativeType, 
DateValueType>(ts2, ts1, is_null);
+            TimeRound<Impl>::template time_round<DateValueType>(ts2, ts1);
         } else {
             // Only week use the FIRST SUNDAY
             ts1.from_olap_datetime(FIRST_SUNDAY);
-            TimeRound<Impl>::template time_round<NativeType, 
DateValueType>(ts2, 1, ts1, is_null);
+            TimeRound<Impl>::template time_round<DateValueType>(ts2, 1, ts1);
         }
     }
 };
@@ -662,21 +950,21 @@ struct TimeRound {
             FunctionDateTimeFloorCeil<FloorCeilImpl<TimeRound<CLASS>>, 
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 55b95e4955d..b3cc110529a 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -763,7 +763,7 @@ public:
     }
 
     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);
 


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]


Reply via email to