This is an automated email from the ASF dual-hosted git repository.
zclll pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 58a3b1db0a7 [Fix](date) Fix the ambiguous usage of TimeInterval
(#55853)
58a3b1db0a7 is described below
commit 58a3b1db0a7a387d75c3e12d4a0aaa62f276db18
Author: linrrarity <[email protected]>
AuthorDate: Mon Sep 15 10:22:01 2025 +0800
[Fix](date) Fix the ambiguous usage of TimeInterval (#55853)
Several usages of `TimeInterval` did not used the `is_neg` parameter
correctly, leading to ambiguous and error‑prone behavior.
This PR converts all time quantity members of TimeInterval to unsigned
types and centralizes sign handling via `is_neg`.
---
.../aggregate_function_window_funnel.cpp | 3 +-
.../aggregate_function_window_funnel.h | 32 +-
.../function_date_or_datetime_computation.h | 2 +-
.../vec/functions/function_datetime_floor_ceil.cpp | 2 +-
be/src/vec/runtime/vdatetime_value.cpp | 22 +-
be/src/vec/runtime/vdatetime_value.h | 18 +-
.../aggregate_functions/vec_window_funnel_test.cpp | 8 +-
be/test/vec/runtime/vdatetime_value_test.cpp | 434 +++++++++++++++++++++
.../datetime_functions/test_date_floor_ceil.out | Bin 886 -> 5624 bytes
.../test_aggregate_window_functions.groovy | 4 +
.../datetime_functions/test_date_floor_ceil.groovy | 154 ++++++++
11 files changed, 641 insertions(+), 38 deletions(-)
diff --git
a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.cpp
b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.cpp
index e10896f0763..8799aed153a 100644
--- a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.cpp
+++ b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.cpp
@@ -37,8 +37,7 @@ AggregateFunctionPtr
create_aggregate_function_window_funnel(const std::string&
return nullptr;
}
if (argument_types[2]->get_primitive_type() == TYPE_DATETIMEV2) {
- return creator_without_type::create<
- AggregateFunctionWindowFunnel<PrimitiveType::TYPE_DATETIMEV2,
UInt64>>(
+ return creator_without_type::create<AggregateFunctionWindowFunnel>(
argument_types, result_is_nullable, attr);
} else {
LOG(WARNING) << "Only support DateTime type as window argument!";
diff --git a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h
b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h
index 5f98441c430..afad283f7f6 100644
--- a/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h
+++ b/be/src/vec/aggregate_functions/aggregate_function_window_funnel.h
@@ -32,6 +32,7 @@
#include "common/cast_set.h"
#include "common/exception.h"
+#include "common/status.h"
#include "util/binary_cast.hpp"
#include "util/simd/bits.h"
#include "vec/aggregate_functions/aggregate_function.h"
@@ -100,9 +101,9 @@ struct DataValue {
}
};
-template <PrimitiveType PrimitiveType, typename NativeType>
struct WindowFunnelState {
- static_assert(PrimitiveType == PrimitiveType::TYPE_DATETIMEV2);
+ static constexpr PrimitiveType PType = PrimitiveType::TYPE_DATETIMEV2;
+ using NativeType = UInt64;
using DateValueType = DateV2Value<DateTimeV2ValueType>;
int event_count = 0;
int64_t window;
@@ -125,8 +126,8 @@ struct WindowFunnelState {
void add(const IColumn** arg_columns, ssize_t row_num, int64_t win,
WindowFunnelMode mode) {
window = win;
window_funnel_mode = enable_mode ? mode : WindowFunnelMode::DEFAULT;
- events_list.dt.emplace_back(assert_cast<const
ColumnVector<PrimitiveType>&>(*arg_columns[2])
- .get_data()[row_num]);
+ events_list.dt.emplace_back(
+ assert_cast<const
ColumnVector<PType>&>(*arg_columns[2]).get_data()[row_num]);
for (int i = 0; i < event_count; i++) {
events_list.event_columns_data[i].emplace_back(
assert_cast<const ColumnUInt8&>(*arg_columns[3 +
i]).get_data()[row_num]);
@@ -160,6 +161,12 @@ struct WindowFunnelState {
int matched_count = 0;
DateValueType start_timestamp;
DateValueType end_timestamp;
+
+ if (window < 0) {
+ throw Exception(ErrorCode::INVALID_ARGUMENT,
+ "the sliding time window must be a positive
integer, but got: {}",
+ window);
+ }
TimeInterval interval(SECOND, window, false);
int column_idx = 0;
const auto& timestamp_data = events_list.dt;
@@ -342,21 +349,17 @@ struct WindowFunnelState {
}
};
-template <PrimitiveType PrimitiveType, typename NativeType>
class AggregateFunctionWindowFunnel
- : public IAggregateFunctionDataHelper<
- WindowFunnelState<PrimitiveType, NativeType>,
- AggregateFunctionWindowFunnel<PrimitiveType, NativeType>>,
+ : public IAggregateFunctionDataHelper<WindowFunnelState,
AggregateFunctionWindowFunnel>,
MultiExpression,
NullableAggregateFunction {
public:
AggregateFunctionWindowFunnel(const DataTypes& argument_types_)
- : IAggregateFunctionDataHelper<
- WindowFunnelState<PrimitiveType, NativeType>,
- AggregateFunctionWindowFunnel<PrimitiveType,
NativeType>>(argument_types_) {}
+ : IAggregateFunctionDataHelper<WindowFunnelState,
AggregateFunctionWindowFunnel>(
+ argument_types_) {}
void create(AggregateDataPtr __restrict place) const override {
- auto data = new (place) WindowFunnelState<PrimitiveType, NativeType>(
+ auto data = new (place) WindowFunnelState(
cast_set<int>(IAggregateFunction::get_argument_types().size()
- 3));
/// support window funnel mode from 2.0. See
`BeExecVersionManager::max_be_exec_version`
data->enable_mode = IAggregateFunction::version >= 3;
@@ -393,9 +396,8 @@ public:
void insert_result_into(ConstAggregateDataPtr __restrict place, IColumn&
to) const override {
this->data(const_cast<AggregateDataPtr>(place)).sort();
assert_cast<ColumnInt32&>(to).get_data().push_back(
- IAggregateFunctionDataHelper<
- WindowFunnelState<PrimitiveType, NativeType>,
- AggregateFunctionWindowFunnel<PrimitiveType,
NativeType>>::data(place)
+ IAggregateFunctionDataHelper<WindowFunnelState,
+
AggregateFunctionWindowFunnel>::data(place)
.get());
}
diff --git a/be/src/vec/functions/function_date_or_datetime_computation.h
b/be/src/vec/functions/function_date_or_datetime_computation.h
index b41b151378c..b67beb476db 100644
--- a/be/src/vec/functions/function_date_or_datetime_computation.h
+++ b/be/src/vec/functions/function_date_or_datetime_computation.h
@@ -74,7 +74,7 @@ auto date_time_add(const typename
PrimitiveTypeTraits<ArgType>::DataType::FieldT
// e.g.: for DatatypeDatetimeV2, cast from u64 to
DateV2Value<DateTimeV2ValueType>
auto ts_value = binary_cast<NativeType, ValueType>(t);
- TimeInterval interval(unit, delta, false);
+ TimeInterval interval(unit, std::abs(delta), delta < 0);
is_null = !(ts_value.template date_add_interval<unit>(interval));
// here DateValueType = ResultDateValueType
return binary_cast<ValueType, NativeType>(ts_value);
diff --git a/be/src/vec/functions/function_datetime_floor_ceil.cpp
b/be/src/vec/functions/function_datetime_floor_ceil.cpp
index 35cc98a10f7..a2d2dd85d78 100644
--- a/be/src/vec/functions/function_datetime_floor_ceil.cpp
+++ b/be/src/vec/functions/function_datetime_floor_ceil.cpp
@@ -487,7 +487,7 @@ private:
diff++;
}
}
- TimeInterval interval(Flag::Unit, diff, true);
+ TimeInterval interval(Flag::Unit, diff, false);
return ts_res.template date_set_interval<Flag::Unit>(interval);
}
}
diff --git a/be/src/vec/runtime/vdatetime_value.cpp
b/be/src/vec/runtime/vdatetime_value.cpp
index 9ca66297899..d480c3d04fa 100644
--- a/be/src/vec/runtime/vdatetime_value.cpp
+++ b/be/src/vec/runtime/vdatetime_value.cpp
@@ -254,8 +254,9 @@ bool VecDateTimeValue::from_date_str_base(const char*
date_str, size_t len,
date_val[5], _type)) {
return false;
}
- return sec_offset ? date_add_interval<TimeUnit::SECOND>(
- TimeInterval {TimeUnit::SECOND, sec_offset,
false})
+ return sec_offset ? date_add_interval<TimeUnit::SECOND>(TimeInterval {
+ TimeUnit::SECOND,
static_cast<uint64_t>(std::abs(sec_offset)),
+ sec_offset < 0})
: true;
}
@@ -1679,9 +1680,12 @@ bool VecDateTimeValue::date_set_interval(const
TimeInterval& interval) {
(unit == YEAR) || (unit == QUARTER) || (unit == MONTH) || (unit ==
DAY) ||
(unit == HOUR) || (unit == MINUTE) || (unit == SECOND),
"date_set_interval function now only support YEAR MONTH DAY HOUR
MINUTE SECOND type");
+ if (interval.is_neg) {
+ throw Exception(ErrorCode::INTERNAL_ERROR,
+ "date_set_interval only support positive interval");
+ }
if constexpr ((unit == SECOND) || (unit == MINUTE) || (unit == HOUR)) {
// This may change the day information
- //FIXME: interval must be positive.
int64_t seconds = interval.day * 86400L + interval.hour * 3600 +
interval.minute * 60 +
interval.second;
int64_t days = seconds / 86400;
@@ -2177,8 +2181,9 @@ bool DateV2Value<T>::from_date_str_base(const char*
date_str, size_t len, int sc
return check_range_and_set_time(date_val[0], date_val[1], date_val[2],
date_val[3], date_val[4],
date_val[5], date_val[6]) &&
- (sec_offset ? date_add_interval<TimeUnit::SECOND>(
- TimeInterval {TimeUnit::SECOND, sec_offset,
false})
+ (sec_offset ? date_add_interval<TimeUnit::SECOND>(TimeInterval {
+ TimeUnit::SECOND,
static_cast<uint64_t>(std::abs(sec_offset)),
+ sec_offset < 0})
: true);
}
@@ -3005,7 +3010,12 @@ bool DateV2Value<T>::date_set_interval(const
TimeInterval& interval) {
(unit == YEAR) || (unit == QUARTER) || (unit == MONTH) || (unit ==
DAY) ||
(unit == HOUR) || (unit == MINUTE) || (unit == SECOND),
"date_set_interval function now only support YEAR MONTH DAY HOUR
MINUTE SECOND type");
- //FIXME: interval must be positive
+
+ if (interval.is_neg) {
+ throw Exception(ErrorCode::INTERNAL_ERROR,
+ "date_set_interval only support positive interval");
+ }
+
if constexpr ((unit == SECOND) || (unit == MINUTE) || (unit == HOUR) ||
(unit == DAY)) {
set_zero();
// This may change the day information
diff --git a/be/src/vec/runtime/vdatetime_value.h
b/be/src/vec/runtime/vdatetime_value.h
index 0e6bb620377..75dde990b1d 100644
--- a/be/src/vec/runtime/vdatetime_value.h
+++ b/be/src/vec/runtime/vdatetime_value.h
@@ -75,14 +75,14 @@ enum TimeUnit {
};
struct TimeInterval {
- int64_t year;
- int64_t month;
- int64_t day;
- int64_t hour;
- int64_t minute;
- int64_t second;
- int64_t millisecond;
- int64_t microsecond;
+ uint64_t year;
+ uint64_t month;
+ uint64_t day;
+ uint64_t hour;
+ uint64_t minute;
+ uint64_t second;
+ uint64_t millisecond;
+ uint64_t microsecond;
bool is_neg;
TimeInterval()
@@ -96,7 +96,7 @@ struct TimeInterval {
microsecond(0),
is_neg(false) {}
- TimeInterval(TimeUnit unit, int64_t count, bool is_neg_param)
+ TimeInterval(TimeUnit unit, uint64_t count, bool is_neg_param)
: year(0),
month(0),
day(0),
diff --git a/be/test/vec/aggregate_functions/vec_window_funnel_test.cpp
b/be/test/vec/aggregate_functions/vec_window_funnel_test.cpp
index e86b0904c41..122977c351a 100644
--- a/be/test/vec/aggregate_functions/vec_window_funnel_test.cpp
+++ b/be/test/vec/aggregate_functions/vec_window_funnel_test.cpp
@@ -210,7 +210,7 @@ TEST_F(VWindowFunnelTest, testMax4SortedNoMerge) {
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(1));
- for (int win = -1; win < NUM_CONDS + 1; win++) {
+ for (int win = 0; win < NUM_CONDS + 1; win++) {
auto column_window = ColumnInt64::create();
for (int i = 0; i < NUM_CONDS; i++) {
column_window->insert(vectorized::Field::create_field<TYPE_BIGINT>(win));
@@ -272,7 +272,7 @@ TEST_F(VWindowFunnelTest, testMax4SortedMerge) {
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(1));
- for (int win = -1; win < NUM_CONDS + 1; win++) {
+ for (int win = 0; win < NUM_CONDS + 1; win++) {
auto column_window = ColumnInt64::create();
for (int i = 0; i < NUM_CONDS; i++) {
column_window->insert(vectorized::Field::create_field<TYPE_BIGINT>(win));
@@ -340,7 +340,7 @@ TEST_F(VWindowFunnelTest, testMax4ReverseSortedNoMerge) {
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
- for (int win = -1; win < NUM_CONDS + 1; win++) {
+ for (int win = 0; win < NUM_CONDS + 1; win++) {
auto column_window = ColumnInt64::create();
for (int i = 0; i < NUM_CONDS; i++) {
column_window->insert(vectorized::Field::create_field<TYPE_BIGINT>(win));
@@ -403,7 +403,7 @@ TEST_F(VWindowFunnelTest, testMax4ReverseSortedMerge) {
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
column_event4->insert(vectorized::Field::create_field<TYPE_BOOLEAN>(0));
- for (int win = -1; win < NUM_CONDS + 1; win++) {
+ for (int win = 0; win < NUM_CONDS + 1; win++) {
auto column_window = ColumnInt64::create();
for (int i = 0; i < NUM_CONDS; i++) {
column_window->insert(vectorized::Field::create_field<TYPE_BIGINT>(win));
diff --git a/be/test/vec/runtime/vdatetime_value_test.cpp
b/be/test/vec/runtime/vdatetime_value_test.cpp
index b811dbfd7a0..444be70bfb7 100644
--- a/be/test/vec/runtime/vdatetime_value_test.cpp
+++ b/be/test/vec/runtime/vdatetime_value_test.cpp
@@ -22,7 +22,9 @@
#include <string>
+#include "common/exception.h"
#include "gtest/gtest_pred_impl.h"
+#include "vec/core/types.h"
namespace doris::vectorized {
@@ -878,4 +880,436 @@ TEST(VDateTimeValueTest, datetime_diff_test) {
}
}
+TEST(VDateTimeValueTest, date_add_interval_positive_test) {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-01-15 10:30:45", 19);
+
+ // Test SECOND unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::SECOND, 30, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::SECOND>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 31);
+ EXPECT_EQ(result.second(), 15);
+ }
+
+ // Test MINUTE unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::MINUTE, 45, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::MINUTE>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 11);
+ EXPECT_EQ(result.minute(), 15);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test HOUR unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::HOUR, 5, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::HOUR>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 15);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test DAY unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::DAY, 10, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::DAY>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 25);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test WEEK unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::WEEK, 2, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::WEEK>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 29);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test MONTH unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::MONTH, 3, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::MONTH>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 4);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test QUARTER unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::QUARTER, 2, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::QUARTER>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 7);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test YEAR unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::YEAR, 2, false);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::YEAR>(interval));
+ EXPECT_EQ(result.year(), 2024);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 10);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+}
+
+TEST(VDateTimeValueTest, date_add_interval_negative_test) {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-06-15 15:30:45", 19);
+
+ // Test SECOND unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::SECOND, 50, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::SECOND>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 6);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 15);
+ EXPECT_EQ(result.minute(), 29);
+ EXPECT_EQ(result.second(), 55);
+ }
+
+ // Test MINUTE unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::MINUTE, 45, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::MINUTE>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 6);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 14);
+ EXPECT_EQ(result.minute(), 45);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test HOUR unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::HOUR, 20, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::HOUR>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 6);
+ EXPECT_EQ(result.day(), 14);
+ EXPECT_EQ(result.hour(), 19);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test DAY unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::DAY, 10, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::DAY>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 6);
+ EXPECT_EQ(result.day(), 5);
+ EXPECT_EQ(result.hour(), 15);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test MONTH unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::MONTH, 3, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::MONTH>(interval));
+ EXPECT_EQ(result.year(), 2022);
+ EXPECT_EQ(result.month(), 3);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 15);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+
+ // Test YEAR unit (negative)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval(TimeUnit::YEAR, 1, true);
+ EXPECT_TRUE(result.date_add_interval<TimeUnit::YEAR>(interval));
+ EXPECT_EQ(result.year(), 2021);
+ EXPECT_EQ(result.month(), 6);
+ EXPECT_EQ(result.day(), 15);
+ EXPECT_EQ(result.hour(), 15);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 45);
+ }
+}
+
+TEST(VDateTimeValueTest, date_set_interval_positive_test) {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-06-12 15:30:45", 19);
+
+ // Test SECOND unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.second = 123;
+ interval.minute = 45;
+ interval.hour = 12;
+ interval.day = 5;
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::SECOND>(interval));
+ EXPECT_EQ(result.year(), 0);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 5);
+ EXPECT_EQ(result.hour(), 12);
+ EXPECT_EQ(result.minute(), 47);
+ EXPECT_EQ(result.second(), 3);
+ }
+
+ // Test MINUTE unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.minute = 90;
+ interval.hour = 5;
+ interval.day = 2;
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::MINUTE>(interval));
+ EXPECT_EQ(result.year(), 0);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 2);
+ EXPECT_EQ(result.hour(), 6);
+ EXPECT_EQ(result.minute(), 30);
+ EXPECT_EQ(result.second(), 0);
+ }
+
+ // Test HOUR unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.hour = 30; // 1 day 6 hours
+ interval.day = 3;
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::HOUR>(interval));
+ EXPECT_EQ(result.year(), 0);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 4);
+ EXPECT_EQ(result.hour(), 6);
+ EXPECT_EQ(result.minute(), 0);
+ EXPECT_EQ(result.second(), 0);
+ }
+
+ // Test DAY unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.day = 100; // day 100 of year 1
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::DAY>(interval));
+ EXPECT_EQ(result.year(), 0);
+ EXPECT_EQ(result.month(), 4);
+ EXPECT_EQ(result.day(), 10);
+ EXPECT_EQ(result.hour(), 0);
+ EXPECT_EQ(result.minute(), 0);
+ EXPECT_EQ(result.second(), 0);
+ }
+
+ // Test MONTH unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.year = 2;
+ interval.month = 15; // 2 years 15 months = 3 years 3 months
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::MONTH>(interval));
+ EXPECT_EQ(result.year(), 3);
+ EXPECT_EQ(result.month(), 4);
+ EXPECT_EQ(result.day(), 1);
+ EXPECT_EQ(result.hour(), 0);
+ EXPECT_EQ(result.minute(), 0);
+ EXPECT_EQ(result.second(), 0);
+ }
+
+ // Test QUARTER unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.year = 1;
+ interval.month = 9; // 1 year + 3 quarters (9 months) = 1 year 9 months
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::QUARTER>(interval));
+ EXPECT_EQ(result.year(), 1);
+ EXPECT_EQ(result.month(), 10);
+ EXPECT_EQ(result.day(), 1);
+ EXPECT_EQ(result.hour(), 0);
+ EXPECT_EQ(result.minute(), 0);
+ EXPECT_EQ(result.second(), 0);
+ }
+
+ // Test YEAR unit
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.year = 2025;
+ interval.is_neg = false;
+ EXPECT_TRUE(result.date_set_interval<TimeUnit::YEAR>(interval));
+ EXPECT_EQ(result.year(), 2025);
+ EXPECT_EQ(result.month(), 1);
+ EXPECT_EQ(result.day(), 1);
+ EXPECT_EQ(result.hour(), 0);
+ EXPECT_EQ(result.minute(), 0);
+ EXPECT_EQ(result.second(), 0);
+ }
+}
+
+TEST(VDateTimeValueTest, date_set_interval_negative_test) {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-06-15 15:30:45", 19);
+
+ // Test SECOND unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.second = 30;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::SECOND>(interval),
Exception);
+ }
+
+ // Test MINUTE unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.minute = 30;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::MINUTE>(interval),
Exception);
+ }
+
+ // Test HOUR unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.hour = 5;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::HOUR>(interval),
Exception);
+ }
+
+ // Test DAY unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.day = 10;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::DAY>(interval),
Exception);
+ }
+
+ // Test MONTH unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.month = 3;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::MONTH>(interval),
Exception);
+ }
+
+ // Test QUARTER unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.month = 6;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::QUARTER>(interval),
Exception);
+ }
+
+ // Test YEAR unit with negative interval (should throw)
+ {
+ DateV2Value<DateTimeV2ValueType> result = dt;
+ TimeInterval interval;
+ interval.year = 1;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::YEAR>(interval),
Exception);
+ }
+
+ {
+ VecDateTimeValue data;
+ dt.from_date_str("2022-06-15 15:30:45", 19);
+ VecDateTimeValue result = data;
+ TimeInterval interval;
+ interval.year = 1;
+ interval.is_neg = true;
+
+ EXPECT_THROW(result.date_set_interval<TimeUnit::YEAR>(interval),
Exception);
+ }
+}
+
+TEST(VDateTimeValueTest, date_add_interval_edge_cases_test) {
+ // Test leap year handling
+ {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2020-02-29 12:00:00", 19); // Leap year
+ TimeInterval interval(TimeUnit::YEAR, 1, false);
+ EXPECT_TRUE(dt.date_add_interval<TimeUnit::YEAR>(interval));
+ EXPECT_EQ(dt.year(), 2021);
+ EXPECT_EQ(dt.month(), 2);
+ EXPECT_EQ(dt.day(), 28);
+ }
+
+ // Test month overflow
+ {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-01-31 12:00:00", 19);
+ TimeInterval interval(TimeUnit::MONTH, 1, false);
+ EXPECT_TRUE(dt.date_add_interval<TimeUnit::MONTH>(interval));
+ EXPECT_EQ(dt.year(), 2022);
+ EXPECT_EQ(dt.month(), 2);
+ EXPECT_EQ(dt.day(), 28);
+ }
+
+ // Test day overflow causing month change
+ {
+ DateV2Value<DateTimeV2ValueType> dt;
+ dt.from_date_str("2022-01-25 20:00:00", 19);
+ TimeInterval interval(TimeUnit::HOUR, 100, false); // 100 hours = 4+
days
+ EXPECT_TRUE(dt.date_add_interval<TimeUnit::HOUR>(interval));
+ EXPECT_EQ(dt.year(), 2022);
+ EXPECT_EQ(dt.month(), 1);
+ EXPECT_EQ(dt.day(), 30);
+ EXPECT_EQ(dt.hour(), 0);
+ }
+}
+
} // namespace doris::vectorized
diff --git
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.out
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.out
index 22379a2b71b..dc2fd78158e 100644
Binary files
a/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.out
and
b/regression-test/data/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.out
differ
diff --git
a/regression-test/suites/nereids_p0/sql_functions/aggregate_functions/test_aggregate_window_functions.groovy
b/regression-test/suites/nereids_p0/sql_functions/aggregate_functions/test_aggregate_window_functions.groovy
index 35240592b4a..7d396a2efee 100644
---
a/regression-test/suites/nereids_p0/sql_functions/aggregate_functions/test_aggregate_window_functions.groovy
+++
b/regression-test/suites/nereids_p0/sql_functions/aggregate_functions/test_aggregate_window_functions.groovy
@@ -518,5 +518,9 @@ suite("test_aggregate_window_functions") {
order_qt_agg_window_window_funnel """
select user_id, window_funnel(3600, "fixed", event_timestamp,
event_name = '登录', event_name = '访问', event_name = '下单', event_name = '付款')
over(partition by user_id) from test_aggregate_window_functions;
"""
+ test {
+ sql """select user_id, window_funnel(-1, "fixed", event_timestamp,
event_name = '登录', event_name = '访问', event_name = '下单', event_name = '付款')
over(partition by user_id) from test_aggregate_window_functions;"""
+ exception "the sliding time window must be a positive integer"
+ }
}
\ No newline at end of file
diff --git
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.groovy
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.groovy
index ffcf9e5eb63..c381b5b4685 100644
---
a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.groovy
+++
b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_floor_ceil.groovy
@@ -59,4 +59,158 @@ suite("test_date_floor_ceil") {
qt_x12 """ select date_ceil('0001-09-01 23:59:59.999999', interval -7
month); """
qt_x13 """ select date_ceil('0002-02-01 23:59:59.999999', interval -7
month); """
qt_x14 """ select date_ceil('9999-12-31 23:54:59.999999', interval 5
minute); """
+
+ qt_f_positive_1 """ select date_floor('2023-07-14 15:30:45', interval 3
second); """
+ qt_f_positive_2 """ select date_floor('2023-07-14 15:30:45', interval 10
minute); """
+ qt_f_positive_3 """ select date_floor('2023-07-14 15:30:45', interval 6
hour); """
+ qt_f_positive_4 """ select date_floor('2023-07-14 15:30:45', interval 7
day); """
+ qt_f_positive_5 """ select date_floor('2023-07-14 15:30:45', interval 3
month); """
+ qt_f_positive_6 """ select date_floor('2023-07-14 15:30:45', interval 2
quarter); """
+ qt_f_positive_7 """ select date_floor('2023-07-14 15:30:45', interval 5
year); """
+
+ qt_f_neg_1 """ select date_floor('2023-07-14 15:30:45', interval -3
second); """
+ qt_f_neg_2 """ select date_floor('2023-07-14 15:30:45', interval -10
minute); """
+ qt_f_neg_3 """ select date_floor('2023-07-14 15:30:45', interval -6 hour);
"""
+ qt_f_neg_4 """ select date_floor('2023-07-14 15:30:45', interval -7 day);
"""
+ qt_f_neg_5 """ select date_floor('2023-07-14 15:30:45', interval -3
month); """
+ qt_f_neg_6 """ select date_floor('2023-07-14 15:30:45', interval -2
quarter); """
+ qt_f_neg_7 """ select date_floor('2023-07-14 15:30:45', interval -5 year);
"""
+
+ qt_c_positive_1 """ select date_ceil('2023-07-14 15:30:45', interval 3
second); """
+ qt_c_positive_2 """ select date_ceil('2023-07-14 15:30:45', interval 10
minute); """
+ qt_c_positive_3 """ select date_ceil('2023-07-14 15:30:45', interval 6
hour); """
+ qt_c_positive_4 """ select date_ceil('2023-07-14 15:30:45', interval 7
day); """
+ qt_c_positive_5 """ select date_ceil('2023-07-14 15:30:45', interval 3
month); """
+ qt_c_positive_6 """ select date_ceil('2023-07-14 15:30:45', interval 2
quarter); """
+ qt_c_positive_7 """ select date_ceil('2023-07-14 15:30:45', interval 5
year); """
+
+ qt_c_neg_1 """ select date_ceil('2023-07-14 15:30:45', interval -3
second); """
+ qt_c_neg_2 """ select date_ceil('2023-07-14 15:30:45', interval -10
minute); """
+ qt_c_neg_3 """ select date_ceil('2023-07-14 15:30:45', interval -6 hour);
"""
+ qt_c_neg_4 """ select date_ceil('2023-07-14 15:30:45', interval -7 day);
"""
+ qt_c_neg_5 """ select date_ceil('2023-07-14 15:30:45', interval -3 month);
"""
+ qt_c_neg_6 """ select date_ceil('2023-07-14 15:30:45', interval -2
quarter); """
+ qt_c_neg_7 """ select date_ceil('2023-07-14 15:30:45', interval -5 year);
"""
+
+ qt_zero_interval_1 """ select date_floor('2023-07-14 15:30:45', interval 0
second); """
+ qt_zero_interval_2 """ select date_ceil('2023-07-14 15:30:45', interval 0
minute); """
+
+ qt_boundary_1 """ select date_floor('9999-12-31 23:59:58', interval 1
second); """
+ qt_boundary_2 """ select date_floor('9999-12-31 22:59:58', interval 1
hour); """
+ qt_boundary_3 """ select date_floor('9999-11-17 23:59:58', interval 1
month); """
+ qt_boundary_4 """ select date_ceil('9999-12-31 23:59:58', interval 1
second); """
+ qt_boundary_5 """ select date_ceil('9999-12-31 21:00:01', interval 1
hour); """
+ qt_boundary_6 """ select date_ceil('9999-10-17 23:59:58', interval 1
month); """
+
+ qt_three_param_1 """ select hour_floor('2023-07-14 15:30:45', 3,
'2023-01-01 00:00:00'); """
+ qt_three_param_2 """ select hour_floor('2023-07-14 15:30:45', 6,
'2023-01-01 02:00:00'); """
+ qt_three_param_3 """ select hour_floor('2023-07-14 15:30:45', 12,
'1970-01-01 00:00:00'); """
+ qt_three_param_4 """ select hour_floor('2023-07-14 15:30:45', 24,
'2023-01-01 00:00:00'); """
+
+ qt_three_param_5 """ select minute_floor('2023-07-14 15:30:45', 15,
'2023-01-01 00:00:00'); """
+ qt_three_param_6 """ select minute_floor('2023-07-14 15:30:45', 30,
'2023-01-01 00:05:00'); """
+ qt_three_param_7 """ select minute_floor('2023-07-14 15:30:45', 60,
'1970-01-01 00:00:00'); """
+
+ qt_three_param_8 """ select second_floor('2023-07-14 15:30:45', 10,
'2023-01-01 00:00:00'); """
+ qt_three_param_9 """ select second_floor('2023-07-14 15:30:45', 30,
'2023-01-01 00:00:05'); """
+ qt_three_param_10 """ select second_floor('2023-07-14 15:30:45', 60,
'1970-01-01 00:00:00'); """
+
+ qt_three_param_11 """ select hour_ceil('2023-07-14 15:30:45', 3,
'2023-01-01 00:00:00'); """
+ qt_three_param_12 """ select hour_ceil('2023-07-14 15:30:45', 6,
'2023-01-01 02:00:00'); """
+ qt_three_param_13 """ select hour_ceil('2023-07-14 15:30:45', 12,
'1970-01-01 00:00:00'); """
+
+ qt_three_param_14 """ select minute_ceil('2023-07-14 15:30:45', 15,
'2023-01-01 00:00:00'); """
+ qt_three_param_15 """ select minute_ceil('2023-07-14 15:30:45', 30,
'2023-01-01 00:05:00'); """
+
+ qt_three_param_16 """ select second_ceil('2023-07-14 15:30:45', 10,
'2023-01-01 00:00:00'); """
+ qt_three_param_17 """ select second_ceil('2023-07-14 15:30:45', 30,
'2023-01-01 00:00:05'); """
+
+ qt_three_param_18 """ select hour_floor('2023-07-14 15:30:45', 1,
'2023-07-14 15:30:45'); """
+ qt_three_param_19 """ select minute_floor('2023-07-14 15:30:45', 1,
'2023-07-14 15:30:45'); """
+ qt_three_param_20 """ select second_floor('2023-07-14 15:30:45', 1,
'2023-07-14 15:30:45'); """
+
+ qt_three_param_21 """ select hour_floor('2023-07-14 15:30:45', 2,
'2023-07-15 00:00:00'); """
+ qt_three_param_22 """ select minute_floor('2023-07-14 15:30:45', 10,
'2023-07-14 16:00:00'); """
+ qt_three_param_23 """ select second_floor('2023-07-14 15:30:45', 30,
'2023-07-14 15:31:00'); """
+
+ qt_three_param_24 """ select hour_floor('2023-07-14 15:30:45', 4,
'2020-01-01 00:00:00'); """
+ qt_three_param_25 """ select hour_floor('2023-07-14 15:30:45', 8,
'2025-01-01 00:00:00'); """
+
+ qt_three_param_26 """ select hour_floor('2023-07-14 15:30:45', 100,
'2023-01-01 00:00:00'); """
+ qt_three_param_27 """ select minute_floor('2023-07-14 15:30:45', 500,
'2023-01-01 00:00:00'); """
+ qt_three_param_28 """ select second_floor('2023-07-14 15:30:45', 3600,
'2023-01-01 00:00:00'); """
+
+ qt_three_param_29 """ select hour_ceil('2023-07-14 15:00:00', 3,
'2023-01-01 00:00:00'); """
+ qt_three_param_30 """ select minute_ceil('2023-07-14 15:30:00', 15,
'2023-01-01 00:00:00'); """
+ qt_three_param_31 """ select second_ceil('2023-07-14 15:30:45', 15,
'2023-01-01 00:00:00'); """
+
+ qt_three_param_32 """ select hour_floor('0001-01-01 01:00:00', 2,
'0001-01-01 00:00:00'); """
+ qt_three_param_33 """ select hour_floor('9999-12-31 23:00:00', 3,
'9999-12-31 00:00:00'); """
+ qt_three_param_34 """ select minute_floor('0001-01-01 00:01:00', 5,
'0001-01-01 00:00:00'); """
+ qt_three_param_35 """ select minute_floor('9999-12-31 23:59:00', 10,
'9999-12-31 23:00:00'); """
+
+ qt_three_param_36 """ select day_floor('2023-07-14 15:30:45', 3,
'2023-01-01 00:00:00'); """
+ qt_three_param_37 """ select day_floor('2023-07-14 15:30:45', 7,
'2023-07-01 00:00:00'); """
+ qt_three_param_38 """ select day_floor('2023-07-14 15:30:45', 15,
'1970-01-01 00:00:00'); """
+ qt_three_param_39 """ select day_floor('2023-07-14 15:30:45', 30,
'2023-01-15 00:00:00'); """
+
+ qt_three_param_40 """ select day_ceil('2023-07-14 15:30:45', 3,
'2023-01-01 00:00:00'); """
+ qt_three_param_41 """ select day_ceil('2023-07-14 15:30:45', 7,
'2023-07-01 00:00:00'); """
+ qt_three_param_42 """ select day_ceil('2023-07-14 15:30:45', 15,
'1970-01-01 00:00:00'); """
+ qt_three_param_43 """ select day_ceil('2023-07-14 15:30:45', 30,
'2023-01-15 00:00:00'); """
+
+ qt_three_param_44 """ select month_floor('2023-07-14 15:30:45', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_45 """ select month_floor('2023-07-14 15:30:45', 3,
'2023-02-01 00:00:00'); """
+ qt_three_param_46 """ select month_floor('2023-07-14 15:30:45', 6,
'1970-01-01 00:00:00'); """
+ qt_three_param_47 """ select month_floor('2023-07-14 15:30:45', 12,
'2022-06-01 00:00:00'); """
+
+ qt_three_param_48 """ select month_ceil('2023-07-14 15:30:45', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_49 """ select month_ceil('2023-07-14 15:30:45', 3,
'2023-02-01 00:00:00'); """
+ qt_three_param_50 """ select month_ceil('2023-07-14 15:30:45', 6,
'1970-01-01 00:00:00'); """
+ qt_three_param_51 """ select month_ceil('2023-07-14 15:30:45', 12,
'2022-06-01 00:00:00'); """
+
+ qt_three_param_52 """ select year_floor('2023-07-14 15:30:45', 2,
'2020-01-01 00:00:00'); """
+ qt_three_param_53 """ select year_floor('2023-07-14 15:30:45', 5,
'2021-01-01 00:00:00'); """
+ qt_three_param_54 """ select year_floor('2023-07-14 15:30:45', 10,
'1970-01-01 00:00:00'); """
+ qt_three_param_55 """ select year_floor('2023-07-14 15:30:45', 100,
'1900-01-01 00:00:00'); """
+
+ qt_three_param_56 """ select year_ceil('2023-07-14 15:30:45', 2,
'2020-01-01 00:00:00'); """
+ qt_three_param_57 """ select year_ceil('2023-07-14 15:30:45', 5,
'2021-01-01 00:00:00'); """
+ qt_three_param_58 """ select year_ceil('2023-07-14 15:30:45', 10,
'1970-01-01 00:00:00'); """
+ qt_three_param_59 """ select year_ceil('2023-07-14 15:30:45', 100,
'1900-01-01 00:00:00'); """
+
+ qt_three_param_60 """ select quarter_floor('2023-07-14 15:30:45', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_61 """ select quarter_floor('2023-07-14 15:30:45', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_62 """ select quarter_floor('2023-07-14 15:30:45', 1,
'2022-10-01 00:00:00'); """
+ qt_three_param_63 """ select quarter_floor('2023-11-20 10:15:30', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_64 """ select quarter_floor('2023-11-20 10:15:30', 2,
'2022-07-01 00:00:00'); """
+ qt_three_param_65 """ select quarter_floor('2023-02-28 12:00:00', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_66 """ select quarter_floor('2023-05-15 18:45:00', 1,
'2023-04-01 00:00:00'); """
+ qt_three_param_67 """ select quarter_floor('2023-08-10 09:30:00', 3,
'2020-01-01 00:00:00'); """
+ qt_three_param_68 """ select quarter_floor('2023-12-31 23:59:59', 1,
'2023-10-01 00:00:00'); """
+ qt_three_param_69 """ select quarter_floor('2024-01-01 00:00:00', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_70 """ select quarter_floor('2023-07-14 15:30:45', 4,
'1970-01-01 00:00:00'); """
+ qt_three_param_71 """ select quarter_floor('2023-07-14 15:30:45', 1,
'2023-07-01 00:00:00'); """
+
+ qt_three_param_72 """ select quarter_ceil('2023-07-14 15:30:45', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_73 """ select quarter_ceil('2023-07-14 15:30:45', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_74 """ select quarter_ceil('2023-07-14 15:30:45', 1,
'2022-10-01 00:00:00'); """
+ qt_three_param_75 """ select quarter_ceil('2023-11-20 10:15:30', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_76 """ select quarter_ceil('2023-11-20 10:15:30', 2,
'2022-07-01 00:00:00'); """
+ qt_three_param_77 """ select quarter_ceil('2023-02-28 12:00:00', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_78 """ select quarter_ceil('2023-05-15 18:45:00', 1,
'2023-04-01 00:00:00'); """
+ qt_three_param_79 """ select quarter_ceil('2023-08-10 09:30:00', 3,
'2020-01-01 00:00:00'); """
+ qt_three_param_80 """ select quarter_ceil('2023-12-31 23:59:59', 1,
'2023-10-01 00:00:00'); """
+ qt_three_param_81 """ select quarter_ceil('2024-01-01 00:00:00', 2,
'2023-01-01 00:00:00'); """
+ qt_three_param_82 """ select quarter_ceil('2023-07-14 15:30:45', 4,
'1970-01-01 00:00:00'); """
+ qt_three_param_83 """ select quarter_ceil('2023-07-14 15:30:45', 1,
'2023-07-01 00:00:00'); """
+
+ qt_three_param_84 """ select quarter_floor('2023-01-01 00:00:00', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_85 """ select quarter_ceil('2023-01-01 00:00:00', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_86 """ select quarter_floor('2023-03-31 23:59:59', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_87 """ select quarter_ceil('2023-04-01 00:00:01', 1,
'2023-01-01 00:00:00'); """
+ qt_three_param_88 """ select quarter_floor('9999-12-31 23:59:59', 1,
'9999-10-01 00:00:00'); """
+ qt_three_param_89 """ select quarter_ceil('0001-01-01 00:00:00', 1,
'0001-01-01 00:00:00'); """
+ qt_three_param_90 """ select quarter_floor('2023-06-30 23:59:59', 2,
'2022-01-01 00:00:00'); """
+ qt_three_param_91 """ select quarter_ceil('2023-07-01 00:00:01', 2,
'2022-01-01 00:00:00'); """
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]