diff --git a/be/src/vec/functions/date_format_type.h b/be/src/vec/functions/date_format_type.h index 9b66d5d8fb55e6..d0785900c9c880 100644 --- a/be/src/vec/functions/date_format_type.h +++ b/be/src/vec/functions/date_format_type.h @@ -156,6 +156,154 @@ struct yyyyMMImpl { } }; +struct dd_HHImpl { + constexpr static size_t row_size = 5; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.day(), buf, i); + buf[i++] = ' '; + put_two_digits(date_value.hour(), buf, i); + return i; + } +}; + +struct dd_HH_mmImpl { + constexpr static size_t row_size = 8; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.day(), buf, i); + buf[i++] = ' '; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + return i; + } +}; + +struct dd_HH_mm_ssImpl { + constexpr static size_t row_size = 11; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.day(), buf, i); + buf[i++] = ' '; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + return i; + } +}; + +struct dd_HH_mm_ss_SSSSSSImpl { + constexpr static size_t row_size = 18; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.day(), buf, i); + buf[i++] = ' '; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + buf[i++] = '.'; + int length = common::count_digits_fast(date_value.microsecond()); + std::fill(buf + i, buf + i + 6 - length, '0'); + std::to_chars(buf + i + 6 - length, buf + i + 6, date_value.microsecond()); + return i + 6; + } +}; + +struct HH_mmImpl { + constexpr static size_t row_size = 5; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + return i; + } +}; + +struct HH_mm_ssImpl { + constexpr static size_t row_size = 8; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + return i; + } +}; + +struct HH_mm_ss_SSSSSSImpl { + constexpr static size_t row_size = 15; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.hour(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + buf[i++] = '.'; + int length = common::count_digits_fast(date_value.microsecond()); + std::fill(buf + i, buf + i + 6 - length, '0'); + std::to_chars(buf + i + 6 - length, buf + i + 6, date_value.microsecond()); + return i + 6; + } +}; + +struct mm_ssImpl { + constexpr static size_t row_size = 5; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + return i; + } +}; + +struct mm_ss_SSSSSSImpl { + constexpr static size_t row_size = 12; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.minute(), buf, i); + buf[i++] = ':'; + put_two_digits(date_value.second(), buf, i); + buf[i++] = '.'; + int length = common::count_digits_fast(date_value.microsecond()); + std::fill(buf + i, buf + i + 6 - length, '0'); + std::to_chars(buf + i + 6 - length, buf + i + 6, date_value.microsecond()); + return i + 6; + } +}; + +struct ss_SSSSSSImpl { + constexpr static size_t row_size = 9; + template + size_t static date_to_str(const DateType& date_value, char* buf) { + int i = 0; + put_two_digits(date_value.second(), buf, i); + buf[i++] = '.'; + int length = common::count_digits_fast(date_value.microsecond()); + std::fill(buf + i, buf + i + 6 - length, '0'); + std::to_chars(buf + i + 6 - length, buf + i + 6, date_value.microsecond()); + return i + 6; + } +}; + struct yyyyImpl { constexpr static size_t row_size = 4; template diff --git a/be/src/vec/functions/date_time_transforms.h b/be/src/vec/functions/date_time_transforms.h index a4a8892dd4a806..300a734e83e063 100644 --- a/be/src/vec/functions/date_time_transforms.h +++ b/be/src/vec/functions/date_time_transforms.h @@ -303,6 +303,53 @@ struct MonthNameImpl { } }; +template +struct DateTimeV2FormatImpl { + static constexpr PrimitiveType OpArgType = TYPE_DATETIMEV2; + using ArgType = typename PrimitiveTypeTraits::CppType; + static constexpr auto name = FuncName; + static constexpr auto max_size = FormatImpl::row_size; + + static auto execute(const ArgType& dt, ColumnString::Chars& res_data, size_t& offset, + const char* const* /*names_ptr*/, FunctionContext* /*context*/) { + auto* buf = reinterpret_cast(&res_data[offset]); + offset += FormatImpl::date_to_str(dt, buf); + return offset; + } + + static DataTypes get_variadic_argument_types() { + return {std::make_shared::DataType>()}; + } +}; + +inline constexpr char kYearMonthName[] = "year_month"; +inline constexpr char kDayHourName[] = "day_hour"; +inline constexpr char kDayMinuteName[] = "day_minute"; +inline constexpr char kDaySecondName[] = "day_second"; +inline constexpr char kDayMicrosecondName[] = "day_microsecond"; +inline constexpr char kHourMinuteName[] = "hour_minute"; +inline constexpr char kHourSecondName[] = "hour_second"; +inline constexpr char kHourMicrosecondName[] = "hour_microsecond"; +inline constexpr char kMinuteSecondName[] = "minute_second"; +inline constexpr char kMinuteMicrosecondName[] = "minute_microsecond"; +inline constexpr char kSecondMicrosecondName[] = "second_microsecond"; + +using YearMonthImpl = DateTimeV2FormatImpl; +using DayHourImpl = DateTimeV2FormatImpl; +using DayMinuteImpl = DateTimeV2FormatImpl; +using DaySecondImpl = DateTimeV2FormatImpl; +using DayMicrosecondImpl = + DateTimeV2FormatImpl; +using HourMinuteImpl = DateTimeV2FormatImpl; +using HourSecondImpl = DateTimeV2FormatImpl; +using HourMicrosecondImpl = + DateTimeV2FormatImpl; +using MinuteSecondImpl = DateTimeV2FormatImpl; +using MinuteMicrosecondImpl = + DateTimeV2FormatImpl; +using SecondMicrosecondImpl = + DateTimeV2FormatImpl; + template struct DateFormatImpl { using DateType = typename PrimitiveTypeTraits::CppType; diff --git a/be/src/vec/functions/datetime_errors.h b/be/src/vec/functions/datetime_errors.h index ddb2fc5f5a5a1a..717b9e1ce1f967 100644 --- a/be/src/vec/functions/datetime_errors.h +++ b/be/src/vec/functions/datetime_errors.h @@ -60,6 +60,14 @@ template datelike_to_string(arg0), delta); } +// Throw for operations with a datelike and a string interval(e.g., date_add(date, interval '-1 2:3:4' day_second)) +template +[[noreturn]] inline void throw_out_of_bound_date_string(const char* op, DateValueType arg0, + std::string_view delta) { + throw Exception(ErrorCode::OUT_OF_BOUND, "Operation {} of {}, {} out of range", op, + datelike_to_string(arg0), delta); +} + // Throw for operations with a single integer argument (e.g., from_days daynr) [[noreturn]] inline void throw_out_of_bound_int(const char* op, int64_t value) { throw Exception(ErrorCode::OUT_OF_BOUND, "Operation {} of {} out of range", op, value); @@ -111,7 +119,7 @@ template } // Helper to get time unit name for error messages -inline const char* get_time_unit_name(TimeUnit unit) { +constexpr const char* get_time_unit_name(TimeUnit unit) { switch (unit) { case TimeUnit::YEAR: return "year_add"; @@ -133,6 +141,28 @@ inline const char* get_time_unit_name(TimeUnit unit) { return "millisecond_add"; case TimeUnit::MICROSECOND: return "microsecond_add"; + case TimeUnit::YEAR_MONTH: + return "year_month_add"; + case TimeUnit::DAY_HOUR: + return "day_hour_add"; + case TimeUnit::DAY_MINUTE: + return "day_minute_add"; + case TimeUnit::DAY_SECOND: + return "day_second_add"; + case TimeUnit::DAY_MICROSECOND: + return "day_microsecond_add"; + case TimeUnit::HOUR_MINUTE: + return "hour_minute_add"; + case TimeUnit::HOUR_SECOND: + return "hour_second_add"; + case TimeUnit::HOUR_MICROSECOND: + return "hour_microsecond_add"; + case TimeUnit::MINUTE_SECOND: + return "minute_second_add"; + case TimeUnit::MINUTE_MICROSECOND: + return "minute_microsecond_add"; + case TimeUnit::SECOND_MICROSECOND: + return "second_microsecond_add"; default: return "date_add"; } diff --git a/be/src/vec/functions/function_date_or_datetime_computation.cpp b/be/src/vec/functions/function_date_or_datetime_computation.cpp index d21dd46609e2ec..a2eba17f26c714 100644 --- a/be/src/vec/functions/function_date_or_datetime_computation.cpp +++ b/be/src/vec/functions/function_date_or_datetime_computation.cpp @@ -105,17 +105,30 @@ using FunctionTimestamptzAddMonths = FunctionDateOrDateTimeComputation>; using FunctionTimestamptzAddYears = FunctionDateOrDateTimeComputation>; +#define FUNCTION_TIME_UNION_CAL(TYPE) \ + using FunctionDatetimeAdd##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionDatetimeSub##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimestamptzAdd##TYPE = \ + FunctionDateOrDateTimeComputation>; \ + using FunctionTimestamptzSub##TYPE = \ + FunctionDateOrDateTimeComputation>; + +FUNCTION_TIME_UNION_CAL(SecondMicrosecond); +FUNCTION_TIME_UNION_CAL(MinuteMicrosecond); +FUNCTION_TIME_UNION_CAL(MinuteSecond); +FUNCTION_TIME_UNION_CAL(HourMicrosecond); +FUNCTION_TIME_UNION_CAL(HourSecond); +FUNCTION_TIME_UNION_CAL(HourMinute); +FUNCTION_TIME_UNION_CAL(DayMicrosecond); +FUNCTION_TIME_UNION_CAL(DaySecond); +FUNCTION_TIME_UNION_CAL(DayMinute); +FUNCTION_TIME_UNION_CAL(DayHour); +FUNCTION_TIME_UNION_CAL(YearMonth); using FunctionDatetimeAddQuarters = FunctionDateOrDateTimeComputation>; -using FunctionDatetimeAddDaySecond = - FunctionDateOrDateTimeComputation>; -using FunctionDatetimeAddDayHour = - FunctionDateOrDateTimeComputation>; -using FunctionDatetimeAddMinuteSecond = - FunctionDateOrDateTimeComputation>; -using FunctionDatetimeAddSecondMicrosecond = - FunctionDateOrDateTimeComputation>; using FunctionDatetimeSubMicroseconds = FunctionDateOrDateTimeComputation>; using FunctionDatetimeSubMilliseconds = @@ -139,14 +152,6 @@ using FunctionDatetimeSubYears = using FunctionTimestamptzAddQuarters = FunctionDateOrDateTimeComputation>; -using FunctionTimestamptzAddDaySecond = - FunctionDateOrDateTimeComputation>; -using FunctionTimestamptzAddDayHour = - FunctionDateOrDateTimeComputation>; -using FunctionTimestamptzAddMinuteSecond = - FunctionDateOrDateTimeComputation>; -using FunctionTimestamptzAddSecondMicrosecond = - FunctionDateOrDateTimeComputation>; using FunctionTimestamptzSubMicroseconds = FunctionDateOrDateTimeComputation>; using FunctionTimestamptzSubMilliseconds = @@ -250,10 +255,6 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); - factory.register_function(); - factory.register_function(); - factory.register_function(); - factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); @@ -264,10 +265,24 @@ void register_function_date_time_computation(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); - factory.register_function(); - factory.register_function(); - factory.register_function(); - factory.register_function(); + +#define REGISTER_TIME_UNION_CAL(TYPE) \ + factory.register_function(); \ + factory.register_function(); \ + factory.register_function(); \ + factory.register_function(); + + REGISTER_TIME_UNION_CAL(SecondMicrosecond); + REGISTER_TIME_UNION_CAL(MinuteMicrosecond); + REGISTER_TIME_UNION_CAL(MinuteSecond); + REGISTER_TIME_UNION_CAL(HourMicrosecond); + REGISTER_TIME_UNION_CAL(HourSecond); + REGISTER_TIME_UNION_CAL(HourMinute); + REGISTER_TIME_UNION_CAL(DayMicrosecond); + REGISTER_TIME_UNION_CAL(DaySecond); + REGISTER_TIME_UNION_CAL(DayMinute); + REGISTER_TIME_UNION_CAL(DayHour); + REGISTER_TIME_UNION_CAL(YearMonth); factory.register_function(); factory.register_function(); 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 eb48238383c6c3..0bc22ed0ef3aec 100644 --- a/be/src/vec/functions/function_date_or_datetime_computation.h +++ b/be/src/vec/functions/function_date_or_datetime_computation.h @@ -125,304 +125,230 @@ ADD_TIME_FUNCTION_IMPL(AddWeeksImpl, weeks_add, WEEK); ADD_TIME_FUNCTION_IMPL(AddMonthsImpl, months_add, MONTH); ADD_TIME_FUNCTION_IMPL(AddYearsImpl, years_add, YEAR); -template -struct AddDaySecondImpl { +template +class AddUnionTypeImpl { + static_assert(UnionType == SECOND_MICROSECOND || UnionType == MINUTE_MICROSECOND || + UnionType == MINUTE_SECOND || UnionType == HOUR_MICROSECOND || + UnionType == HOUR_SECOND || UnionType == HOUR_MINUTE || + UnionType == DAY_MICROSECOND || UnionType == DAY_SECOND || + UnionType == DAY_MINUTE || UnionType == DAY_HOUR || + UnionType == YEAR_MONTH, + "Unsupported Union TimeUnit for AddUnionTypeImpl"); + +public: static constexpr PrimitiveType ArgPType = PType; static constexpr PrimitiveType ReturnType = PType; - static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING; - using InputValueType = typename PrimitiveTypeTraits::DataType ::FieldType; + static constexpr PrimitiveType IntervalPType = PrimitiveType::TYPE_STRING; + using InputValueType = typename PrimitiveTypeTraits::DataType::FieldType; using ReturnValueType = InputValueType; - using IntervalDataType = typename PrimitiveTypeTraits::DataType; - using IntervalValueType = IntervalDataType::FieldType; // string - using ConvertedType = typename PrimitiveTypeTraits::DataType::FieldType; + using IntervalValueType = String; - static constexpr auto name = "day_second_add"; - static constexpr auto is_nullable = false; - - static inline ReturnValueType execute(const InputValueType& t, IntervalValueType delta) { - long seconds = parse_time_string_to_seconds(delta); - return date_time_add(t, seconds); - } + static constexpr auto name = get_time_unit_name(UnionType); static DataTypes get_variadic_argument_types() { return {std ::make_shared::DataType>(), std ::make_shared::DataType>()}; } - static long parse_time_string_to_seconds(IntervalValueType time_str_ref) { - bool is_negative = false; - auto time_str = StringRef {time_str_ref.data(), time_str_ref.length()}.trim(); - // string format: "d h:m:s" - size_t space_pos = time_str.find_first_of(' '); - if (space_pos == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, - "Invalid time format, missing space in '{}'", - std::string_view {time_str.data, time_str.size}); - } - // day - StringRef days_sub = time_str.substring(0, space_pos).trim(); - StringParser::ParseResult success; - int days = StringParser::string_to_int_internal(days_sub.data, days_sub.size, - &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid days format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - if (days < 0) { - is_negative = true; - } - - // hour:minute:second - StringRef time_hour_str = time_str.substring(space_pos + 1); - size_t colon1 = time_hour_str.find_first_of(':'); - if (colon1 == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid time format, missing ':' in '{}'", - std::string_view {time_str.data, time_str.size}); - } - size_t colon2_rel = time_hour_str.substring(colon1 + 1).find_first_of(':'); - size_t colon2 = - (colon2_rel != std::string::npos) ? colon1 + 1 + colon2_rel : std::string::npos; - if (colon2 == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid time format, missing ':' in '{}'", - std::string_view {time_str.data, time_str.size}); - } - StringRef hours_sub = time_hour_str.substring(0, colon1).trim(); - int hours = StringParser::string_to_int_internal(hours_sub.data, - hours_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid hours format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - StringRef minutes_sub = time_hour_str.substring(colon1 + 1, colon2 - colon1 - 1).trim(); - int minutes = StringParser::string_to_int_internal( - minutes_sub.data, minutes_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid minutes format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - StringRef seconds_sub = time_hour_str.substring(colon2 + 1).trim(); - int seconds = StringParser::string_to_int_internal( - seconds_sub.data, seconds_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid seconds format in '{}'", - std::string_view {time_str.data, time_str.size}); + static inline ReturnValueType execute(const InputValueType& t, const IntervalValueType& delta) { + TimeInterval interval; + get_interval_value(delta, interval); + InputValueType v = t; + if (!v.template date_add_interval(interval)) { + throw_out_of_bound_date_string(get_time_unit_name(UnionType), t, delta); } - - long part0 = days * 24 * 3600; - // NOTE: Compatible with MySQL - long part1 = std::abs(hours) * 3600 + std::abs(minutes) * 60 + std::abs(seconds); - if (is_negative) { - part1 *= -1; - } - return part0 + part1; - } -}; - -template -struct AddDayHourImpl { - static constexpr PrimitiveType ArgPType = PType; - static constexpr PrimitiveType ReturnType = PType; - static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING; - using InputValueType = typename PrimitiveTypeTraits::DataType ::FieldType; - using ReturnValueType = InputValueType; - using IntervalDataType = typename PrimitiveTypeTraits::DataType; - using IntervalValueType = IntervalDataType::FieldType; // string - using ConvertedType = typename PrimitiveTypeTraits::DataType::FieldType; - - static constexpr auto name = "day_hour_add"; - static constexpr auto is_nullable = false; - - static inline ReturnValueType execute(const InputValueType& t, IntervalValueType delta) { - long seconds = parse_day_hour_string_to_seconds(delta); - return date_time_add(t, seconds); + return v; } - static DataTypes get_variadic_argument_types() { - return {std ::make_shared::DataType>(), - std ::make_shared::DataType>()}; +#ifdef BE_TEST + // Test helper: parse interval string into TimeInterval for assertions in UTs. + static TimeInterval test_get_interval_value(const IntervalValueType& delta) { + TimeInterval interval; + get_interval_value(delta, interval); + return interval; } - static long parse_day_hour_string_to_seconds(IntervalValueType time_str_ref) { - bool is_negative = false; - auto time_str = StringRef {time_str_ref.data(), time_str_ref.length()}.trim(); - // string format: "d h" - size_t space_pos = time_str.find_first_of(' '); - if (space_pos == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, - "Invalid time format, missing space in '{}'", - std::string_view {time_str.data, time_str.size}); - } - // day - StringRef days_sub = time_str.substring(0, space_pos).trim(); - StringParser::ParseResult success; - int days = StringParser::string_to_int_internal(days_sub.data, days_sub.size, - &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid days format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - if (days < 0) { - is_negative = true; - } - - // hour - StringRef hours_sub = time_str.substring(space_pos + 1).trim(); - int hours = StringParser::string_to_int_internal(hours_sub.data, - hours_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid hours format in '{}'", - std::string_view {time_str.data, time_str.size}); - } +#endif - long part0 = days * 24 * 3600; - // NOTE: Compatible with MySQL - long part1 = std::abs(hours) * 3600; - if (is_negative) { - part1 *= -1; - } - return part0 + part1; - } -}; - -template -struct AddMinuteSecondImpl { - static constexpr PrimitiveType ArgPType = PType; - static constexpr PrimitiveType ReturnType = PType; - static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING; - using InputValueType = typename PrimitiveTypeTraits::DataType ::FieldType; - using ReturnValueType = InputValueType; - using IntervalDataType = typename PrimitiveTypeTraits::DataType; - using IntervalValueType = IntervalDataType::FieldType; // string - using ConvertedType = typename PrimitiveTypeTraits::DataType::FieldType; +private: + // Extracts numeric values from interval string + // Returns true on error + static bool extract_time_values(StringRef str_value, bool& is_negative, uint32_t count, + uint64_t* time_part, bool transform_msec) { + const char* cur = str_value.data; + const char* const end = cur + str_value.size; - static constexpr auto name = "minute_second_add"; - static constexpr auto is_nullable = false; + bool has_digit = false; - static inline ReturnValueType execute(const InputValueType& t, IntervalValueType delta) { - long seconds = parse_minute_second_string_to_seconds(delta); - return date_time_add(t, seconds); - } + auto advance_to_digit = [&](const char*& p) { + while (p < end && (*p < '0' || *p > '9')) ++p; + }; - static DataTypes get_variadic_argument_types() { - return {std ::make_shared::DataType>(), - std ::make_shared::DataType>()}; - } + // Skip leading spaces + while (cur < end && (*cur == ' ' || *cur == '\t')) ++cur; - static long parse_minute_second_string_to_seconds(IntervalValueType time_str_ref) { - bool is_negative = false; - auto time_str = StringRef {time_str_ref.data(), time_str_ref.length()}.trim(); - // string format: "m:s" - size_t colon_pos = time_str.find_first_of(':'); - if (colon_pos == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, - "Invalid time format, missing colon in '{}'", - std::string_view {time_str.data, time_str.size}); - } - // minute - StringRef minutes_sub = time_str.substring(0, colon_pos).trim(); - StringParser::ParseResult success; - int minutes = StringParser::string_to_int_internal( - minutes_sub.data, minutes_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid minutes format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - if (minutes < 0) { + // Check for negative sign + if (cur < end && *cur == '-') { is_negative = true; + ++cur; } - // second - StringRef second_sub = time_str.substring(colon_pos + 1).trim(); - int seconds = StringParser::string_to_int_internal( - second_sub.data, second_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid seconds format in '{}'", - std::string_view {time_str.data, time_str.size}); - } + advance_to_digit(cur); - long part0 = minutes * 60; - // NOTE: Compatible with MySQL - long part1 = std::abs(seconds); - if (is_negative) { - part1 *= -1; + int64_t msec_length = 0; + for (uint32_t i = 0; i < count; ++i) { + int64_t value = 0; + const char* start = cur; + for (; cur != end && (*cur >= '0' && *cur <= '9'); ++cur) { + // keep same behavior with MySQL + if (value > (LLONG_MAX - 10) / 10) { + return true; // overflow + } + value = value * 10LL + static_cast(*cur - '0'); + has_digit = true; + } + msec_length = 6 - (cur - start); + time_part[i] = value; + + advance_to_digit(cur); + + // If reached end but haven't filled all time_part, right-align existing time_part + if (cur == end && i != count - 1) { + ++i; + const size_t len = sizeof(*time_part) * i; + std::memmove(reinterpret_cast(time_part + count) - len, + reinterpret_cast(time_part + i) - len, len); + std::memset(time_part, 0, sizeof(*time_part) * (count - i)); + break; + } } - return part0 + part1; - } -}; -template -struct AddSecondMicrosecondImpl { - static constexpr PrimitiveType ArgPType = PType; - static constexpr PrimitiveType ReturnType = PType; - static constexpr PrimitiveType IntervalPType = PrimitiveType ::TYPE_STRING; - using InputValueType = typename PrimitiveTypeTraits::DataType ::FieldType; - using ReturnValueType = InputValueType; - using IntervalDataType = typename PrimitiveTypeTraits::DataType; - using IntervalValueType = IntervalDataType::FieldType; // string - using ConvertedType = typename PrimitiveTypeTraits::DataType::FieldType; - - static constexpr auto name = "second_microsecond_add"; - static constexpr auto is_nullable = false; + if (transform_msec && msec_length > 0 && msec_length <= 6) { + static constexpr uint64_t pow10[] = {1, 10, 100, 1000, 10000, 100000, 1000000}; + time_part[count - 1] *= pow10[msec_length]; + } - static inline ReturnValueType execute(const InputValueType& t, IntervalValueType delta) { - long microseconds = parse_second_microsecond_string_to_microseconds(delta); - return date_time_add(t, microseconds); + return (cur != end) || !has_digit; } - static DataTypes get_variadic_argument_types() { - return {std ::make_shared::DataType>(), - std ::make_shared::DataType>()}; - } - - static long parse_second_microsecond_string_to_microseconds(IntervalValueType time_str_ref) { + static void get_interval_value(const IntervalValueType& delta, TimeInterval& interval) { + // the longest expr is 'DAYS HOURS:MINUTES:SECONDS.MICROSECONDS' + // which contains 5 parts + uint64_t time_part[5] = {0}; bool is_negative = false; - auto time_str = StringRef {time_str_ref.data(), time_str_ref.length()}.trim(); - // string format: "s.microsecond" - size_t colon_pos = time_str.find_first_of('.'); - if (colon_pos == std::string::npos) { - throw Exception(ErrorCode::INVALID_ARGUMENT, - "Invalid time format, missing colon in '{}'", - std::string_view {time_str.data, time_str.size}); - } - // second - StringRef seconds_sub = time_str.substring(0, colon_pos).trim(); - StringParser::ParseResult success; - int seconds = StringParser::string_to_int_internal( - seconds_sub.data, seconds_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid seconds format in '{}'", - std::string_view {time_str.data, time_str.size}); - } - if (seconds < 0) { - is_negative = true; - } + interval = TimeInterval {}; - // microsecond - StringRef microsecond_sub = time_str.substring(colon_pos + 1).trim(); - auto microseconds = StringParser::string_to_int_internal( - microsecond_sub.data, microsecond_sub.size, &success); - if (success != StringParser::PARSE_SUCCESS) { - throw Exception(ErrorCode::INVALID_ARGUMENT, "Invalid microseconds format in '{}'", - std::string_view {time_str.data, time_str.size}); - } + auto str_ref = StringRef {delta.data(), delta.length()}.trim(); - long part0 = seconds; - // NOTE: Compatible with MySQL - int microsecond_len = microsecond_sub.to_string().starts_with("-") - ? microsecond_sub.size - 1 - : microsecond_sub.size; - if (microsecond_len < 6) { - microseconds *= pow(10, 6 - microsecond_len); + if constexpr (UnionType == YEAR_MONTH) { + // YEAR-MONTH: "YYYY-MM" format + if (extract_time_values(str_ref, is_negative, 2, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.year = time_part[0]; + interval.month = time_part[1]; + } else if constexpr (UnionType == DAY_HOUR) { + // DAY_HOUR: "DD HH" format + if (extract_time_values(str_ref, is_negative, 2, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.day = time_part[0]; + interval.hour = time_part[1]; + } else if constexpr (UnionType == DAY_MINUTE) { + // DAY_MINUTE: "DD HH:MM" format + if (extract_time_values(str_ref, is_negative, 3, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.day = time_part[0]; + interval.hour = time_part[1]; + interval.minute = time_part[2]; + } else if constexpr (UnionType == DAY_SECOND) { + // DAY_SECOND: "DD HH:MM:SS" format + if (extract_time_values(str_ref, is_negative, 4, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.day = time_part[0]; + interval.hour = time_part[1]; + interval.minute = time_part[2]; + interval.second = time_part[3]; + } else if constexpr (UnionType == DAY_MICROSECOND) { + // DAY_MICROSECOND: "DD HH:MM:SS.ssssss" format + if (extract_time_values(str_ref, is_negative, 5, time_part, true)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.day = time_part[0]; + interval.hour = time_part[1]; + interval.minute = time_part[2]; + interval.second = time_part[3]; + interval.microsecond = time_part[4]; + } else if constexpr (UnionType == HOUR_MINUTE) { + // HOUR_MINUTE: "HH:MM" format + if (extract_time_values(str_ref, is_negative, 2, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.hour = time_part[0]; + interval.minute = time_part[1]; + } else if constexpr (UnionType == HOUR_SECOND) { + // HOUR_SECOND: "HH:MM:SS" format + if (extract_time_values(str_ref, is_negative, 3, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.hour = time_part[0]; + interval.minute = time_part[1]; + interval.second = time_part[2]; + } else if constexpr (UnionType == HOUR_MICROSECOND) { + // HOUR_MICROSECOND: "HH:MM:SS.ssssss" format + if (extract_time_values(str_ref, is_negative, 4, time_part, true)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.hour = time_part[0]; + interval.minute = time_part[1]; + interval.second = time_part[2]; + interval.microsecond = time_part[3]; + } else if constexpr (UnionType == MINUTE_SECOND) { + // MINUTE_SECOND: "MM:SS" format + if (extract_time_values(str_ref, is_negative, 2, time_part, false)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.minute = time_part[0]; + interval.second = time_part[1]; + } else if constexpr (UnionType == MINUTE_MICROSECOND) { + // MINUTE_MICROSECOND: "MM:SS.ssssss" format + if (extract_time_values(str_ref, is_negative, 3, time_part, true)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.minute = time_part[0]; + interval.second = time_part[1]; + interval.microsecond = time_part[2]; + } else if constexpr (UnionType == SECOND_MICROSECOND) { + // SECOND_MICROSECOND: "SS.ssssss" format + if (extract_time_values(str_ref, is_negative, 2, time_part, true)) { + throw_invalid_string(get_time_unit_name(UnionType), str_ref); + } + interval.second = time_part[0]; + interval.microsecond = time_part[1]; } - long part1 = std::abs(microseconds); - if (is_negative) { - part1 *= -1; - } - return part0 * 1000000 + part1; + interval.is_neg = is_negative; } }; +#define DEFINE_ADD_UNION_TYPE_IMPL(CLASS, UNIT) \ + template \ + using CLASS = AddUnionTypeImpl; + +DEFINE_ADD_UNION_TYPE_IMPL(AddSecondMicrosecondImpl, SECOND_MICROSECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddMinuteMicrosecondImpl, MINUTE_MICROSECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddMinuteSecondImpl, MINUTE_SECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddHourMicrosecondImpl, HOUR_MICROSECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddHourSecondImpl, HOUR_SECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddHourMinuteImpl, HOUR_MINUTE); +DEFINE_ADD_UNION_TYPE_IMPL(AddDayMicrosecondImpl, DAY_MICROSECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddDaySecondImpl, DAY_SECOND); +DEFINE_ADD_UNION_TYPE_IMPL(AddDayMinuteImpl, DAY_MINUTE); +DEFINE_ADD_UNION_TYPE_IMPL(AddDayHourImpl, DAY_HOUR); +DEFINE_ADD_UNION_TYPE_IMPL(AddYearMonthImpl, YEAR_MONTH); + template struct AddQuartersImpl { static constexpr PrimitiveType ArgPType = PType; @@ -519,6 +445,103 @@ struct SubtractYearsImpl : SubtractIntervalImpl> { static constexpr auto name = "years_sub"; }; +template +struct SubtractUnionIntervalImpl { + static constexpr PrimitiveType ArgPType = Transform::ArgPType; + static constexpr PrimitiveType ReturnType = Transform::ReturnType; + using InputValueType = typename Transform::InputValueType; + using ReturnValueType = typename Transform::ReturnValueType; + static constexpr auto is_nullable = false; + static inline ReturnValueType execute(const InputValueType& t, const std::string& delta) { + auto str_ref = StringRef {delta.data(), delta.length()}.trim(); + + std::string negated_delta; + if (!str_ref.empty() && str_ref.data[0] == '-') { + negated_delta.assign(str_ref.data + 1, str_ref.size - 1); + } else { + negated_delta.reserve(str_ref.size + 1); + negated_delta = '-'; + negated_delta.append(str_ref.data, str_ref.size); + } + + return Transform::execute(t, std::string {negated_delta.data(), negated_delta.length()}); + } + + static DataTypes get_variadic_argument_types() { + return Transform::get_variadic_argument_types(); + } +}; + +template +struct SubtractYearMonthImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddYearMonthImpl::IntervalPType; + static constexpr auto name = "year_month_sub"; +}; + +template +struct SubtractDayHourImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddDayHourImpl::IntervalPType; + static constexpr auto name = "day_hour_sub"; +}; + +template +struct SubtractDayMinuteImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddDayMinuteImpl::IntervalPType; + static constexpr auto name = "day_minute_sub"; +}; + +template +struct SubtractDaySecondImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddDaySecondImpl::IntervalPType; + static constexpr auto name = "day_second_sub"; +}; + +template +struct SubtractDayMicrosecondImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddDayMicrosecondImpl::IntervalPType; + static constexpr auto name = "day_microsecond_sub"; +}; + +template +struct SubtractHourMinuteImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddHourMinuteImpl::IntervalPType; + static constexpr auto name = "hour_minute_sub"; +}; + +template +struct SubtractHourSecondImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddHourSecondImpl::IntervalPType; + static constexpr auto name = "hour_second_sub"; +}; + +template +struct SubtractHourMicrosecondImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddHourMicrosecondImpl::IntervalPType; + static constexpr auto name = "hour_microsecond_sub"; +}; + +template +struct SubtractMinuteSecondImpl : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = AddMinuteSecondImpl::IntervalPType; + static constexpr auto name = "minute_second_sub"; +}; + +template +struct SubtractMinuteMicrosecondImpl + : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = + AddMinuteMicrosecondImpl::IntervalPType; + static constexpr auto name = "minute_microsecond_sub"; +}; + +template +struct SubtractSecondMicrosecondImpl + : SubtractUnionIntervalImpl> { + static constexpr PrimitiveType IntervalPType = + AddSecondMicrosecondImpl::IntervalPType; + static constexpr auto name = "second_microsecond_sub"; +}; + #define DECLARE_DATE_FUNCTIONS(NAME, FN_NAME, RETURN_TYPE, STMT) \ template \ struct NAME { \ @@ -626,19 +649,28 @@ template ::CppType; using ValueType1 = typename PrimitiveTypeTraits::CppType; + using IntervalColumnType = typename PrimitiveTypeTraits::ColumnType; // arg1 maybe just delta value(e.g. DataTypeInt32, not datelike type) constexpr static bool CastType1 = is_date_type(DataType1); + // Use for compatibility with TimeUnionType interval(string type) + static inline ValueType1 get_element(const IntervalColumnType& data, size_t i) { + if constexpr (DataType1 == TYPE_STRING) { + return data.get_data_at(i).to_string(); + } else { + return data.get_data()[i]; + } + } + // execute on the null value's nested value may cause false positive exception, so use nullmaps to skip them. static void vector_vector(const PaddedPODArray& vec_from0, - const PaddedPODArray& vec_from1, - PaddedPODArray& vec_to, const NullMap* nullmap0, - const NullMap* nullmap1) { + const IntervalColumnType& vec_from1, PaddedPODArray& vec_to, + const NullMap* nullmap0, const NullMap* nullmap1) { for (size_t i = 0; i < vec_from0.size(); ++i) { if ((nullmap0 && (*nullmap0)[i]) || (nullmap1 && (*nullmap1)[i])) [[unlikely]] { continue; } - vec_to[i] = Transform::execute(vec_from0[i], vec_from1[i]); + vec_to[i] = Transform::execute(vec_from0[i], get_element(vec_from1, i)); } } @@ -658,17 +690,17 @@ struct DateTimeOp { } static void constant_vector(const ValueType0& from, PaddedPODArray& vec_to, - const PaddedPODArray& delta, const NullMap* nullmap0, + const IntervalColumnType& delta, const NullMap* nullmap0, const NullMap* nullmap1) { if (nullmap0 && (*nullmap0)[0]) [[unlikely]] { return; } - for (size_t i = 0; i < delta.size(); ++i) { + for (size_t i = 0; i < vec_to.size(); ++i) { if (nullmap1 && (*nullmap1)[i]) [[unlikely]] { continue; } - vec_to[i] = Transform::execute(from, delta[i]); + vec_to[i] = Transform::execute(from, get_element(delta, i)); } } }; @@ -735,12 +767,12 @@ class FunctionTimeDiff : public IFunction { assert_cast&>( nest_col1_const->get_data_column()); Op::vector_constant(sources->get_data(), res_col->get_data(), - col1_inside_const.get_data()[0], nullmap0, nullmap1); + Op::get_element(col1_inside_const, 0), nullmap0, nullmap1); } else { // vector-vector const auto& concrete_col1 = assert_cast&>(*nest_col1); - Op::vector_vector(sources->get_data(), concrete_col1.get_data(), - res_col->get_data(), nullmap0, nullmap1); + Op::vector_vector(sources->get_data(), concrete_col1, res_col->get_data(), nullmap0, + nullmap1); } // update result nullmap with inputs @@ -767,8 +799,8 @@ class FunctionTimeDiff : public IFunction { const ColumnPtr nested_col1 = remove_nullable(col1); const auto& concrete_col1 = assert_cast&>(*nested_col1); - Op::constant_vector(col0_inside_const.get_data()[0], res_col->get_data(), - concrete_col1.get_data(), nullmap0, nullmap1); + Op::constant_vector(col0_inside_const.get_data()[0], res_col->get_data(), concrete_col1, + nullmap0, nullmap1); // update result nullmap with inputs if (result_nullable) { @@ -857,32 +889,14 @@ class FunctionDateOrDateTimeComputation : public IFunction { // vector-const if (const auto* nest_col1_const = check_and_get_column(*nest_col1)) { rconst = true; - if constexpr (Transform::IntervalPType == TYPE_STRING) { - Op::vector_constant(sources->get_data(), res_col->get_data(), - nest_col1_const->get_data_at(0).to_string(), nullmap0, - nullmap1); - } else { - const auto& col1_inside_const = assert_cast( - nest_col1_const->get_data_column()); - Op::vector_constant(sources->get_data(), res_col->get_data(), - col1_inside_const.get_data()[0], nullmap0, nullmap1); - } + const auto& col1_inside_const = + assert_cast(nest_col1_const->get_data_column()); + Op::vector_constant(sources->get_data(), res_col->get_data(), + Op::get_element(col1_inside_const, 0), nullmap0, nullmap1); } else { // vector-vector - if constexpr (Transform::IntervalPType != TYPE_STRING) { - const auto& concrete_col1 = assert_cast(*nest_col1); - Op::vector_vector(sources->get_data(), concrete_col1.get_data(), - res_col->get_data(), nullmap0, nullmap1); - } else { - const auto* nest_col1_string = check_and_get_column(*nest_col1); - if (nest_col1_string->size() == 1) { - rconst = true; - Op::vector_constant(sources->get_data(), res_col->get_data(), - nest_col1_string->get_data_at(0).to_string(), nullmap0, - nullmap1); - } else { - return Status::NotSupported("Do not support vector-vector for string type"); - } - } + const auto& concrete_col1 = assert_cast(*nest_col1); + Op::vector_vector(sources->get_data(), concrete_col1, res_col->get_data(), nullmap0, + nullmap1); } // update result nullmap with inputs @@ -903,33 +917,28 @@ class FunctionDateOrDateTimeComputation : public IFunction { } else if (const auto* sources_const = check_and_get_column_const>( src_nested_col.get())) { - if constexpr (Transform::IntervalPType != TYPE_STRING) { - // const-vector - const auto& col0_inside_const = - assert_cast&>( - sources_const->get_data_column()); - const ColumnPtr nested_col1 = remove_nullable(col1); - const auto& concrete_col1 = assert_cast(*nested_col1); - Op::constant_vector(col0_inside_const.get_data()[0], res_col->get_data(), - concrete_col1.get_data(), nullmap0, nullmap1); - - // update result nullmap with inputs - if (result_nullable) { - auto null_map = ColumnBool::create(input_rows_count, 0); - NullMap& result_null_map = assert_cast(*null_map).get_data(); - if (nullmap0) { - VectorizedUtils::update_null_map(result_null_map, *nullmap0, true); - } - if (nullmap1) { // no const-const here. default impl deal it. - VectorizedUtils::update_null_map(result_null_map, *nullmap1); - } - block.get_by_position(result).column = - ColumnNullable::create(std::move(res_col), std::move(null_map)); - } else { - block.replace_by_position(result, std::move(res_col)); + // const-vector + const auto& col0_inside_const = assert_cast&>( + sources_const->get_data_column()); + const ColumnPtr nested_col1 = remove_nullable(col1); + const auto& concrete_col1 = assert_cast(*nested_col1); + Op::constant_vector(col0_inside_const.get_data()[0], res_col->get_data(), concrete_col1, + nullmap0, nullmap1); + + // update result nullmap with inputs + if (result_nullable) { + auto null_map = ColumnBool::create(input_rows_count, 0); + NullMap& result_null_map = assert_cast(*null_map).get_data(); + if (nullmap0) { + VectorizedUtils::update_null_map(result_null_map, *nullmap0, true); + } + if (nullmap1) { // no const-const here. default impl deal it. + VectorizedUtils::update_null_map(result_null_map, *nullmap1); } + block.get_by_position(result).column = + ColumnNullable::create(std::move(res_col), std::move(null_map)); } else { - return Status::NotSupported("Do not support const-vector for string type"); + block.replace_by_position(result, std::move(res_col)); } } else { // no const-const here. default impl deal it. return Status::InternalError( diff --git a/be/src/vec/functions/function_date_or_datetime_to_string.cpp b/be/src/vec/functions/function_date_or_datetime_to_string.cpp index b31efec8f3964c..01c069b9b02b66 100644 --- a/be/src/vec/functions/function_date_or_datetime_to_string.cpp +++ b/be/src/vec/functions/function_date_or_datetime_to_string.cpp @@ -214,6 +214,17 @@ using FunctionMonthNameV2 = FunctionDateOrDateTimeToString>; using FunctionDateTimeV2MonthName = FunctionDateOrDateTimeToString>; +using FunctionYearMonth = FunctionDateOrDateTimeToString; +using FunctionDayHour = FunctionDateOrDateTimeToString; +using FunctionDayMinute = FunctionDateOrDateTimeToString; +using FunctionDaySecond = FunctionDateOrDateTimeToString; +using FunctionDayMicrosecond = FunctionDateOrDateTimeToString; +using FunctionHourMinute = FunctionDateOrDateTimeToString; +using FunctionHourSecond = FunctionDateOrDateTimeToString; +using FunctionHourMicrosecond = FunctionDateOrDateTimeToString; +using FunctionMinuteSecond = FunctionDateOrDateTimeToString; +using FunctionMinuteMicrosecond = FunctionDateOrDateTimeToString; +using FunctionSecondMicrosecond = FunctionDateOrDateTimeToString; using FunctionDateIso8601 = FunctionDateOrDateTimeToString>; using FunctionDateTimeIso8601 = FunctionDateOrDateTimeToString>; @@ -224,6 +235,17 @@ void register_function_date_time_to_string(SimpleFunctionFactory& factory) { factory.register_function(); factory.register_function(); factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); + factory.register_function(); factory.register_function(); factory.register_function(); factory.register_function(); diff --git a/be/src/vec/runtime/vdatetime_value.cpp b/be/src/vec/runtime/vdatetime_value.cpp index 4cf32a0e831f36..72bca602a04927 100644 --- a/be/src/vec/runtime/vdatetime_value.cpp +++ b/be/src/vec/runtime/vdatetime_value.cpp @@ -3613,6 +3613,28 @@ template bool DateV2Value::date_add_interval::date_add_interval( const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); +template bool DateV2Value::date_add_interval( + const TimeInterval& interval); template bool DateV2Value::date_add_interval( const TimeInterval& interval); diff --git a/be/test/vec/function/function_time_test.cpp b/be/test/vec/function/function_time_test.cpp index 6e3d12c22ae177..5a09e5c1be96ea 100644 --- a/be/test/vec/function/function_time_test.cpp +++ b/be/test/vec/function/function_time_test.cpp @@ -1887,4 +1887,672 @@ TEST(VTimestampFunctionsTest, utc_impl_function_name_test) { EXPECT_STREQ("utc_time", UtcImpl::name); } +TEST(VTimestampFunctionsTest, add_union_interval_parse_test) { + { + auto interval = + AddUnionTypeImpl::test_get_interval_value(" -1-2"); + EXPECT_TRUE(interval.is_neg); + EXPECT_EQ(1u, interval.year); + EXPECT_EQ(2u, interval.month); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1--2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.year); + EXPECT_EQ(2u, interval.month); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value("5"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.year); + EXPECT_EQ(5u, interval.month); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value("1-2-3")), + Exception); + + { + auto interval = AddUnionTypeImpl::test_get_interval_value("1 2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1@@2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value("12"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(12u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value("1 2 3")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("2 3:04"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(2u, interval.day); + EXPECT_EQ(3u, interval.hour); + EXPECT_EQ(4u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1::02**03"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(3u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("30"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(30u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW( + (AddUnionTypeImpl::test_get_interval_value("1 2:3:4")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("3 4:5:6"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(3u, interval.day); + EXPECT_EQ(4u, interval.hour); + EXPECT_EQ(5u, interval.minute); + EXPECT_EQ(6u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "1::02**03::04"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(3u, interval.minute); + EXPECT_EQ(4u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("2:3:4"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(3u, interval.minute); + EXPECT_EQ(4u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW( + (AddUnionTypeImpl::test_get_interval_value("1 2:3:4:5")), + Exception); + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "4 5:06:07.008009"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(4u, interval.day); + EXPECT_EQ(5u, interval.hour); + EXPECT_EQ(6u, interval.minute); + EXPECT_EQ(7u, interval.second); + EXPECT_EQ(8009u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "7&8:9!?6.123"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(7u, interval.day); + EXPECT_EQ(8u, interval.hour); + EXPECT_EQ(9u, interval.minute); + EXPECT_EQ(6u, interval.second); + EXPECT_EQ(123000u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "-7!8@9$10^11"); + EXPECT_TRUE(interval.is_neg); + EXPECT_EQ(7u, interval.day); + EXPECT_EQ(8u, interval.hour); + EXPECT_EQ(9u, interval.minute); + EXPECT_EQ(10u, interval.second); + EXPECT_EQ(110000u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "1::02**03::04..5"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(1u, interval.day); + EXPECT_EQ(2u, interval.hour); + EXPECT_EQ(3u, interval.minute); + EXPECT_EQ(4u, interval.second); + EXPECT_EQ(500000u, interval.microsecond); + } + + { + auto interval = AddUnionTypeImpl::test_get_interval_value( + "1 2:3:4"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(1u, interval.hour); + EXPECT_EQ(2u, interval.minute); + EXPECT_EQ(3u, interval.second); + EXPECT_EQ(400000u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value( + "1 2:3:4:5:6")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("10:11"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(10u, interval.hour); + EXPECT_EQ(11u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1::2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(1u, interval.hour); + EXPECT_EQ(2u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("5"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(5u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value("1:2:3")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("9:10:11"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(9u, interval.hour); + EXPECT_EQ(10u, interval.minute); + EXPECT_EQ(11u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1::2**3"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(1u, interval.hour); + EXPECT_EQ(2u, interval.minute); + EXPECT_EQ(3u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("40"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(40u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW( + (AddUnionTypeImpl::test_get_interval_value("1:2:3:4")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "8:09:10.000011"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(8u, interval.hour); + EXPECT_EQ(9u, interval.minute); + EXPECT_EQ(10u, interval.second); + EXPECT_EQ(11u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "1::2**3..4"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(1u, interval.hour); + EXPECT_EQ(2u, interval.minute); + EXPECT_EQ(3u, interval.second); + EXPECT_EQ(400000u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("5.6"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(5u, interval.second); + EXPECT_EQ(600000u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value( + "1:2:3:4:5")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("7:08"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(7u, interval.minute); + EXPECT_EQ(8u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("1::2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(1u, interval.minute); + EXPECT_EQ(2u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("30"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(30u, interval.second); + EXPECT_EQ(0u, interval.microsecond); + } + + EXPECT_THROW( + (AddUnionTypeImpl::test_get_interval_value("1:2:3")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "6:07.123456"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(6u, interval.minute); + EXPECT_EQ(7u, interval.second); + EXPECT_EQ(123456u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "-10@11.000009"); + EXPECT_TRUE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(10u, interval.minute); + EXPECT_EQ(11u, interval.second); + EXPECT_EQ(9u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "3:4,56"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(3u, interval.minute); + EXPECT_EQ(4u, interval.second); + EXPECT_EQ(560000u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "1::2..3"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(1u, interval.minute); + EXPECT_EQ(2u, interval.second); + EXPECT_EQ(300000u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "9.8"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(9u, interval.second); + EXPECT_EQ(800000u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value( + "1:2:3:4")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "1,2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(1u, interval.second); + EXPECT_EQ(200000u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "1..2"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(1u, interval.second); + EXPECT_EQ(200000u, interval.microsecond); + } + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value("7"); + EXPECT_FALSE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(0u, interval.second); + EXPECT_EQ(700000u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value( + "1.2.3")), + Exception); + + { + auto interval = + AddUnionTypeImpl::test_get_interval_value( + "-5.654321"); + EXPECT_TRUE(interval.is_neg); + EXPECT_EQ(0u, interval.day); + EXPECT_EQ(0u, interval.hour); + EXPECT_EQ(0u, interval.minute); + EXPECT_EQ(5u, interval.second); + EXPECT_EQ(654321u, interval.microsecond); + } + + EXPECT_THROW((AddUnionTypeImpl::test_get_interval_value("abc")), + Exception); +} + +TEST(VTimestampFunctionsTest, add_union_functions_cover_all) { + const std::string base = "2020-01-02 03:04:05.123456"; + + { + std::string func_name = "year_month_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("1-2")}, std::string("2021-03-02 03:04:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-0-1")}, std::string("2019-12-02 03:04:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "day_hour_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("1 2")}, std::string("2020-01-03 05:04:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1 1")}, std::string("2020-01-01 02:04:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "day_minute_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("2 3:04")}, std::string("2020-01-04 06:08:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1 0:05")}, std::string("2020-01-01 02:59:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "day_second_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("0 0:0:2")}, std::string("2020-01-02 03:04:07.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1 0:0:5")}, std::string("2020-01-01 03:04:00.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "day_microsecond_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("0 0:0:0.100000")}, std::string("2020-01-02 03:04:05.223456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-0 0:0:0.000001")}, std::string("2020-01-02 03:04:05.123455")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "hour_minute_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("1:30")}, std::string("2020-01-02 04:34:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-0:05")}, std::string("2020-01-02 02:59:05.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "hour_second_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("2:0:3")}, std::string("2020-01-02 05:04:08.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1:00:05")}, std::string("2020-01-02 02:04:00.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "hour_microsecond_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("0:1:2.003004")}, std::string("2020-01-02 03:05:07.126460")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-0:00:00.000001")}, std::string("2020-01-02 03:04:05.123455")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "minute_second_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("5:6")}, std::string("2020-01-02 03:09:11.123456")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-0:05")}, std::string("2020-01-02 03:04:00.123456")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "minute_microsecond_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("1:2.003004")}, std::string("2020-01-02 03:05:07.126460")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1:00.000001")}, std::string("2020-01-02 03:03:05.123455")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } + + { + std::string func_name = "second_microsecond_add"; + InputTypeSet input_types = {{PrimitiveType::TYPE_DATETIMEV2, 6}, + Consted {PrimitiveType::TYPE_STRING}}; + DataSet data_set = { + {{base, std::string("3.004005")}, std::string("2020-01-02 03:04:08.127461")}, + }; + static_cast( + check_function(func_name, input_types, data_set, 6)); + + DataSet negative_set = { + {{base, std::string("-1.000001")}, std::string("2020-01-02 03:04:04.123455")}, + }; + static_cast( + check_function(func_name, input_types, negative_set, 6)); + } +} + } // namespace doris::vectorized diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 index 50ae1034c70b75..7b734f63038047 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisLexer.g4 @@ -174,9 +174,13 @@ DATEV2: 'DATEV2'; DATETIMEV1: 'DATETIMEV1'; DATEV1: 'DATEV1'; DAY: 'DAY'; -DAY_SECOND: 'DAY_SECOND'; +DAYOFWEEK: 'DAYOFWEEK'; +DAYOFYEAR: 'DAYOFYEAR'; DAYS: 'DAYS'; DAY_HOUR: 'DAY_HOUR'; +DAY_MICROSECOND: 'DAY_MICROSECOND'; +DAY_MINUTE: 'DAY_MINUTE'; +DAY_SECOND: 'DAY_SECOND'; DECIMAL: 'DECIMAL'; DECIMALV2: 'DECIMALV2'; DECIMALV3: 'DECIMALV3'; @@ -201,6 +205,8 @@ DIV: 'DIV'; DO: 'DO'; DORIS_INTERNAL_TABLE_ID: 'DORIS_INTERNAL_TABLE_ID'; DOUBLE: 'DOUBLE'; +DOW: 'DOW'; +DOY: 'DOY'; DROP: 'DROP'; DROPP: 'DROPP'; DUAL: 'DUAL'; @@ -276,6 +282,9 @@ HOSTNAME: 'HOSTNAME'; HOTSPOT: 'HOTSPOT'; HOUR: 'HOUR'; HOURS: 'HOURS'; +HOUR_MICROSECOND: 'HOUR_MICROSECOND'; +HOUR_MINUTE: 'HOUR_MINUTE'; +HOUR_SECOND: 'HOUR_SECOND'; HUB: 'HUB'; IDENTIFIED: 'IDENTIFIED'; IF: 'IF'; @@ -353,6 +362,7 @@ MAX: 'MAX'; MAXVALUE: 'MAXVALUE'; MEMO:'MEMO'; MERGE: 'MERGE'; +MICROSECOND: 'MICROSECOND'; MID: 'MID'; MIGRATE: 'MIGRATE'; MIGRATIONS: 'MIGRATIONS'; @@ -360,6 +370,7 @@ MIN: 'MIN'; MINUS: 'MINUS'; MINUTE: 'MINUTE'; MINUTES: 'MINUTES'; +MINUTE_MICROSECOND: 'MINUTE_MICROSECOND'; MINUTE_SECOND: 'MINUTE_SECOND'; MODIFY: 'MODIFY'; MONTH: 'MONTH'; @@ -599,6 +610,7 @@ WORKLOAD: 'WORKLOAD'; WRITE: 'WRITE'; XOR: 'XOR'; YEAR: 'YEAR'; +YEAR_MONTH: 'YEAR_MONTH'; //--DORIS-KEYWORD-LIST-END //============================ // End of the keywords list diff --git a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 index 54f33361907994..03bea7f57814ec 100644 --- a/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 +++ b/fe/fe-core/src/main/antlr4/org/apache/doris/nereids/DorisParser.g4 @@ -1663,7 +1663,7 @@ primaryExpression | base=primaryExpression DOT fieldName=identifier #dereference | LEFT_PAREN expression RIGHT_PAREN #parenthesizedExpression | KEY (dbName=identifier DOT)? keyName=identifier #encryptKey - | EXTRACT LEFT_PAREN field=identifier FROM (DATE | TIMESTAMP)? + | EXTRACT LEFT_PAREN field=unitIdentifier FROM (DATE | TIMESTAMP)? source=valueExpression RIGHT_PAREN #extract | primaryExpression COLLATE (identifier | STRING_LITERAL | DEFAULT) #collate ; @@ -1780,8 +1780,10 @@ interval ; unitIdentifier - : YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | DAY_SECOND | DAY_HOUR - | MINUTE_SECOND | SECOND_MICROSECOND + : YEAR | QUARTER | MONTH | WEEK | DAY | HOUR | MINUTE | SECOND | MICROSECOND | YEAR_MONTH + | DAY_HOUR | DAY_MINUTE | DAY_SECOND | DAY_MICROSECOND | HOUR_MINUTE | HOUR_SECOND + | HOUR_MICROSECOND | MINUTE_SECOND | MINUTE_MICROSECOND | SECOND_MICROSECOND + | DAYOFWEEK | DAYOFYEAR | DOW | DOY ; dataTypeWithNullable @@ -1997,6 +1999,8 @@ nonReserved | DATEV1 | DATEV2 | DAY + | DAYOFWEEK + | DAYOFYEAR | DAYS | DECIMAL | DECIMALV2 @@ -2011,6 +2015,8 @@ nonReserved | DISTINCTPCSA | DO | DORIS_INTERNAL_TABLE_ID + | DOW + | DOY | DUAL | DYNAMIC | E @@ -2205,6 +2211,7 @@ nonReserved | SCHEDULER | SCHEMA | SECOND + | MICROSECOND | SEPARATOR | SERIALIZABLE | SET_SESSION_VARIABLE diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java index 19f806b964d6cb..a4909747db09a3 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java +++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/BuiltinScalarFunctions.java @@ -168,10 +168,14 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.DateV2; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHour; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinute; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayName; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfMonth; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfYear; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysSub; @@ -239,6 +243,9 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.HourCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinute; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub; @@ -346,6 +353,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesSub; @@ -426,6 +435,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondTimestamp; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsDiff; @@ -553,6 +563,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Year; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonth; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearOfWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsAdd; @@ -717,10 +728,14 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(DateV2.class, "datev2"), scalar(DayCeil.class, "day_ceil"), scalar(DayFloor.class, "day_floor"), + scalar(DayHour.class, "day_hour"), + scalar(DayMicrosecond.class, "day_microsecond"), + scalar(DayMinute.class, "day_minute"), scalar(DayName.class, "dayname"), scalar(DayOfMonth.class, "day", "dayofmonth"), scalar(DayOfWeek.class, "dayofweek", "dow"), scalar(DayOfYear.class, "dayofyear", "doy"), + scalar(DaySecond.class, "day_second"), scalar(DaysAdd.class, "days_add", "date_add", "adddate"), scalar(DaysDiff.class, "days_diff"), scalar(DaysSub.class, "days_sub", "date_sub", "subdate"), @@ -784,6 +799,9 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(Hour.class, "hour"), scalar(HourCeil.class, "hour_ceil"), scalar(HourFloor.class, "hour_floor"), + scalar(HourMicrosecond.class, "hour_microsecond"), + scalar(HourMinute.class, "hour_minute"), + scalar(HourSecond.class, "hour_second"), scalar(HourFromUnixtime.class, "hour_from_unixtime"), scalar(HoursAdd.class, "hours_add"), scalar(HoursDiff.class, "hours_diff"), @@ -898,6 +916,8 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(MinuteCeil.class, "minute_ceil"), scalar(MinuteFloor.class, "minute_floor"), scalar(MinuteFromUnixtime.class, "minute_from_unixtime"), + scalar(MinuteMicrosecond.class, "minute_microsecond"), + scalar(MinuteSecond.class, "minute_second"), scalar(MinutesAdd.class, "minutes_add"), scalar(MinutesDiff.class, "minutes_diff"), scalar(MinutesSub.class, "minutes_sub"), @@ -979,6 +999,7 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(SecondCeil.class, "second_ceil"), scalar(SecondFloor.class, "second_floor"), scalar(SecondFromUnixtime.class, "second_from_unixtime"), + scalar(SecondMicrosecond.class, "second_microsecond"), scalar(SecondsAdd.class, "seconds_add"), scalar(SecondsDiff.class, "seconds_diff"), scalar(SecondsSub.class, "seconds_sub"), @@ -1114,6 +1135,7 @@ public class BuiltinScalarFunctions implements FunctionHelper { scalar(Year.class, "year"), scalar(YearCeil.class, "year_ceil"), scalar(YearFloor.class, "year_floor"), + scalar(YearMonth.class, "year_month"), scalar(YearOfWeek.class, "year_of_week", "yow"), scalar(YearWeek.class, "yearweek"), scalar(YearsAdd.class, "years_add"), diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java index 025dbafc0e8004..c93f151cf0c092 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/rules/analysis/DatetimeFunctionBinder.java @@ -34,18 +34,33 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.DayCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHourAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHourSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecondSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinuteAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinuteSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecondSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinuteAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinuteSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesSub; @@ -62,6 +77,7 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsSub; @@ -72,6 +88,8 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.WeeksSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonthAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonthSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsSub; @@ -307,12 +325,26 @@ private Expression processDateAdd(TimeUnit unit, Expression timestamp, Expressio return new MinutesAdd(timestamp, amount); case SECOND: return new SecondsAdd(timestamp, amount); + case YEAR_MONTH: + return new YearMonthAdd(timestamp, amount); case DAY_SECOND: return new DaySecondAdd(timestamp, amount); case DAY_HOUR: return new DayHourAdd(timestamp, amount); + case DAY_MINUTE: + return new DayMinuteAdd(timestamp, amount); + case DAY_MICROSECOND: + return new DayMicrosecondAdd(timestamp, amount); + case HOUR_MINUTE: + return new HourMinuteAdd(timestamp, amount); + case HOUR_SECOND: + return new HourSecondAdd(timestamp, amount); + case HOUR_MICROSECOND: + return new HourMicrosecondAdd(timestamp, amount); case MINUTE_SECOND: return new MinuteSecondAdd(timestamp, amount); + case MINUTE_MICROSECOND: + return new MinuteMicrosecondAdd(timestamp, amount); case SECOND_MICROSECOND: return new SecondMicrosecondAdd(timestamp, amount); default: @@ -339,6 +371,28 @@ private Expression processDateSub(TimeUnit unit, Expression timeStamp, Expressio return new MinutesSub(timeStamp, amount); case SECOND: return new SecondsSub(timeStamp, amount); + case YEAR_MONTH: + return new YearMonthSub(timeStamp, amount); + case DAY_SECOND: + return new DaySecondSub(timeStamp, amount); + case DAY_HOUR: + return new DayHourSub(timeStamp, amount); + case DAY_MINUTE: + return new DayMinuteSub(timeStamp, amount); + case DAY_MICROSECOND: + return new DayMicrosecondSub(timeStamp, amount); + case HOUR_MINUTE: + return new HourMinuteSub(timeStamp, amount); + case HOUR_SECOND: + return new HourSecondSub(timeStamp, amount); + case HOUR_MICROSECOND: + return new HourMicrosecondSub(timeStamp, amount); + case MINUTE_SECOND: + return new MinuteSecondSub(timeStamp, amount); + case MINUTE_MICROSECOND: + return new MinuteMicrosecondSub(timeStamp, amount); + case SECOND_MICROSECOND: + return new SecondMicrosecondSub(timeStamp, amount); default: throw new AnalysisException("Unsupported time stamp sub time unit: " + unit + ", supported time unit: YEAR/QUARTER/MONTH/WEEK/DAY/HOUR/MINUTE/SECOND"); diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java index 5cc40803fca782..c521c408f78c8d 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeArithmetic.java @@ -17,23 +17,285 @@ package org.apache.doris.nereids.trees.expressions.functions.executable; +import org.apache.doris.nereids.exceptions.AnalysisException; import org.apache.doris.nereids.trees.expressions.ExecFunction; import org.apache.doris.nereids.trees.expressions.Expression; import org.apache.doris.nereids.trees.expressions.literal.BigIntLiteral; import org.apache.doris.nereids.trees.expressions.literal.DateTimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.DateV2Literal; import org.apache.doris.nereids.trees.expressions.literal.IntegerLiteral; +import org.apache.doris.nereids.trees.expressions.literal.Interval.TimeUnit; import org.apache.doris.nereids.trees.expressions.literal.TimeV2Literal; import org.apache.doris.nereids.trees.expressions.literal.TimestampTzLiteral; import org.apache.doris.nereids.trees.expressions.literal.VarcharLiteral; import java.time.LocalDateTime; import java.time.temporal.ChronoUnit; +import java.util.Arrays; /** * executable function: date_add/sub, years/quarters/months/week/days/hours/minutes/seconds_add/sub, datediff */ public class DateTimeArithmetic { + private static final long[] POW_10 = { 1, 10, 100, 1000, 10000, 100000, 1000000 }; + private static final long MICROS_PER_SECOND = 1_000_000L; + private static final long MICROS_PER_MINUTE = Math.multiplyExact(MICROS_PER_SECOND, 60L); + private static final long MICROS_PER_HOUR = Math.multiplyExact(MICROS_PER_MINUTE, 60L); + private static final long MICROS_PER_DAY = Math.multiplyExact(MICROS_PER_HOUR, 24L); + + private static long parseYearMonthToMonths(String raw) { + long[] values = parseIntervalValues(raw, TimeUnit.YEAR_MONTH); + long months = Math.addExact(Math.multiplyExact(values[0], 12L), values[1]); + return months; + } + + private static long parseIntervalToMicros(String raw, TimeUnit unit) { + if (unit == TimeUnit.YEAR_MONTH) { + throw new AnalysisException("YEAR_MONTH should be handled via months parsing"); + } + long[] values = parseIntervalValues(raw, unit); + try { + long micros; + switch (unit) { + case DAY_HOUR: { + long dayMicros = Math.multiplyExact(values[0], MICROS_PER_DAY); + long hourMicros = Math.multiplyExact(values[1], MICROS_PER_HOUR); + micros = Math.addExact(dayMicros, hourMicros); + break; + } + case DAY_MINUTE: { + long dayMicros = Math.multiplyExact(values[0], MICROS_PER_DAY); + long hourMicros = Math.multiplyExact(values[1], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[2], MICROS_PER_MINUTE); + micros = Math.addExact(Math.addExact(dayMicros, hourMicros), minuteMicros); + break; + } + case DAY_SECOND: { + long dayMicros = Math.multiplyExact(values[0], MICROS_PER_DAY); + long hourMicros = Math.multiplyExact(values[1], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[2], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[3], MICROS_PER_SECOND); + micros = Math.addExact(Math.addExact(dayMicros, hourMicros), + Math.addExact(minuteMicros, secondMicros)); + break; + } + case DAY_MICROSECOND: { + long dayMicros = Math.multiplyExact(values[0], MICROS_PER_DAY); + long hourMicros = Math.multiplyExact(values[1], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[2], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[3], MICROS_PER_SECOND); + micros = Math.addExact(Math.addExact(dayMicros, hourMicros), + Math.addExact(Math.addExact(minuteMicros, secondMicros), values[4])); + break; + } + case HOUR_MINUTE: { + long hourMicros = Math.multiplyExact(values[0], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[1], MICROS_PER_MINUTE); + micros = Math.addExact(hourMicros, minuteMicros); + break; + } + case HOUR_SECOND: { + long hourMicros = Math.multiplyExact(values[0], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[1], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[2], MICROS_PER_SECOND); + micros = Math.addExact(Math.addExact(hourMicros, minuteMicros), secondMicros); + break; + } + case HOUR_MICROSECOND: { + long hourMicros = Math.multiplyExact(values[0], MICROS_PER_HOUR); + long minuteMicros = Math.multiplyExact(values[1], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[2], MICROS_PER_SECOND); + micros = Math.addExact(Math.addExact(hourMicros, minuteMicros), + Math.addExact(secondMicros, values[3])); + break; + } + case MINUTE_SECOND: { + long minuteMicros = Math.multiplyExact(values[0], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[1], MICROS_PER_SECOND); + micros = Math.addExact(minuteMicros, secondMicros); + break; + } + case MINUTE_MICROSECOND: { + long minuteMicros = Math.multiplyExact(values[0], MICROS_PER_MINUTE); + long secondMicros = Math.multiplyExact(values[1], MICROS_PER_SECOND); + micros = Math.addExact(Math.addExact(minuteMicros, secondMicros), values[2]); + break; + } + case SECOND_MICROSECOND: { + long secondMicros = Math.multiplyExact(values[0], MICROS_PER_SECOND); + micros = Math.addExact(secondMicros, values[1]); + break; + } + default: + throw new AnalysisException("Unsupported time unit: " + unit); + } + return micros; + } catch (ArithmeticException ex) { + throw new AnalysisException("Interval out of range", ex); + } + } + + private static long[] parseIntervalValues(String raw, TimeUnit unit) { + String str = raw.trim(); + if (str.isEmpty()) { + throw new AnalysisException("Invalid time format"); + } + + int expectedParts; + boolean transformMicro = false; + switch (unit) { + case YEAR_MONTH: + expectedParts = 2; + break; + case DAY_HOUR: + expectedParts = 2; + break; + case DAY_MINUTE: + expectedParts = 3; + break; + case DAY_SECOND: + expectedParts = 4; + break; + case DAY_MICROSECOND: + expectedParts = 5; + transformMicro = true; + break; + case HOUR_MINUTE: + expectedParts = 2; + break; + case HOUR_SECOND: + expectedParts = 3; + break; + case HOUR_MICROSECOND: + expectedParts = 4; + transformMicro = true; + break; + case MINUTE_SECOND: + expectedParts = 2; + break; + case MINUTE_MICROSECOND: + expectedParts = 3; + transformMicro = true; + break; + case SECOND_MICROSECOND: + expectedParts = 2; + transformMicro = true; + break; + default: + throw new AnalysisException("Unsupported time unit: " + unit); + } + + long[] values = new long[expectedParts]; + boolean negative = false; + int idx = 0; + int len = str.length(); + + while (idx < len && Character.isWhitespace(str.charAt(idx))) { + idx++; + } + if (idx < len && str.charAt(idx) == '-') { + negative = true; + idx++; + } + + idx = advanceToDigit(str, idx); + + int lastDigits = 0; + for (int i = 0; i < expectedParts; i++) { + if (idx >= len || !Character.isDigit(str.charAt(idx))) { + throw new AnalysisException("Invalid time format"); + } + long val = 0; + lastDigits = 0; + while (idx < len && Character.isDigit(str.charAt(idx))) { + val = val * 10 + (str.charAt(idx) - '0'); + idx++; + lastDigits++; + if (val < 0) { + throw new AnalysisException("Invalid time format"); + } + } + values[i] = val; + + idx = advanceToDigit(str, idx); + if (idx == len && i != expectedParts - 1) { + int filled = i + 1; + System.arraycopy(values, 0, values, expectedParts - filled, filled); + Arrays.fill(values, 0, expectedParts - filled, 0L); + break; + } + } + + if (idx != len) { + throw new AnalysisException("Invalid time format"); + } + + if (transformMicro) { + int microIndex = expectedParts - 1; + int digits = lastDigits; + if (digits > 0 && digits < 6) { + values[microIndex] = Math.multiplyExact(values[microIndex], POW_10[6 - digits]); + } + } + + if (negative) { + for (int i = 0; i < values.length; i++) { + values[i] = -values[i]; + } + } + return values; + } + + private static int advanceToDigit(String str, int idx) { + int len = str.length(); + while (idx < len && !Character.isDigit(str.charAt(idx))) { + idx++; + } + return idx; + } + + private static Expression applyInterval(DateTimeV2Literal date, VarcharLiteral delta, TimeUnit unit, + boolean add) { + if (unit == TimeUnit.YEAR_MONTH) { + long months = parseYearMonthToMonths(delta.getStringValue()); + months = add ? months : -months; + return date.plusMonths(months); + } + + long micros = parseIntervalToMicros(delta.getStringValue(), unit); + micros = add ? micros : -micros; + Expression result = date.plusMicroSeconds(micros); + if (result instanceof DateTimeV2Literal) { + DateTimeV2Literal dt = (DateTimeV2Literal) result; + if (dt.getScale() != date.getScale()) { + // Keep original scale to match existing folding behavior. + return DateTimeV2Literal.fromJavaDateType(dt.toJavaDateType(), date.getScale()); + } + } + return result; + } + + private static Expression applyInterval(TimestampTzLiteral date, VarcharLiteral delta, TimeUnit unit, + boolean add) { + if (unit == TimeUnit.YEAR_MONTH) { + long months = parseYearMonthToMonths(delta.getStringValue()); + months = add ? months : -months; + return date.plusMonths(months); + } + + long micros = parseIntervalToMicros(delta.getStringValue(), unit); + micros = add ? micros : -micros; + Expression result = date.plusMicroSeconds(micros); + if (result instanceof TimestampTzLiteral) { + TimestampTzLiteral dt = (TimestampTzLiteral) result; + if (dt.getScale() != date.getScale()) { + // Keep original scale to match existing folding behavior. + return TimestampTzLiteral.fromJavaDateType(dt.toJavaDateType(), date.getScale()); + } + } + return result; + } + /** * datetime arithmetic function date-add. */ @@ -57,12 +319,22 @@ public static Expression dateAdd(TimestampTzLiteral date, IntegerLiteral day) { */ @ExecFunction(name = "day_hour_add") public static Expression dayHourAdd(DateTimeV2Literal date, VarcharLiteral dayHour) { - return date.plusDayHour(dayHour); + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, true); } @ExecFunction(name = "day_hour_add") public static Expression dayHourAdd(TimestampTzLiteral date, VarcharLiteral dayHour) { - return date.plusDayHour(dayHour); + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, true); + } + + @ExecFunction(name = "day_hour_sub") + public static Expression dayHourSub(DateTimeV2Literal date, VarcharLiteral dayHour) { + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, false); + } + + @ExecFunction(name = "day_hour_sub") + public static Expression dayHourSub(TimestampTzLiteral date, VarcharLiteral dayHour) { + return applyInterval(date, dayHour, TimeUnit.DAY_HOUR, false); } /** @@ -70,12 +342,22 @@ public static Expression dayHourAdd(TimestampTzLiteral date, VarcharLiteral dayH */ @ExecFunction(name = "minute_second_add") public static Expression minuteSecondAdd(DateTimeV2Literal date, VarcharLiteral minuteSecond) { - return date.plusMinuteSecond(minuteSecond); + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, true); } @ExecFunction(name = "minute_second_add") public static Expression minuteSecondAdd(TimestampTzLiteral date, VarcharLiteral minuteSecond) { - return date.plusMinuteSecond(minuteSecond); + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, true); + } + + @ExecFunction(name = "minute_second_sub") + public static Expression minuteSecondSub(DateTimeV2Literal date, VarcharLiteral minuteSecond) { + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, false); + } + + @ExecFunction(name = "minute_second_sub") + public static Expression minuteSecondSub(TimestampTzLiteral date, VarcharLiteral minuteSecond) { + return applyInterval(date, minuteSecond, TimeUnit.MINUTE_SECOND, false); } /** @@ -83,12 +365,22 @@ public static Expression minuteSecondAdd(TimestampTzLiteral date, VarcharLiteral */ @ExecFunction(name = "second_microsecond_add") public static Expression secondMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral secondMicrosecond) { - return date.plusSecondMicrosecond(secondMicrosecond); + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, true); } @ExecFunction(name = "second_microsecond_add") public static Expression secondMicrosecondAdd(TimestampTzLiteral date, VarcharLiteral secondMicrosecond) { - return date.plusSecondMicrosecond(secondMicrosecond); + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, true); + } + + @ExecFunction(name = "second_microsecond_sub") + public static Expression secondMicrosecondSub(DateTimeV2Literal date, VarcharLiteral secondMicrosecond) { + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, false); + } + + @ExecFunction(name = "second_microsecond_sub") + public static Expression secondMicrosecondSub(TimestampTzLiteral date, VarcharLiteral secondMicrosecond) { + return applyInterval(date, secondMicrosecond, TimeUnit.SECOND_MICROSECOND, false); } /** @@ -204,7 +496,180 @@ public static Expression daysAdd(TimestampTzLiteral date, IntegerLiteral day) { */ @ExecFunction(name = "day_second_add") public static Expression daysAdd(DateTimeV2Literal date, VarcharLiteral daySecond) { - return date.plusDaySecond(daySecond); + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, true); + } + + @ExecFunction(name = "day_second_add") + public static Expression daysAdd(TimestampTzLiteral date, VarcharLiteral daySecond) { + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, true); + } + + @ExecFunction(name = "day_second_sub") + public static Expression daysSub(DateTimeV2Literal date, VarcharLiteral daySecond) { + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, false); + } + + @ExecFunction(name = "day_second_sub") + public static Expression daysSub(TimestampTzLiteral date, VarcharLiteral daySecond) { + return applyInterval(date, daySecond, TimeUnit.DAY_SECOND, false); + } + + /** + * datetime arithmetic function days-sub + */ + @ExecFunction(name = "days_sub") + public static Expression daysSub(DateV2Literal date, IntegerLiteral day) { + return daysAdd(date, new IntegerLiteral(-day.getValue())); + } + + @ExecFunction(name = "days_sub") + public static Expression daysSub(DateTimeV2Literal date, IntegerLiteral day) { + return daysAdd(date, new IntegerLiteral(-day.getValue())); + } + + @ExecFunction(name = "days_sub") + public static Expression daysSub(TimestampTzLiteral date, IntegerLiteral day) { + return daysAdd(date, new IntegerLiteral(-day.getValue())); + } + + @ExecFunction(name = "day_minute_add") + public static Expression dayMinuteAdd(DateTimeV2Literal date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, true); + } + + @ExecFunction(name = "day_minute_add") + public static Expression dayMinuteAdd(TimestampTzLiteral date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, true); + } + + @ExecFunction(name = "day_minute_sub") + public static Expression dayMinuteSub(DateTimeV2Literal date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, false); + } + + @ExecFunction(name = "day_minute_sub") + public static Expression dayMinuteSub(TimestampTzLiteral date, VarcharLiteral dayMinute) { + return applyInterval(date, dayMinute, TimeUnit.DAY_MINUTE, false); + } + + @ExecFunction(name = "day_microsecond_add") + public static Expression dayMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, true); + } + + @ExecFunction(name = "day_microsecond_add") + public static Expression dayMicrosecondAdd(TimestampTzLiteral date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, true); + } + + @ExecFunction(name = "day_microsecond_sub") + public static Expression dayMicrosecondSub(DateTimeV2Literal date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, false); + } + + @ExecFunction(name = "day_microsecond_sub") + public static Expression dayMicrosecondSub(TimestampTzLiteral date, VarcharLiteral dayMicrosecond) { + return applyInterval(date, dayMicrosecond, TimeUnit.DAY_MICROSECOND, false); + } + + @ExecFunction(name = "hour_minute_add") + public static Expression hourMinuteAdd(DateTimeV2Literal date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, true); + } + + @ExecFunction(name = "hour_minute_add") + public static Expression hourMinuteAdd(TimestampTzLiteral date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, true); + } + + @ExecFunction(name = "hour_minute_sub") + public static Expression hourMinuteSub(DateTimeV2Literal date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, false); + } + + @ExecFunction(name = "hour_minute_sub") + public static Expression hourMinuteSub(TimestampTzLiteral date, VarcharLiteral hourMinute) { + return applyInterval(date, hourMinute, TimeUnit.HOUR_MINUTE, false); + } + + @ExecFunction(name = "hour_second_add") + public static Expression hourSecondAdd(DateTimeV2Literal date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, true); + } + + @ExecFunction(name = "hour_second_add") + public static Expression hourSecondAdd(TimestampTzLiteral date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, true); + } + + @ExecFunction(name = "hour_second_sub") + public static Expression hourSecondSub(DateTimeV2Literal date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, false); + } + + @ExecFunction(name = "hour_second_sub") + public static Expression hourSecondSub(TimestampTzLiteral date, VarcharLiteral hourSecond) { + return applyInterval(date, hourSecond, TimeUnit.HOUR_SECOND, false); + } + + @ExecFunction(name = "hour_microsecond_add") + public static Expression hourMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, true); + } + + @ExecFunction(name = "hour_microsecond_add") + public static Expression hourMicrosecondAdd(TimestampTzLiteral date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, true); + } + + @ExecFunction(name = "hour_microsecond_sub") + public static Expression hourMicrosecondSub(DateTimeV2Literal date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, false); + } + + @ExecFunction(name = "hour_microsecond_sub") + public static Expression hourMicrosecondSub(TimestampTzLiteral date, VarcharLiteral hourMicrosecond) { + return applyInterval(date, hourMicrosecond, TimeUnit.HOUR_MICROSECOND, false); + } + + @ExecFunction(name = "minute_microsecond_add") + public static Expression minuteMicrosecondAdd(DateTimeV2Literal date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, true); + } + + @ExecFunction(name = "minute_microsecond_add") + public static Expression minuteMicrosecondAdd(TimestampTzLiteral date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, true); + } + + @ExecFunction(name = "minute_microsecond_sub") + public static Expression minuteMicrosecondSub(DateTimeV2Literal date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, false); + } + + @ExecFunction(name = "minute_microsecond_sub") + public static Expression minuteMicrosecondSub(TimestampTzLiteral date, VarcharLiteral minuteMicrosecond) { + return applyInterval(date, minuteMicrosecond, TimeUnit.MINUTE_MICROSECOND, false); + } + + @ExecFunction(name = "year_month_add") + public static Expression yearMonthAdd(DateTimeV2Literal date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, true); + } + + @ExecFunction(name = "year_month_add") + public static Expression yearMonthAdd(TimestampTzLiteral date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, true); + } + + @ExecFunction(name = "year_month_sub") + public static Expression yearMonthSub(DateTimeV2Literal date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, false); + } + + @ExecFunction(name = "year_month_sub") + public static Expression yearMonthSub(TimestampTzLiteral date, VarcharLiteral yearMonth) { + return applyInterval(date, yearMonth, TimeUnit.YEAR_MONTH, false); } /** @@ -331,24 +796,6 @@ public static Expression weeksSub(TimestampTzLiteral date, IntegerLiteral weeks) return date.plusWeeks(-weeks.getValue()); } - /** - * datetime arithmetic function days-sub - */ - @ExecFunction(name = "days_sub") - public static Expression daysSub(DateV2Literal date, IntegerLiteral day) { - return daysAdd(date, new IntegerLiteral(-day.getValue())); - } - - @ExecFunction(name = "days_sub") - public static Expression daysSub(DateTimeV2Literal date, IntegerLiteral day) { - return daysAdd(date, new IntegerLiteral(-day.getValue())); - } - - @ExecFunction(name = "days_sub") - public static Expression daysSub(TimestampTzLiteral date, IntegerLiteral day) { - return daysAdd(date, new IntegerLiteral(-day.getValue())); - } - /** * datetime arithmetic function hours-sub */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java index efe6b6bc6f9aec..b3f356a0a36e58 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/executable/DateTimeExtractAndTransform.java @@ -313,6 +313,89 @@ public static Expression timeFormat(DateTimeV2Literal dateTime, StringLikeLitera return new VarcharLiteral(DateTimeFormatterUtils.toFormatStringConservative(dateTime, format, true)); } + private static String padTwo(int value) { + return value < 10 ? "0" + value : Integer.toString(value); + } + + private static String padMicro(int micro) { + String s = Integer.toString(micro); + int len = s.length(); + return len >= 6 ? s : "000000".substring(len) + s; + } + + @ExecFunction(name = "year_month") + public static Expression yearMonth(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(t.getYear() + "-" + padTwo(t.getMonthValue())); + } + + @ExecFunction(name = "day_hour") + public static Expression dayHour(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour())); + } + + @ExecFunction(name = "day_minute") + public static Expression dayMinute(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute())); + } + + @ExecFunction(name = "day_second") + public static Expression daySecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); + } + + @ExecFunction(name = "day_microsecond") + public static Expression dayMicrosecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getDayOfMonth()) + " " + padTwo(t.getHour()) + ":" + + padTwo(t.getMinute()) + ":" + padTwo(t.getSecond()) + "." + + padMicro(t.getNano() / 1000)); + } + + @ExecFunction(name = "hour_minute") + public static Expression hourMinute(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute())); + } + + @ExecFunction(name = "hour_second") + public static Expression hourSecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute()) + ":" + + padTwo(t.getSecond())); + } + + @ExecFunction(name = "hour_microsecond") + public static Expression hourMicrosecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getHour()) + ":" + padTwo(t.getMinute()) + ":" + + padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); + } + + @ExecFunction(name = "minute_second") + public static Expression minuteSecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getMinute()) + ":" + padTwo(t.getSecond())); + } + + @ExecFunction(name = "minute_microsecond") + public static Expression minuteMicrosecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getMinute()) + ":" + padTwo(t.getSecond()) + "." + + padMicro(t.getNano() / 1000)); + } + + @ExecFunction(name = "second_microsecond") + public static Expression secondMicrosecond(DateTimeV2Literal dateTime) { + LocalDateTime t = dateTime.toJavaDateType(); + return new VarcharLiteral(padTwo(t.getSecond()) + "." + padMicro(t.getNano() / 1000)); + } + /** * datetime arithmetic function date */ diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java new file mode 100644 index 00000000000000..c67397d92d183e --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHour.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_hour'. + */ +public class DayHour extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public DayHour(Expression arg) { + super("day_hour", arg); + } + + private DayHour(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayHour withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new DayHour(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayHour(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java new file mode 100644 index 00000000000000..fba84e5c534bf6 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayHourSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_hour_sub'. + */ +public class DayHourSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, + VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, + VarcharType.SYSTEM_DEFAULT) + ); + + public DayHourSub(Expression arg0, Expression arg1) { + super("day_hour_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DayHourSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayHourSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DayHourSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayHourSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DayHourSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java new file mode 100644 index 00000000000000..2f05f8e588a07d --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_microsecond'. + */ +public class DayMicrosecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public DayMicrosecond(Expression arg) { + super("day_microsecond", arg); + } + + private DayMicrosecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMicrosecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new DayMicrosecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMicrosecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java new file mode 100644 index 00000000000000..22b319464bc08a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondAdd.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_microsecond_add'. + */ +public class DayMicrosecondAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public DayMicrosecondAdd(Expression arg0, Expression arg1) { + super("day_microsecond_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DayMicrosecondAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMicrosecondAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DayMicrosecondAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMicrosecondAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DayMicrosecondAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java new file mode 100644 index 00000000000000..efb61c5f72ec17 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMicrosecondSub.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_microsecond_sub'. + */ +public class DayMicrosecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public DayMicrosecondSub(Expression arg0, Expression arg1) { + super("day_microsecond_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DayMicrosecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMicrosecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DayMicrosecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMicrosecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DayMicrosecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java new file mode 100644 index 00000000000000..46eed01bd20c36 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinute.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_minute'. + */ +public class DayMinute extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public DayMinute(Expression arg) { + super("day_minute", arg); + } + + private DayMinute(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMinute withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new DayMinute(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMinute(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java new file mode 100644 index 00000000000000..a2aa28d088ac94 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteAdd.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_minute_add'. + */ +public class DayMinuteAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public DayMinuteAdd(Expression arg0, Expression arg1) { + super("day_minute_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DayMinuteAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMinuteAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DayMinuteAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMinuteAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DayMinuteAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java new file mode 100644 index 00000000000000..e74dc3daf1246c --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DayMinuteSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_minute_sub'. + */ +public class DayMinuteSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public DayMinuteSub(Expression arg0, Expression arg1) { + super("day_minute_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DayMinuteSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DayMinuteSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DayMinuteSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDayMinuteSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DayMinuteSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java new file mode 100644 index 00000000000000..78314de8708061 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_second'. + */ +public class DaySecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public DaySecond(Expression arg) { + super("day_second", arg); + } + + private DaySecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DaySecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new DaySecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDaySecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java new file mode 100644 index 00000000000000..3c23817031df5c --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/DaySecondSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'day_second_sub'. + */ +public class DaySecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, + VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, + VarcharType.SYSTEM_DEFAULT) + ); + + public DaySecondSub(Expression arg0, Expression arg1) { + super("day_second_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private DaySecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public DaySecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new DaySecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitDaySecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new DaySecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java new file mode 100644 index 00000000000000..5322c6bb965a07 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_microsecond'. + */ +public class HourMicrosecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public HourMicrosecond(Expression arg) { + super("hour_microsecond", arg); + } + + private HourMicrosecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMicrosecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new HourMicrosecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMicrosecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java new file mode 100644 index 00000000000000..d7f7c9e2a31faa --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondAdd.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_microsecond_add'. + */ +public class HourMicrosecondAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public HourMicrosecondAdd(Expression arg0, Expression arg1) { + super("hour_microsecond_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourMicrosecondAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMicrosecondAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourMicrosecondAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMicrosecondAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourMicrosecondAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java new file mode 100644 index 00000000000000..1d43cb8e94cc5b --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMicrosecondSub.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_microsecond_sub'. + */ +public class HourMicrosecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public HourMicrosecondSub(Expression arg0, Expression arg1) { + super("hour_microsecond_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourMicrosecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMicrosecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourMicrosecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMicrosecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourMicrosecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java new file mode 100644 index 00000000000000..122fc0daf2514a --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinute.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_minute'. + */ +public class HourMinute extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public HourMinute(Expression arg) { + super("hour_minute", arg); + } + + private HourMinute(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMinute withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new HourMinute(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMinute(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java new file mode 100644 index 00000000000000..117c7c89140f77 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteAdd.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_minute_add'. + */ +public class HourMinuteAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public HourMinuteAdd(Expression arg0, Expression arg1) { + super("hour_minute_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourMinuteAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMinuteAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourMinuteAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMinuteAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourMinuteAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java new file mode 100644 index 00000000000000..7caaf1d61aaae9 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourMinuteSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_minute_sub'. + */ +public class HourMinuteSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public HourMinuteSub(Expression arg0, Expression arg1) { + super("hour_minute_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourMinuteSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourMinuteSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourMinuteSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourMinuteSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourMinuteSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java new file mode 100644 index 00000000000000..74a6d957c17b5f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_second'. + */ +public class HourSecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public HourSecond(Expression arg) { + super("hour_second", arg); + } + + private HourSecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourSecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new HourSecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourSecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java new file mode 100644 index 00000000000000..056c4734b9271f --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondAdd.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_second_add'. + */ +public class HourSecondAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public HourSecondAdd(Expression arg0, Expression arg1) { + super("hour_second_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourSecondAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourSecondAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourSecondAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourSecondAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourSecondAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java new file mode 100644 index 00000000000000..341a7ec98e4c3b --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/HourSecondSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'hour_second_sub'. + */ +public class HourSecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public HourSecondSub(Expression arg0, Expression arg1) { + super("hour_second_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private HourSecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public HourSecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new HourSecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitHourSecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new HourSecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java new file mode 100644 index 00000000000000..f4a6e4e0951f91 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'minute_microsecond'. + */ +public class MinuteMicrosecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public MinuteMicrosecond(Expression arg) { + super("minute_microsecond", arg); + } + + private MinuteMicrosecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public MinuteMicrosecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new MinuteMicrosecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitMinuteMicrosecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java new file mode 100644 index 00000000000000..135666d6d52cf4 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondAdd.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'minute_microsecond_add'. + */ +public class MinuteMicrosecondAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public MinuteMicrosecondAdd(Expression arg0, Expression arg1) { + super("minute_microsecond_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private MinuteMicrosecondAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public MinuteMicrosecondAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new MinuteMicrosecondAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitMinuteMicrosecondAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new MinuteMicrosecondAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java new file mode 100644 index 00000000000000..45b7272d505f46 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteMicrosecondSub.java @@ -0,0 +1,85 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'minute_microsecond_sub'. + */ +public class MinuteMicrosecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX) + .args(DateTimeV2Type.MAX, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX) + .args(TimeStampTzType.MAX, VarcharType.SYSTEM_DEFAULT) + ); + + public MinuteMicrosecondSub(Expression arg0, Expression arg1) { + super("minute_microsecond_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private MinuteMicrosecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public MinuteMicrosecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new MinuteMicrosecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitMinuteMicrosecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new MinuteMicrosecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java new file mode 100644 index 00000000000000..18499e98e64e4c --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'minute_second'. + */ +public class MinuteSecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public MinuteSecond(Expression arg) { + super("minute_second", arg); + } + + private MinuteSecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public MinuteSecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new MinuteSecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitMinuteSecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java new file mode 100644 index 00000000000000..c525d696fa1e82 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/MinuteSecondSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'minute_second_sub'. + */ +public class MinuteSecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD).args(DateTimeV2Type.WILDCARD, + VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD).args(TimeStampTzType.WILDCARD, + VarcharType.SYSTEM_DEFAULT) + ); + + public MinuteSecondSub(Expression arg0, Expression arg1) { + super("minute_second_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private MinuteSecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public MinuteSecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new MinuteSecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitMinuteSecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new MinuteSecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java new file mode 100644 index 00000000000000..f4e6c047bfff24 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecond.java @@ -0,0 +1,66 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'second_microsecond'. + */ +public class SecondMicrosecond extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + public SecondMicrosecond(Expression arg) { + super("second_microsecond", arg); + } + + private SecondMicrosecond(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public SecondMicrosecond withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new SecondMicrosecond(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitSecondMicrosecond(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java new file mode 100644 index 00000000000000..af4350f28f26ba --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/SecondMicrosecondSub.java @@ -0,0 +1,88 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'second_microsecond_sub'. + */ +public class SecondMicrosecondSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.MAX).args(DateTimeV2Type.MAX, + VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.MAX).args(TimeStampTzType.MAX, + VarcharType.SYSTEM_DEFAULT) + ); + + public SecondMicrosecondSub(Expression arg0, Expression arg1) { + super("second_microsecond_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private SecondMicrosecondSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public SecondMicrosecondSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new SecondMicrosecondSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitSecondMicrosecondSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new SecondMicrosecondSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + signature = super.computeSignature(signature); + if (signature.argumentsTypes.get(0) instanceof TimeStampTzType) { + return signature.withArgumentType(0, TimeStampTzType.MAX).withReturnType(TimeStampTzType.MAX); + } + return signature.withArgumentType(0, DateTimeV2Type.MAX).withReturnType(DateTimeV2Type.MAX); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java new file mode 100644 index 00000000000000..04816fb2a1db61 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonth.java @@ -0,0 +1,73 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.UnaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'year_month'. + */ +public class YearMonth extends ScalarFunction + implements UnaryExpression, ExplicitlyCastableSignature, PropagateNullable { + + private static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(VarcharType.SYSTEM_DEFAULT).args(DateTimeV2Type.WILDCARD)); + + /** + * constructor with 1 argument. + */ + public YearMonth(Expression arg) { + super("year_month", arg); + } + + /** constructor for withChildren and reuse signature */ + private YearMonth(ScalarFunctionParams functionParams) { + super(functionParams); + } + + /** + * withChildren. + */ + @Override + public YearMonth withChildren(List children) { + Preconditions.checkArgument(children.size() == 1); + return new YearMonth(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitYearMonth(this, context); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java new file mode 100644 index 00000000000000..872654e2e4bdd3 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthAdd.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'year_month_add'. + */ +public class YearMonthAdd extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public YearMonthAdd(Expression arg0, Expression arg1) { + super("year_month_add", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private YearMonthAdd(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public YearMonthAdd withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new YearMonthAdd(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitYearMonthAdd(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new YearMonthAdd(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java new file mode 100644 index 00000000000000..fe3d64ae240653 --- /dev/null +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/functions/scalar/YearMonthSub.java @@ -0,0 +1,84 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +package org.apache.doris.nereids.trees.expressions.functions.scalar; + +import org.apache.doris.catalog.FunctionSignature; +import org.apache.doris.nereids.trees.expressions.Expression; +import org.apache.doris.nereids.trees.expressions.functions.ComputeSignatureForDateArithmetic; +import org.apache.doris.nereids.trees.expressions.functions.DateAddSubMonotonic; +import org.apache.doris.nereids.trees.expressions.functions.ExplicitlyCastableSignature; +import org.apache.doris.nereids.trees.expressions.functions.PropagateNullable; +import org.apache.doris.nereids.trees.expressions.shape.BinaryExpression; +import org.apache.doris.nereids.trees.expressions.visitor.ExpressionVisitor; +import org.apache.doris.nereids.types.DateTimeV2Type; +import org.apache.doris.nereids.types.TimeStampTzType; +import org.apache.doris.nereids.types.VarcharType; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +import java.util.List; + +/** + * ScalarFunction 'year_month_sub'. + */ +public class YearMonthSub extends ScalarFunction + implements BinaryExpression, ExplicitlyCastableSignature, + ComputeSignatureForDateArithmetic, PropagateNullable, DateAddSubMonotonic { + public static final List SIGNATURES = ImmutableList.of( + FunctionSignature.ret(DateTimeV2Type.WILDCARD) + .args(DateTimeV2Type.WILDCARD, VarcharType.SYSTEM_DEFAULT), + FunctionSignature.ret(TimeStampTzType.WILDCARD) + .args(TimeStampTzType.WILDCARD, VarcharType.SYSTEM_DEFAULT) + ); + + public YearMonthSub(Expression arg0, Expression arg1) { + super("year_month_sub", arg0, arg1); + } + + /** constructor for withChildren and reuse signature */ + private YearMonthSub(ScalarFunctionParams functionParams) { + super(functionParams); + } + + @Override + public YearMonthSub withChildren(List children) { + Preconditions.checkArgument(children.size() == 2); + return new YearMonthSub(getFunctionParams(children)); + } + + @Override + public List getSignatures() { + return SIGNATURES; + } + + @Override + public R accept(ExpressionVisitor visitor, C context) { + return visitor.visitYearMonthSub(this, context); + } + + @Override + public Expression withConstantArgs(Expression literal) { + return new YearMonthSub(literal, child(1)); + } + + @Override + public FunctionSignature computeSignature(FunctionSignature signature) { + return super.computeSignature(signature); + } +} diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java index a1e660f886439d..275e0f74fe1bc9 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/literal/Interval.java @@ -88,18 +88,25 @@ protected boolean extraEquals(Expression that) { * Supported time unit. */ public enum TimeUnit { - SECOND_MICROSECOND("SECOND_MICROSECOND", false, 1200), - MINUTE_SECOND("MINUTE_SECOND", false, 1100), - DAY_HOUR("DAY_HOUR", false, 1000), - DAY_SECOND("DAY_SECOND", false, 900), YEAR("YEAR", false, 800), + YEAR_MONTH("YEAR_MONTH", false, 800), MONTH("MONTH", false, 700), QUARTER("QUARTER", false, 600), //TODO: need really support quarter WEEK("WEEK", false, 500), DAY("DAY", false, 400), + DAY_HOUR("DAY_HOUR", false, 400), + DAY_MINUTE("DAY_MINUTE", false, 400), + DAY_MICROSECOND("DAY_MICROSECOND", false, 400), + DAY_SECOND("DAY_SECOND", false, 400), HOUR("HOUR", true, 300), + HOUR_MINUTE("HOUR_MINUTE", false, 300), + HOUR_SECOND("HOUR_SECOND", false, 300), + HOUR_MICROSECOND("HOUR_MICROSECOND", false, 300), MINUTE("MINUTE", true, 200), - SECOND("SECOND", true, 100); + MINUTE_SECOND("MINUTE_SECOND", false, 200), + MINUTE_MICROSECOND("MINUTE_MICROSECOND", false, 200), + SECOND("SECOND", true, 100), + SECOND_MICROSECOND("SECOND_MICROSECOND", true, 100); private final String description; private final boolean isDateTimeUnit; diff --git a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java index f09bd61f8c36f3..9dfaf1d6d0a95e 100644 --- a/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java +++ b/fe/fe-core/src/main/java/org/apache/doris/nereids/trees/expressions/visitor/ScalarFunctionVisitor.java @@ -179,12 +179,22 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.DateV2; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHour; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHourAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayHourSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMicrosecondSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinute; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinuteAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DayMinuteSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayName; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfMonth; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.DayOfYear; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.DaySecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.DaysSub; @@ -247,6 +257,15 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.HourCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.HourFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMicrosecondSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinute; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinuteAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourMinuteSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.HourSecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.HoursSub; @@ -352,7 +371,12 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecond; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteMicrosecondSub; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.MinuteSecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.MinutesSub; @@ -431,7 +455,9 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondFloor; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondFromUnixtime; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecond; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecondAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondMicrosecondSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsAdd; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsDiff; import org.apache.doris.nereids.trees.expressions.functions.scalar.SecondsSub; @@ -557,6 +583,9 @@ import org.apache.doris.nereids.trees.expressions.functions.scalar.Year; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearCeil; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearFloor; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonth; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonthAdd; +import org.apache.doris.nereids.trees.expressions.functions.scalar.YearMonthSub; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearOfWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearWeek; import org.apache.doris.nereids.trees.expressions.functions.scalar.YearsAdd; @@ -1161,16 +1190,44 @@ default R visitDaysDiff(DaysDiff daysDiff, C context) { return visitScalarFunction(daysDiff, context); } + default R visitDayHour(DayHour dayHour, C context) { + return visitScalarFunction(dayHour, context); + } + default R visitDayHourAdd(DayHourAdd dayHourAdd, C context) { return visitScalarFunction(dayHourAdd, context); } - default R visitMinuteSecondAdd(MinuteSecondAdd minuteSecondAdd, C context) { - return visitScalarFunction(minuteSecondAdd, context); + default R visitDayHourSub(DayHourSub dayHourSub, C context) { + return visitScalarFunction(dayHourSub, context); } - default R visitSecondMicrosecondAdd(SecondMicrosecondAdd secondMicrosecondAdd, C context) { - return visitScalarFunction(secondMicrosecondAdd, context); + default R visitDayMinute(DayMinute dayMinute, C context) { + return visitScalarFunction(dayMinute, context); + } + + default R visitDayMinuteAdd(DayMinuteAdd dayMinuteAdd, C context) { + return visitScalarFunction(dayMinuteAdd, context); + } + + default R visitDayMinuteSub(DayMinuteSub dayMinuteSub, C context) { + return visitScalarFunction(dayMinuteSub, context); + } + + default R visitDaySecond(DaySecond daySecond, C context) { + return visitScalarFunction(daySecond, context); + } + + default R visitDayMicrosecond(DayMicrosecond dayMicrosecond, C context) { + return visitScalarFunction(dayMicrosecond, context); + } + + default R visitDayMicrosecondAdd(DayMicrosecondAdd dayMicrosecondAdd, C context) { + return visitScalarFunction(dayMicrosecondAdd, context); + } + + default R visitDayMicrosecondSub(DayMicrosecondSub dayMicrosecondSub, C context) { + return visitScalarFunction(dayMicrosecondSub, context); } default R visitDaysAdd(DaysAdd daysAdd, C context) { @@ -1181,6 +1238,10 @@ default R visitDaySecondAdd(DaySecondAdd daySecondAdd, C context) { return visitScalarFunction(daySecondAdd, context); } + default R visitDaySecondSub(DaySecondSub daySecondSub, C context) { + return visitScalarFunction(daySecondSub, context); + } + default R visitDaysSub(DaysSub daysSub, C context) { return visitScalarFunction(daysSub, context); } @@ -1213,6 +1274,42 @@ default R visitHoursSub(HoursSub hoursSub, C context) { return visitScalarFunction(hoursSub, context); } + default R visitHourMinute(HourMinute hourMinute, C context) { + return visitScalarFunction(hourMinute, context); + } + + default R visitHourMinuteAdd(HourMinuteAdd hourMinuteAdd, C context) { + return visitScalarFunction(hourMinuteAdd, context); + } + + default R visitHourMinuteSub(HourMinuteSub hourMinuteSub, C context) { + return visitScalarFunction(hourMinuteSub, context); + } + + default R visitHourMicrosecond(HourMicrosecond hourMicrosecond, C context) { + return visitScalarFunction(hourMicrosecond, context); + } + + default R visitHourMicrosecondAdd(HourMicrosecondAdd hourMicrosecondAdd, C context) { + return visitScalarFunction(hourMicrosecondAdd, context); + } + + default R visitHourMicrosecondSub(HourMicrosecondSub hourMicrosecondSub, C context) { + return visitScalarFunction(hourMicrosecondSub, context); + } + + default R visitHourSecond(HourSecond hourSecond, C context) { + return visitScalarFunction(hourSecond, context); + } + + default R visitHourSecondAdd(HourSecondAdd hourSecondAdd, C context) { + return visitScalarFunction(hourSecondAdd, context); + } + + default R visitHourSecondSub(HourSecondSub hourSecondSub, C context) { + return visitScalarFunction(hourSecondSub, context); + } + default R visitMinutesSub(MinutesSub minutesSub, C context) { return visitScalarFunction(minutesSub, context); } @@ -1257,6 +1354,30 @@ default R visitMinutesAdd(MinutesAdd minutesAdd, C context) { return visitScalarFunction(minutesAdd, context); } + default R visitMinuteSecond(MinuteSecond minuteSecond, C context) { + return visitScalarFunction(minuteSecond, context); + } + + default R visitMinuteSecondAdd(MinuteSecondAdd minuteSecondAdd, C context) { + return visitScalarFunction(minuteSecondAdd, context); + } + + default R visitMinuteSecondSub(MinuteSecondSub minuteSecondSub, C context) { + return visitScalarFunction(minuteSecondSub, context); + } + + default R visitMinuteMicrosecond(MinuteMicrosecond minuteMicrosecond, C context) { + return visitScalarFunction(minuteMicrosecond, context); + } + + default R visitMinuteMicrosecondAdd(MinuteMicrosecondAdd minuteMicrosecondAdd, C context) { + return visitScalarFunction(minuteMicrosecondAdd, context); + } + + default R visitMinuteMicrosecondSub(MinuteMicrosecondSub minuteMicrosecondSub, C context) { + return visitScalarFunction(minuteMicrosecondSub, context); + } + default R visitSecondsAdd(SecondsAdd secondsAdd, C context) { return visitScalarFunction(secondsAdd, context); } @@ -2105,6 +2226,18 @@ default R visitSecondFloor(SecondFloor secondFloor, C context) { return visitScalarFunction(secondFloor, context); } + default R visitSecondMicrosecond(SecondMicrosecond secondMicrosecond, C context) { + return visitScalarFunction(secondMicrosecond, context); + } + + default R visitSecondMicrosecondAdd(SecondMicrosecondAdd secondMicrosecondAdd, C context) { + return visitScalarFunction(secondMicrosecondAdd, context); + } + + default R visitSecondMicrosecondSub(SecondMicrosecondSub secondMicrosecondSub, C context) { + return visitScalarFunction(secondMicrosecondSub, context); + } + default R visitSecondsDiff(SecondsDiff secondsDiff, C context) { return visitScalarFunction(secondsDiff, context); } @@ -2589,6 +2722,18 @@ default R visitYearFloor(YearFloor yearFloor, C context) { return visitScalarFunction(yearFloor, context); } + default R visitYearMonth(YearMonth yearMonth, C context) { + return visitScalarFunction(yearMonth, context); + } + + default R visitYearMonthAdd(YearMonthAdd yearMonthAdd, C context) { + return visitScalarFunction(yearMonthAdd, context); + } + + default R visitYearMonthSub(YearMonthSub yearMonthSub, C context) { + return visitScalarFunction(yearMonthSub, context); + } + default R visitYearWeek(YearWeek yearWeek, C context) { return visitScalarFunction(yearWeek, context); } diff --git a/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.out b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.out new file mode 100644 index 00000000000000..1236449bdfc43a --- /dev/null +++ b/regression-test/data/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.out @@ -0,0 +1,810 @@ +-- This file is automatically generated. You should know what you did if you want to edit this +-- !year_month_add_1 -- +2024-03-02T00:00 + +-- !year_month_add_2 -- +2022-10-02T03:04:05.123456 + +-- !year_month_add_3 -- +2024-03-02T03:04:05.123456 + +-- !year_month_add_4 -- +2023-12-29T10:00 + +-- !year_month_add_5 -- +2024-02-29T00:00 + +-- !year_month_add_6 -- +2024-03-28 12:00:00+08:00 + +-- !year_month_add_7 -- +2024-04-30 20:00:00+08:00 + +-- !year_month_add_8 -- +2024-05-31 01:30:00+08:00 + +-- !year_month_add_9 -- +2026-05-02T00:00 + +-- !year_month_add_10 -- +2024-03-02T00:00 + +-- !year_month_add_11 -- +2023-06-02T00:00 + +-- !year_month_add_12 -- +3257-12-02T00:00 + +-- !year_month_add_13 -- +2022-02-28T00:00 + +-- !year_month_add_14 -- +2024-02-29T00:00 + +-- !year_month_sub_1 -- +2021-11-02T00:00 + +-- !year_month_sub_2 -- +2021-11-02T03:04:05.123456 + +-- !year_month_sub_3 -- +2022-04-30T00:00 + +-- !year_month_sub_4 -- +2022-05-30 12:00:00+08:00 + +-- !year_month_sub_5 -- +2022-06-30 20:00:00+08:00 + +-- !year_month_sub_6 -- +2022-07-31 01:30:00+08:00 + +-- !year_month_sub_7 -- +2017-07-02T00:00 + +-- !year_month_extract_1 -- +2023-01 +2024-02 + +-- !year_month_extract_2 -- +2023-01 + +-- !year_month_extract_3 -- +2023-01 + +-- !year_month_extract_4 -- +2022-12 + +-- !year_month_extract_5 -- +2023-01 + +-- !day_hour_add_1 -- +2023-01-03T05:04:05 + +-- !day_hour_add_2 -- +2022-12-31T00:04:05.123456 + +-- !day_hour_add_3 -- +2023-01-03T05:04:05.123456 + +-- !day_hour_add_4 -- +2024-02-28T10:00 + +-- !day_hour_add_5 -- +2023-01-09T11:04:05 + +-- !day_hour_add_6 -- +2023-01-03T05:04:05.123456 + +-- !day_hour_add_7 -- +2023-01-02T15:04:05.123456 + +-- !day_hour_add_8 -- +2025-09-28T02:04:05.123456 + +-- !day_hour_add_9 -- +2023-03-01T10:00 + +-- !day_hour_add_10 -- +2023-04-01 11:00:00+08:00 + +-- !day_hour_add_11 -- +2023-05-01 19:00:00+08:00 + +-- !day_hour_add_12 -- +2023-06-02 00:30:00+08:00 + +-- !day_hour_sub_1 -- +2023-01-01T01:04:05 + +-- !day_hour_sub_2 -- +2023-01-01T01:04:05.123456 + +-- !day_hour_sub_3 -- +2022-12-23T17:04:05 + +-- !day_hour_sub_4 -- +2023-11-28T14:00 + +-- !day_hour_sub_5 -- +2023-10-29 15:00:00+08:00 + +-- !day_hour_sub_6 -- +2023-09-28 23:00:00+08:00 + +-- !day_hour_sub_7 -- +2023-08-30 04:30:00+08:00 + +-- !day_hour_extract_1 -- +02 03 +29 10 + +-- !day_hour_extract_2 -- +02 00 + +-- !day_hour_extract_3 -- +02 03 + +-- !day_hour_extract_4 -- +02 03 + +-- !day_hour_extract_5 -- +02 16 + +-- !day_minute_add_1 -- +2023-01-03T05:07:05 + +-- !day_minute_add_2 -- +2022-12-31T00:00:05.123456 + +-- !day_minute_add_3 -- +2023-01-03T05:07:05.123456 + +-- !day_minute_add_4 -- +2024-02-28T09:59 + +-- !day_minute_add_5 -- +2023-01-05T07:09:05 + +-- !day_minute_add_6 -- +2023-01-03T05:07:05.123456 + +-- !day_minute_add_7 -- +2023-01-02T03:34:05.123456 + +-- !day_minute_add_8 -- +2025-09-28T03:03:05.123456 + +-- !day_minute_add_9 -- +2023-03-01T10:59 + +-- !day_minute_add_10 -- +2023-04-01 11:59:00+08:00 + +-- !day_minute_add_11 -- +2023-05-01 19:59:00+08:00 + +-- !day_minute_add_12 -- +2023-06-02 01:29:00+08:00 + +-- !day_minute_sub_1 -- +2023-01-01T01:01:05 + +-- !day_minute_sub_2 -- +2023-01-01T01:01:05.123456 + +-- !day_minute_sub_3 -- +2022-12-27T20:57:05 + +-- !day_minute_sub_4 -- +2023-11-28T13:01 + +-- !day_minute_sub_5 -- +2023-10-29 14:01:00+08:00 + +-- !day_minute_sub_6 -- +2023-09-28 22:01:00+08:00 + +-- !day_minute_sub_7 -- +2023-08-30 03:31:00+08:00 + +-- !day_minute_extract_1 -- +02 03:04 +29 10:00 + +-- !day_minute_extract_2 -- +02 00:00 + +-- !day_minute_extract_3 -- +02 03:04 + +-- !day_minute_extract_4 -- +02 03:04 + +-- !day_minute_extract_5 -- +02 16:34 + +-- !day_second_add_1 -- +2023-01-03T05:07:09 + +-- !day_second_add_2 -- +2022-12-31T00:00:00.123456 + +-- !day_second_add_3 -- +2023-01-03T05:07:09.123456 + +-- !day_second_add_4 -- +2024-02-28T09:59:58 + +-- !day_second_add_5 -- +2023-01-02T03:04:12.123456 + +-- !day_second_add_6 -- +2023-01-02T10:12:14 + +-- !day_second_add_7 -- +2023-01-03T05:07:09.123456 + +-- !day_second_add_8 -- +2023-01-02T05:07:09.123456 + +-- !day_second_add_9 -- +2025-09-28T03:04:04.123456 + +-- !day_second_add_10 -- +2022-01-01T10:20:30 + +-- !day_second_add_11 -- +2021-12-01 11:20:30+08:00 + +-- !day_second_add_12 -- +2021-11-01 19:20:30+08:00 + +-- !day_second_add_13 -- +2021-10-02 00:50:30+08:00 + +-- !day_second_sub_1 -- +2023-01-01T01:01:01 + +-- !day_second_sub_2 -- +2023-01-01T01:01:01.123456 + +-- !day_second_sub_3 -- +2023-01-01T21:57:58 + +-- !day_second_sub_4 -- +2019-02-26T13:39:30 + +-- !day_second_sub_5 -- +2019-01-29 14:39:30+08:00 + +-- !day_second_sub_6 -- +2019-03-29 22:39:30+08:00 + +-- !day_second_sub_7 -- +2019-04-29 04:09:30+08:00 + +-- !day_second_extract_1 -- +02 03:04:05 +29 10:00:00 + +-- !day_second_extract_2 -- +02 00:00:00 + +-- !day_second_extract_3 -- +02 03:04:05 + +-- !day_second_extract_4 -- +02 03:04:05 + +-- !day_second_extract_5 -- +02 16:34:05 + +-- !day_microsecond_add_1 -- +2023-01-03T05:07:09.691346 + +-- !day_microsecond_add_2 -- +2023-01-02T03:04:05.123455 + +-- !day_microsecond_add_3 -- +2023-01-03T05:07:09.246912 + +-- !day_microsecond_add_4 -- +2024-02-28T09:59:56.999999 + +-- !day_microsecond_add_5 -- +2023-01-09T11:13:11.246456 + +-- !day_microsecond_add_6 -- +2023-01-03T05:07:09.623456 + +-- !day_microsecond_add_7 -- +2023-01-03T05:07:09.623456 + +-- !day_microsecond_add_8 -- +2023-01-02T04:06:08.523456 + +-- !day_microsecond_add_9 -- +2025-09-28T03:04:05.123455 + +-- !day_microsecond_add_10 -- +2024-07-31T10:20:30.123456 + +-- !day_microsecond_add_11 -- +2024-08-31T11:20:30.123456 + +-- !day_microsecond_add_12 -- +2024-09-30T19:20:30.123456 + +-- !day_microsecond_add_13 -- +2024-11-01T00:50:30.123456 + +-- !day_microsecond_sub_1 -- +2023-01-01T01:01:00.555566 + +-- !day_microsecond_sub_2 -- +2023-01-01T01:01:01 + +-- !day_microsecond_sub_3 -- +2022-12-26T22:00:01.923456 + +-- !day_microsecond_sub_4 -- +2017-02-27T13:39:29.876544 + +-- !day_microsecond_sub_5 -- +2017-03-30T14:39:29.876544 + +-- !day_microsecond_sub_6 -- +2017-04-29T22:39:29.876544 + +-- !day_microsecond_sub_7 -- +2017-05-31T04:09:29.876544 + +-- !day_microsecond_extract_1 -- +02 03:04:05.123456 +29 10:00:00.000000 + +-- !day_microsecond_extract_2 -- +02 00:00:00.000000 + +-- !day_microsecond_extract_3 -- +02 03:04:05.123456 + +-- !day_microsecond_extract_4 -- +02 03:04:05.123456 + +-- !day_microsecond_extract_5 -- +02 16:34:05.123456 + +-- !hour_minute_add_1 -- +2023-01-02T05:34:05 + +-- !hour_minute_add_2 -- +2023-01-02T02:19:05.123456 + +-- !hour_minute_add_3 -- +2023-01-02T05:34:05.123456 + +-- !hour_minute_add_4 -- +2024-02-29T09:15 + +-- !hour_minute_add_5 -- +2023-01-02T06:49:05 + +-- !hour_minute_add_6 -- +2023-01-02T04:06:05.123456 + +-- !hour_minute_add_7 -- +2023-01-02T03:09:05.123456 + +-- !hour_minute_add_8 -- +2023-02-12T20:03:05.123456 + +-- !hour_minute_add_9 -- +2018-01-31T10:59 + +-- !hour_minute_add_10 -- +2018-02-28 11:59:00+08:00 + +-- !hour_minute_add_11 -- +2018-03-31 19:59:00+08:00 + +-- !hour_minute_add_12 -- +2018-05-01 01:29:00+08:00 + +-- !hour_minute_sub_1 -- +2023-01-02T00:34:05 + +-- !hour_minute_sub_2 -- +2023-01-02T00:34:05.123456 + +-- !hour_minute_sub_3 -- +2023-01-01T20:57:05 + +-- !hour_minute_sub_4 -- +2018-08-30T13:01 + +-- !hour_minute_sub_5 -- +2018-09-29 14:01:00+08:00 + +-- !hour_minute_sub_6 -- +2018-10-30 22:01:00+08:00 + +-- !hour_minute_sub_7 -- +2018-11-30 03:31:00+08:00 + +-- !hour_minute_extract_1 -- +03:04 +10:00 + +-- !hour_minute_extract_2 -- +00:00 + +-- !hour_minute_extract_3 -- +03:04 + +-- !hour_minute_extract_4 -- +03:04 + +-- !hour_minute_extract_5 -- +16:34 + +-- !hour_second_add_1 -- +2023-01-02T05:34:45 + +-- !hour_second_add_2 -- +2023-01-02T02:04:00.123456 + +-- !hour_second_add_3 -- +2023-01-02T05:34:45.123456 + +-- !hour_second_add_4 -- +2024-02-29T09:14:50 + +-- !hour_second_add_5 -- +2023-01-02T10:12:14 + +-- !hour_second_add_6 -- +2023-01-02T04:06:08.123456 + +-- !hour_second_add_7 -- +2023-01-02T03:04:45.123456 + +-- !hour_second_add_8 -- +2023-07-29T12:04:04.123456 + +-- !hour_second_add_9 -- +2017-06-30T10:20:30 + +-- !hour_second_add_10 -- +2017-07-31 11:20:30+08:00 + +-- !hour_second_add_11 -- +2017-08-31 19:20:30+08:00 + +-- !hour_second_add_12 -- +2017-10-01 00:50:30+08:00 + +-- !hour_second_sub_1 -- +2023-01-02T00:33:25 + +-- !hour_second_sub_2 -- +2023-01-02T00:33:25.123456 + +-- !hour_second_sub_3 -- +2023-01-01T20:56:57 + +-- !hour_second_sub_4 -- +2015-12-30T13:39:30 + +-- !hour_second_sub_5 -- +2015-11-29 14:39:30+08:00 + +-- !hour_second_sub_6 -- +2015-10-30 22:39:30+08:00 + +-- !hour_second_sub_7 -- +2015-09-30 04:09:30+08:00 + +-- !hour_second_extract_1 -- +03:04:05 +10:00:00 + +-- !hour_second_extract_2 -- +00:00:00 + +-- !hour_second_extract_3 -- +03:04:05 + +-- !hour_second_extract_4 -- +03:04:05 + +-- !hour_second_extract_5 -- +16:34:05 + +-- !hour_microsecond_add_1 -- +2023-01-02T05:34:45.246912 + +-- !hour_microsecond_add_2 -- +2023-01-02T03:04:05.123455 + +-- !hour_microsecond_add_3 -- +2023-01-02T05:34:45.246912 + +-- !hour_microsecond_add_4 -- +2024-02-29T09:14:49.999990 + +-- !hour_microsecond_add_5 -- +2023-01-02T04:06:08.123460 + +-- !hour_microsecond_add_6 -- +2023-01-02T04:06:08.523456 + +-- !hour_microsecond_add_7 -- +2023-01-02T03:04:10.723456 + +-- !hour_microsecond_add_8 -- +2034-05-30T20:04:05.123455 + +-- !hour_microsecond_add_9 -- +2013-12-31T10:20:30.123456 + +-- !hour_microsecond_add_10 -- +2013-11-30T11:20:30.123456 + +-- !hour_microsecond_add_11 -- +2013-10-31T19:20:30.123456 + +-- !hour_microsecond_add_12 -- +2013-10-01T00:50:30.123456 + +-- !hour_microsecond_sub_1 -- +2023-01-02T00:33:25 + +-- !hour_microsecond_sub_2 -- +2023-01-02T00:33:25 + +-- !hour_microsecond_sub_3 -- +2023-01-01T17:55:58.123450 + +-- !hour_microsecond_sub_4 -- +2011-12-30T13:39:29.876544 + +-- !hour_microsecond_sub_5 -- +2011-11-29T14:39:29.876544 + +-- !hour_microsecond_sub_6 -- +2011-10-30T22:39:29.876544 + +-- !hour_microsecond_sub_7 -- +2011-09-30T04:09:29.876544 + +-- !hour_microsecond_extract_1 -- +03:04:05.123456 +10:00:00.000000 + +-- !hour_microsecond_extract_2 -- +00:00:00.000000 + +-- !hour_microsecond_extract_3 -- +03:04:05.123456 + +-- !hour_microsecond_extract_4 -- +03:04:05.123456 + +-- !hour_microsecond_extract_5 -- +16:34:05.123456 + +-- !minute_second_add_1 -- +2023-01-02T03:49:55 + +-- !minute_second_add_2 -- +2023-01-02T02:53:45.123456 + +-- !minute_second_add_3 -- +2023-01-02T03:49:55.123456 + +-- !minute_second_add_4 -- +2024-02-29T09:49:40 + +-- !minute_second_add_5 -- +2023-01-02T03:11:13 + +-- !minute_second_add_6 -- +2023-01-02T03:05:07.123456 + +-- !minute_second_add_7 -- +2023-01-02T03:04:35.123456 + +-- !minute_second_add_8 -- +2023-12-15T08:25:04.123456 + +-- !minute_second_add_10 -- +2009-12-31T00:10:20 + +-- !minute_second_add_11 -- +2009-11-30 01:10:20+08:00 + +-- !minute_second_add_12 -- +2009-10-31 09:10:20+08:00 + +-- !minute_second_add_13 -- +2009-09-30 14:40:20+08:00 + +-- !minute_second_sub_1 -- +2023-01-02T02:18:15 + +-- !minute_second_sub_2 -- +2023-01-02T02:18:15.123456 + +-- !minute_second_sub_3 -- +2023-01-02T02:54:55 + +-- !minute_second_sub_4 -- +2007-12-30T23:49:40 + +-- !minute_second_sub_5 -- +2007-11-30 00:49:40+08:00 + +-- !minute_second_sub_6 -- +2007-10-31 08:49:40+08:00 + +-- !minute_second_sub_7 -- +2007-09-30 14:19:40+08:00 + +-- !minute_second_extract_1 -- +04:05 +00:00 + +-- !minute_second_extract_2 -- +00:00 + +-- !minute_second_extract_3 -- +04:05 + +-- !minute_second_extract_4 -- +04:05 + +-- !minute_second_extract_5 -- +34:05 + +-- !minute_microsecond_add_1 -- +2023-01-02T03:49:55.246912 + +-- !minute_microsecond_add_2 -- +2023-01-02T02:53:45.123436 + +-- !minute_microsecond_add_3 -- +2023-01-02T03:49:55.246912 + +-- !minute_microsecond_add_4 -- +2024-02-29T09:49:39.999980 + +-- !minute_microsecond_add_5 -- +2023-01-02T03:07:09.683456 + +-- !minute_microsecond_add_6 -- +2023-01-02T03:11:13.132456 + +-- !minute_microsecond_add_7 -- +2023-01-02T03:05:07.423456 + +-- !minute_microsecond_add_8 -- +2023-01-02T03:04:14.923456 + +-- !minute_microsecond_add_9 -- +2024-05-02T05:45:05.123455 + +-- !minute_microsecond_add_10 -- +2007-12-30T00:10:20.123456 + +-- !minute_microsecond_add_11 -- +2007-11-30T01:10:20.123456 + +-- !minute_microsecond_add_12 -- +2007-10-31T09:10:20.123456 + +-- !minute_microsecond_add_13 -- +2007-09-30T14:40:20.123456 + +-- !minute_microsecond_sub_1 -- +2023-01-02T02:18:15 + +-- !minute_microsecond_sub_2 -- +2023-01-02T02:18:15 + +-- !minute_microsecond_sub_3 -- +2023-01-02T02:54:55.122456 + +-- !minute_microsecond_sub_4 -- +2005-12-30T23:49:39.876544 + +-- !minute_microsecond_sub_5 -- +2005-11-30T00:49:39.876544 + +-- !minute_microsecond_sub_6 -- +2005-10-31T08:49:39.876544 + +-- !minute_microsecond_sub_7 -- +2005-09-30T14:19:39.876544 + +-- !minute_microsecond_extract_1 -- +04:05.123456 +00:00.000000 + +-- !minute_microsecond_extract_2 -- +00:00.000000 + +-- !minute_microsecond_extract_3 -- +04:05.123456 + +-- !minute_microsecond_extract_4 -- +04:05.123456 + +-- !minute_microsecond_extract_5 -- +34:05.123456 + +-- !second_microsecond_add_1 -- +2023-01-02T03:05:04.777777 + +-- !second_microsecond_add_2 -- +2023-01-02T03:04:00.123451 + +-- !second_microsecond_add_3 -- +2023-01-02T03:05:04.777777 + +-- !second_microsecond_add_4 -- +2024-02-29T09:59:54.999995 + +-- !second_microsecond_add_5 -- +2023-01-02T03:04:06.323456 + +-- !second_microsecond_add_6 -- +2023-01-02T03:04:12.923456 + +-- !second_microsecond_add_7 -- +2023-01-02T03:04:06.323456 + +-- !second_microsecond_add_8 -- +2023-01-02T03:04:05.823456 + +-- !second_microsecond_add_9 -- +2026-03-04T12:50:46.123455 + +-- !second_microsecond_add_10 -- +2004-12-31T00:00:10.123456 + +-- !second_microsecond_add_11 -- +2004-11-30 01:00:10.123456+08:00 + +-- !second_microsecond_sub_1 -- +2023-01-02T03:03:05.469135 + +-- !second_microsecond_sub_2 -- +2023-01-02T03:03:05.469135 + +-- !second_microsecond_sub_3 -- +2023-01-02T03:03:55.323456 + +-- !second_microsecond_sub_4 -- +2002-12-30T23:59:49.876544 + +-- !second_microsecond_sub_5 -- +2002-11-30 00:59:49.876544+08:00 + +-- !second_microsecond_extract_1 -- +05.123456 +00.000000 + +-- !second_microsecond_extract_2 -- +00.000000 + +-- !second_microsecond_extract_3 -- +05.123456 + +-- !second_microsecond_extract_4 -- +05.123456 + +-- !second_microsecond_extract_5 -- +05.123456 + diff --git a/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out b/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out index 9032bc441f2329..87cf2ba7de6e79 100644 --- a/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out +++ b/regression-test/data/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.out @@ -33,6 +33,40 @@ -- !sql -- 2025-10-27T22:58:59 +-- !add_day_second_1 -- +2025-10-28T09:09:09 + +-- !add_day_second_2 -- +2025-10-27T22:58:59 + +-- !add_day_second_3 -- +2025-10-24T01:02:04.123456 +2025-10-29T10:10:11 + +-- !add_day_second_4 -- +2025-10-24T01:03:05.123456 +2025-10-29T10:11:12 + +-- !add_day_second_5 -- +2025-10-24T02:04:06.123456 +2025-10-29T11:12:13 + +-- !add_day_second_6 -- +2025-10-24T01:02:04.123456 +2025-10-29T10:10:11 + +-- !add_day_second_7 -- +2025-10-24T02:02:04.123456 +2025-10-29T11:10:11 + +-- !add_day_second_8 -- +2025-10-24T02:02:04.123456 +2025-10-29T11:10:11 + +-- !add_day_second_9 -- +2025-10-24T02:02:03.123456 +2025-10-29T11:10:10 + -- !sql -- 2025-10-25T02:02:03.123456 2025-10-30T11:10:10 @@ -97,6 +131,27 @@ -- !sql -- 2025-10-27T14:00 +-- !add_day_hour_1 -- +2025-10-29T11:10:10 + +-- !add_day_hour_2 -- +2025-10-29T20:10:10 + +-- !add_day_hour_3 -- +2025-10-29T11:10:10 + +-- !add_day_hour_4 -- +2025-10-24T02:02:03.123456 +2025-10-29T11:10:10 + +-- !add_day_hour_5 -- +2025-10-24T11:02:03.123456 +2025-10-29T20:10:10 + +-- !add_day_hour_6 -- +2025-10-24T02:02:03.123456 +2025-10-29T11:10:10 + -- !sql -- 2025-10-24T01:03:04.123456 2025-10-29T10:11:11 @@ -161,6 +216,27 @@ -- !sql -- 2025-10-28T23:58:50 +-- !add_minute_second_1 -- +2025-10-29T10:10:11 + +-- !add_minute_second_2 -- +2025-10-29T10:10:20 + +-- !add_minute_second_3 -- +2025-10-29T10:10:11 + +-- !add_minute_second_4 -- +2025-10-24T01:02:04.123456 +2025-10-29T10:10:11 + +-- !add_minute_second_5 -- +2025-10-24T01:02:13.123456 +2025-10-29T10:10:20 + +-- !add_minute_second_6 -- +2025-10-24T01:02:04.123456 +2025-10-29T10:10:11 + -- !sql -- 2025-10-24T01:02:04.223456 2025-10-29T10:10:11.100 @@ -225,3 +301,24 @@ -- !sql -- 2025-10-28T23:59:57.765433 +-- !add_second_microsecond_1 -- +2025-10-29T10:10:10.100 + +-- !add_second_microsecond_2 -- +2025-10-29T10:10:10.100 + +-- !add_second_microsecond_3 -- +2025-10-29T10:10:10.100 + +-- !add_second_microsecond_4 -- +2025-10-24T01:02:03.223456 +2025-10-29T10:10:10.100 + +-- !add_second_microsecond_5 -- +2025-10-24T01:02:03.223456 +2025-10-29T10:10:10.100 + +-- !add_second_microsecond_6 -- +2025-10-24T01:02:03.223456 +2025-10-29T10:10:10.100 + diff --git a/regression-test/suites/doc/sql-manual/sql-functions/doc_date_functions_test.groovy b/regression-test/suites/doc/sql-manual/sql-functions/doc_date_functions_test.groovy index d48690451b4720..4b41c9ed1ac005 100644 --- a/regression-test/suites/doc/sql-manual/sql-functions/doc_date_functions_test.groovy +++ b/regression-test/suites/doc/sql-manual/sql-functions/doc_date_functions_test.groovy @@ -778,7 +778,7 @@ suite("doc_date_functions_test") { qt_from_days_3 """select from_days(NULL)""" // 21. FROM_ISO8601_DATE function tests - qt_from_iso8601_date_1 """select from_iso8601_date('2023') as year_only, from_iso8601_date('2023-10') as year_month, from_iso8601_date('2023-10-05') as full_date""" + qt_from_iso8601_date_1 """select from_iso8601_date('2023') as year_only, from_iso8601_date('2023-10') as year_and_month, from_iso8601_date('2023-10-05') as full_date""" qt_from_iso8601_date_2 """select from_iso8601_date('2021-001') as day_1, from_iso8601_date('2021-059') as day_59, from_iso8601_date('2021-060') as day_60, from_iso8601_date('2024-366') as day_366""" qt_from_iso8601_date_3 """select from_iso8601_date('0522-W01-1') as week_1""" qt_from_iso8601_date_4 """select from_iso8601_date('0522-W01-4') as week_4""" @@ -2399,7 +2399,7 @@ suite("doc_date_functions_test") { // 21. FROM_ISO8601_DATE function constant folding tests testFoldConst("SELECT FROM_ISO8601_DATE('2023') as year_only") - testFoldConst("SELECT FROM_ISO8601_DATE('2023-10') as year_month") + testFoldConst("SELECT FROM_ISO8601_DATE('2023-10')") testFoldConst("SELECT FROM_ISO8601_DATE('2023-10-05') as full_date") testFoldConst("SELECT FROM_ISO8601_DATE('2021-001') as day_1") testFoldConst("SELECT FROM_ISO8601_DATE('2021-060') as day_60") diff --git a/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.groovy b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.groovy new file mode 100644 index 00000000000000..924fa98528f509 --- /dev/null +++ b/regression-test/suites/nereids_p0/sql_functions/datetime_functions/test_add_sub_union_type.groovy @@ -0,0 +1,645 @@ +// Licensed to the Apache Software Foundation (ASF) under one +// or more contributor license agreements. See the NOTICE file +// distributed with this work for additional information +// regarding copyright ownership. The ASF licenses this file +// to you under the Apache License, Version 2.0 (the +// "License"); you may not use this file except in compliance +// with the License. You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, +// software distributed under the License is distributed on an +// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// KIND, either express or implied. See the License for the +// specific language governing permissions and limitations +// under the License. + +suite('test_add_sub_union_type') { + sql """ set time_zone = '+08:00'; """ + + sql """drop table if exists test_add_sub_union_type""" + + sql """ + create table test_add_sub_union_type ( + dt datetimev2(6), + iv_year_month string, + iv_day_hour string, + iv_day_minute string, + iv_day_second string, + iv_day_microsecond string, + iv_hour_minute string, + iv_hour_second string, + iv_hour_microsecond string, + iv_minute_second string, + iv_minute_microsecond string, + iv_second_microsecond string + ) duplicate key(dt) + distributed by hash(dt) buckets 1 + properties('replication_num'='1'); + """ + + sql """ + insert into test_add_sub_union_type values + ('2023-01-02 03:04:05.123456', '1-2', '1 2', '1 02:03', '1 02:03:04', + '1 02:03:04.123456', '2:30', '2:30:40', '2:30:40.123456', '45:50', + '45:50.123456', '59.654321'), + ('2024-02-29 10:00:00.000000', '-0-2', '-1 0', '-1 00:01', '-1 00:00:02', + '-1 00:00:03.000001', '-0:45', '-0:45:10', '-0:45:10.000010', '-10:20', + '-10:20.000020', '-5.000005'); + """ + + // YEAR_MONTH add/sub + qt_year_month_add_1 """select date_add('2023-01-02', interval '1-2' year_month)""" + qt_year_month_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-0-3' year_month)""" + qt_year_month_add_3 """select date_add(dt, interval iv_year_month year_month) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_year_month_add_4 """select date_add(dt, interval iv_year_month year_month) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_year_month_add_5 """select date_add('2023-01-31', interval '1-01' year_month)""" + qt_year_month_add_6 """select date_add('2023-02-28 12:00:00.000000+08:00', interval '1-01' year_month)""" + qt_year_month_add_7 """select date_add('2023-03-31 12:00:00.000000+00:00', interval '1-01' year_month)""" + qt_year_month_add_8 """select date_add('2023-04-30 12:00:00.000000-05:30', interval '1-01' year_month)""" + qt_year_month_add_9 """select date_add('2023-01-02', interval '3&4' year_month)""" + qt_year_month_add_10 """select date_add('2023-01-02', interval '1--2' year_month)""" + qt_year_month_add_11 """select date_add('2023-01-02', interval '5' year_month)""" + qt_year_month_add_12 """select date_add('2023-01-02', interval '1234-11' year_month)""" + qt_year_month_add_13 """select date_add('2021-1-31', interval '1-1' year_month)""" + qt_year_month_add_14 """select date_add('2023-1-31', interval '1-1' year_month)""" + test { + sql """select date_add('2023-01-02', interval '1-2-3' year_month)""" + exception "Operation year_month_add of 1-2-3 is invalid" + } + testFoldConst("select date_add('2023-01-02', interval '3&4' year_month)") + testFoldConst("select date_add('2023-01-02', interval '1--2' year_month)") + testFoldConst("select date_add('2023-01-02', interval '5' year_month)") + testFoldConst("select date_add('2023-01-02', interval '1234-11' year_month)") + testFoldConst("select date_add('2023-05-31', interval '1-01' year_month)") + testFoldConst("select date_add('2023-06-30 12:00:00.000000+08:00', interval '1-01' year_month)") + testFoldConst("select date_add('2023-07-31 12:00:00.000000+00:00', interval '1-01' year_month)") + testFoldConst("select date_add('2023-08-31 12:00:00.000000-05:30', interval '1-01' year_month)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '2-11' year_month)") + testFoldConst("select date_add('2024-02-29 23:59:59', interval '-0-0' year_month)") + testFoldConst("select date_add('2021-1-31', interval '1-1' year_month)") + testFoldConst("select date_add('2023-1-31', interval '1-1' year_month)") + + qt_year_month_sub_1 """select date_sub('2023-01-02', interval '1-2' year_month)""" + qt_year_month_sub_2 """select date_sub(dt, interval iv_year_month year_month) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_year_month_sub_3 """select date_sub('2023-03-31', interval '0-11' year_month)""" + qt_year_month_sub_4 """select date_sub('2023-04-30 12:00:00.000000+08:00', interval '0-11' year_month)""" + qt_year_month_sub_5 """select date_sub('2023-05-31 12:00:00.000000+00:00', interval '0-11' year_month)""" + qt_year_month_sub_6 """select date_sub('2023-06-30 12:00:00.000000-05:30', interval '0-11' year_month)""" + qt_year_month_sub_7 """select date_sub('2023-01-02', interval '5@6' year_month)""" + testFoldConst("select date_sub('2023-07-31 23:59:59', interval '0-6' year_month)") + testFoldConst("select date_sub('2023-08-31 12:00:00.000000+08:00', interval '0-11' year_month)") + testFoldConst("select date_sub('2023-09-30 12:00:00.000000+00:00', interval '0-11' year_month)") + testFoldConst("select date_sub('2023-10-31 12:00:00.000000-05:30', interval '0-11' year_month)") + testFoldConst("select date_sub('0001-01-01 00:00:00', interval '-10-00' year_month)") + + // YEAR_MONTH extract + qt_year_month_extract_1 """select extract(year_month from dt) from test_add_sub_union_type order by dt""" + qt_year_month_extract_2 """select extract(year_month from '2023-01-02')""" + qt_year_month_extract_3 """select extract(year_month from '2023-01-02 03:04:05.123456')""" + qt_year_month_extract_4 """select extract(year_month from '2023-01-01 01:04:05.123456+12:00')""" + qt_year_month_extract_5 """select extract(year_month from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(year_month from '2023-01-02')") + testFoldConst("select extract(year_month from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(year_month from '2023-01-01 01:04:05.123456+12:00')") + testFoldConst("select extract(year_month from '2023-01-02 03:04:05.123456-05:30')") + + // DAY_HOUR add/sub + qt_day_hour_add_1 """select date_add('2023-01-02 03:04:05', interval '1 2' day_hour)""" + qt_day_hour_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-2 03' day_hour)""" + qt_day_hour_add_3 """select date_add(dt, interval iv_day_hour day_hour) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_hour_add_4 """select date_add(dt, interval iv_day_hour day_hour) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_day_hour_add_5 """select date_add('2023-01-02 03:04:05', interval '7&8' day_hour)""" + qt_day_hour_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1@@2' day_hour)""" + qt_day_hour_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '12' day_hour)""" + qt_day_hour_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '999 23' day_hour)""" + qt_day_hour_add_9 """select date_add('2023-02-28', interval '1 10' day_hour)""" + qt_day_hour_add_10 """select date_add('2023-03-31 01:00:00+08:00', interval '1 10' day_hour)""" + qt_day_hour_add_11 """select date_add('2023-04-30 01:00:00+00:00', interval '1 10' day_hour)""" + qt_day_hour_add_12 """select date_add('2023-05-31 01:00:00-05:30', interval '1 10' day_hour)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '7&8' day_hour)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1@@2' day_hour)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '12' day_hour)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '999 23' day_hour)") + testFoldConst("select date_add('2023-06-30 23:00:00', interval '2 10' day_hour)") + testFoldConst("select date_add('2023-07-31 23:00:00', interval '-0 00' day_hour)") + testFoldConst("select date_add('2023-08-31', interval '1 10' day_hour)") + testFoldConst("select date_add('2023-09-30 01:00:00+08:00', interval '1 10' day_hour)") + testFoldConst("select date_add('2023-10-31 01:00:00+00:00', interval '1 10' day_hour)") + testFoldConst("select date_add('2023-11-30 01:00:00-05:30', interval '1 10' day_hour)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1 2 3 4' day_hour)""" + exception "Operation day_hour_add of" + } + + qt_day_hour_sub_1 """select date_sub('2023-01-02 03:04:05', interval '1 2' day_hour)""" + qt_day_hour_sub_2 """select date_sub(dt, interval iv_day_hour day_hour) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_hour_sub_3 """select date_sub('2023-01-02 03:04:05', interval '9@10' day_hour)""" + qt_day_hour_sub_4 """select date_sub('2023-11-30', interval '1 10' day_hour)""" + qt_day_hour_sub_5 """select date_sub('2023-10-31 01:00:00+08:00', interval '1 10' day_hour)""" + qt_day_hour_sub_6 """select date_sub('2023-09-30 01:00:00+00:00', interval '1 10' day_hour)""" + qt_day_hour_sub_7 """select date_sub('2023-08-31 01:00:00-05:30', interval '1 10' day_hour)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '9@10' day_hour)") + testFoldConst("select date_sub('2023-06-30 23:00:00', interval '2 10' day_hour)") + testFoldConst("select date_sub('2023-07-31 23:00:00', interval '000 000' day_hour)") + testFoldConst("select date_sub('2023-08-31', interval '1 10' day_hour)") + testFoldConst("select date_sub('2022-12-31 01:00:00+08:00', interval '1 10' day_hour)") + testFoldConst("select date_sub('2022-12-31 01:00:00+00:00', interval '1 10' day_hour)") +testFoldConst("select date_sub('2022-12-31 01:00:00-05:30', interval '1 10' day_hour)") + + // DAY_HOUR extract + qt_day_hour_extract_1 """select extract(day_hour from dt) from test_add_sub_union_type order by dt""" + qt_day_hour_extract_2 """select extract(day_hour from '2023-01-02')""" + qt_day_hour_extract_3 """select extract(day_hour from '2023-01-02 03:04:05.123456')""" + qt_day_hour_extract_4 """select extract(day_hour from '2023-01-02 03:04:05.123456+08:00')""" + qt_day_hour_extract_5 """select extract(day_hour from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(day_hour from '2023-01-02')") + testFoldConst("select extract(day_hour from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(day_hour from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(day_hour from '2023-01-02 03:04:05.123456-05:30')") + + // DAY_MINUTE add/sub + qt_day_minute_add_1 """select date_add('2023-01-02 03:04:05', interval '1 02:03' day_minute)""" + qt_day_minute_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-2 03:04' day_minute)""" + qt_day_minute_add_3 """select date_add(dt, interval iv_day_minute day_minute) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_minute_add_4 """select date_add(dt, interval iv_day_minute day_minute) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_day_minute_add_5 """select date_add('2023-01-02 03:04:05', interval '3&04:05' day_minute)""" + qt_day_minute_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1::02**03' day_minute)""" + qt_day_minute_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '30' day_minute)""" + qt_day_minute_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '999 23:59' day_minute)""" + qt_day_minute_add_9 """select date_add('2023-02-28', interval '1 10:59' day_minute)""" + qt_day_minute_add_10 """select date_add('2023-03-31 01:00:00+08:00', interval '1 10:59' day_minute)""" + qt_day_minute_add_11 """select date_add('2023-04-30 01:00:00+00:00', interval '1 10:59' day_minute)""" + qt_day_minute_add_12 """select date_add('2023-05-31 01:00:00-05:30', interval '1 10:59' day_minute)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '3&04:05' day_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::02**03' day_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '30' day_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '999 23:59' day_minute)") + testFoldConst("select date_add('2023-06-30 23:59:59', interval '0 10:59' day_minute)") + testFoldConst("select date_add('2023-07-31 23:59:59', interval '-1 00:00' day_minute)") + testFoldConst("select date_add('2023-08-31', interval '1 10:59' day_minute)") + testFoldConst("select date_add('2023-09-30 01:00:00+08:00', interval '1 10:59' day_minute)") + testFoldConst("select date_add('2023-10-31 01:00:00+00:00', interval '1 10:59' day_minute)") + testFoldConst("select date_add('2023-11-30 01:00:00-05:30', interval '1 10:59' day_minute)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1 2 3 4 5' day_minute)""" + exception "Operation day_minute_add of" + } + + qt_day_minute_sub_1 """select date_sub('2023-01-02 03:04:05', interval '1 02:03' day_minute)""" + qt_day_minute_sub_2 """select date_sub(dt, interval iv_day_minute day_minute) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_minute_sub_3 """select date_sub('2023-01-02 03:04:05', interval '5@06:07' day_minute)""" + qt_day_minute_sub_4 """select date_sub('2023-11-30', interval '1 10:59' day_minute)""" + qt_day_minute_sub_5 """select date_sub('2023-10-31 01:00:00+08:00', interval '1 10:59' day_minute)""" + qt_day_minute_sub_6 """select date_sub('2023-09-30 01:00:00+00:00', interval '1 10:59' day_minute)""" + qt_day_minute_sub_7 """select date_sub('2023-08-31 01:00:00-05:30', interval '1 10:59' day_minute)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '5@06:07' day_minute)") + testFoldConst("select date_sub('2023-06-30 23:59:59', interval '0 10:59' day_minute)") + testFoldConst("select date_sub('2023-07-31 23:59:59', interval '000 00:00' day_minute)") + testFoldConst("select date_sub('2023-08-31', interval '1 10:59' day_minute)") + testFoldConst("select date_sub('2025-04-30 01:00:00+08:00', interval '1 10:59' day_minute)") + testFoldConst("select date_sub('2025-05-31 01:00:00+00:00', interval '1 10:59' day_minute)") +testFoldConst("select date_sub('2025-06-30 01:00:00-05:30', interval '1 10:59' day_minute)") + + // DAY_MINUTE extract + qt_day_minute_extract_1 """select extract(day_minute from dt) from test_add_sub_union_type order by dt""" + qt_day_minute_extract_2 """select extract(day_minute from '2023-01-02')""" + qt_day_minute_extract_3 """select extract(day_minute from '2023-01-02 03:04:05.123456')""" + qt_day_minute_extract_4 """select extract(day_minute from '2023-01-02 03:04:05.123456+08:00')""" + qt_day_minute_extract_5 """select extract(day_minute from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(day_minute from '2023-01-02')") + testFoldConst("select extract(day_minute from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(day_minute from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(day_minute from '2023-01-02 03:04:05.123456-05:30')") + + // DAY_SECOND add/sub + qt_day_second_add_1 """select date_add('2023-01-02 03:04:05', interval '1 02:03:04' day_second)""" + qt_day_second_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-2 03:04:05' day_second)""" + qt_day_second_add_3 """select date_add(dt, interval iv_day_second day_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_second_add_4 """select date_add(dt, interval iv_day_second day_second) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_day_second_add_5 """select date_add(dt, interval c day_second) from (select dt, '0 0:0:7' c from test_add_sub_union_type limit 1) t""" + qt_day_second_add_6 """select date_add('2023-01-02 03:04:05', interval '7&8:9' day_second)""" + qt_day_second_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '1::02**03::04' day_second)""" + qt_day_second_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '2:3:4' day_second)""" + qt_day_second_add_9 """select date_add('2023-01-02 03:04:05.123456', interval '999 23:59:59' day_second)""" + qt_day_second_add_10 """select date_add('2021-12-31', interval '1 10:20:30' day_second)""" + qt_day_second_add_11 """select date_add('2021-11-30 01:00:00+08:00', interval '1 10:20:30' day_second)""" + qt_day_second_add_12 """select date_add('2021-10-31 01:00:00+00:00', interval '1 10:20:30' day_second)""" + qt_day_second_add_13 """select date_add('2021-09-30 01:00:00-05:30', interval '1 10:20:30' day_second)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '7&8:9' day_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::02**03::04' day_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '2:3:4' day_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '999 23:59:59' day_second)") + testFoldConst("select date_add('2021-11-30 23:59:50', interval '0 00:00:15' day_second)") + testFoldConst("select date_add('2021-10-31 23:59:50', interval '-0 00:00:00' day_second)") + testFoldConst("select date_add('2020-02-29', interval '1 10:20:30' day_second)") + testFoldConst("select date_add('2016-02-29 01:00:00+08:00', interval '1 10:20:30' day_second)") + testFoldConst("select date_add('2024-01-02 01:00:00+00:00', interval '1 10:20:30' day_second)") + testFoldConst("select date_add('2024-03-31 01:00:00-05:30', interval '1 10:20:30' day_second)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1 2 3 4 5 6' day_second)""" + exception "Operation day_second_add of" + } + + qt_day_second_sub_1 """select date_sub('2023-01-02 03:04:05', interval '1 02:03:04' day_second)""" + qt_day_second_sub_2 """select date_sub(dt, interval iv_day_second day_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_second_sub_3 """select date_sub('2023-01-02 03:04:05', interval '5@06:07' day_second)""" + qt_day_second_sub_4 """select date_sub('2019-02-28', interval '1 10:20:30' day_second)""" + qt_day_second_sub_5 """select date_sub('2019-01-31 01:00:00+08:00', interval '1 10:20:30' day_second)""" + qt_day_second_sub_6 """select date_sub('2019-03-31 01:00:00+00:00', interval '1 10:20:30' day_second)""" + qt_day_second_sub_7 """select date_sub('2019-04-30 01:00:00-05:30', interval '1 10:20:30' day_second)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '5@06:07' day_second)") + testFoldConst("select date_sub('2018-12-31 23:59:50', interval '0 00:00:15' day_second)") + testFoldConst("select date_sub('2018-11-30 23:59:50', interval '10 10:10:10' day_second)") + testFoldConst("select date_sub('2022-02-28', interval '1 10:20:30' day_second)") + testFoldConst("select date_sub('2022-03-31 01:00:00+08:00', interval '1 10:20:30' day_second)") + testFoldConst("select date_sub('2022-04-30 01:00:00+00:00', interval '1 10:20:30' day_second)") + testFoldConst("select date_sub('2022-05-31 01:00:00-05:30', interval '1 10:20:30' day_second)") + + // DAY_SECOND extract + qt_day_second_extract_1 """select extract(day_second from dt) from test_add_sub_union_type order by dt""" + qt_day_second_extract_2 """select extract(day_second from '2023-01-02')""" + qt_day_second_extract_3 """select extract(day_second from '2023-01-02 03:04:05.123456')""" + qt_day_second_extract_4 """select extract(day_second from '2023-01-02 03:04:05.123456+08:00')""" + qt_day_second_extract_5 """select extract(day_second from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(day_second from '2023-01-02')") + testFoldConst("select extract(day_second from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(day_second from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(day_second from '2023-01-02 03:04:05.123456-05:30')") + + // DAY_MICROSECOND add/sub + qt_day_microsecond_add_1 """select date_add('2023-01-02 03:04:05.123456', interval '1 02:03:04.567890' day_microsecond)""" + qt_day_microsecond_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-0 00:00:00.000001' day_microsecond)""" + qt_day_microsecond_add_3 """select date_add(dt, interval iv_day_microsecond day_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_microsecond_add_4 """select date_add(dt, interval iv_day_microsecond day_microsecond) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_day_microsecond_add_5 """select date_add('2023-01-02 03:04:05.123456', interval '7&8:9!?6.123' day_microsecond)""" + qt_day_microsecond_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1!2@3#4_5^' day_microsecond)""" + qt_day_microsecond_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '1::02**03::04..5' day_microsecond)""" + qt_day_microsecond_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '1 2:3:4' day_microsecond)""" + qt_day_microsecond_add_9 """select date_add('2023-01-02 03:04:05.123456', interval '999 23:59:59.999999' day_microsecond)""" + qt_day_microsecond_add_10 """select date_add('2024-07-31', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_add_11 """select date_add('2024-08-31 01:00:00+08:00', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_add_12 """select date_add('2024-09-30 01:00:00+00:00', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_add_13 """select date_add('2024-10-31 01:00:00-05:30', interval '0 10:20:30.123456' day_microsecond)""" + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '7&8:9!?6.123' day_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1!2@3#4_5^' day_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::02**03::04..5' day_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1 2:3:4' day_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '999 23:59:59.999999' day_microsecond)") + testFoldConst("select date_add('2000-02-29 23:59:59.999999', interval '0 00:00:00.000005' day_microsecond)") + testFoldConst("select date_add('2004-02-29 23:59:59.123456', interval '-0 00:00:00.000010' day_microsecond)") + testFoldConst("select date_add('2025-12-31', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_add('2025-11-30 01:00:00+08:00', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_add('2026-01-01 01:00:00+00:00', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_add('2015-06-30 01:00:00-05:30', interval '0 10:20:30.123456' day_microsecond)") + test { + sql """select date_add('2023-01-02 03:04:05.123456', interval '1 2 3 4 5 6 7' day_microsecond)""" + exception "Operation day_microsecond_add of" + } + + qt_day_microsecond_sub_1 """select date_sub('2023-01-02 03:04:05.123456', interval '1 02:03:04.567890' day_microsecond)""" + qt_day_microsecond_sub_2 """select date_sub(dt, interval iv_day_microsecond day_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_day_microsecond_sub_3 """select date_sub('2023-01-02 03:04:05.123456', interval '6!5@4#3_2^!' day_microsecond)""" + qt_day_microsecond_sub_4 """select date_sub('2017-02-28', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_sub_5 """select date_sub('2017-03-31 01:00:00+08:00', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_sub_6 """select date_sub('2017-04-30 01:00:00+00:00', interval '0 10:20:30.123456' day_microsecond)""" + qt_day_microsecond_sub_7 """select date_sub('2017-05-31 01:00:00-05:30', interval '0 10:20:30.123456' day_microsecond)""" + testFoldConst("select date_sub('2023-01-02 03:04:05.123456', interval '6!5@4#3_2^!' day_microsecond)") + testFoldConst("select date_sub('2008-02-29 23:59:59.999999', interval '0 00:00:00.000005' day_microsecond)") + testFoldConst("select date_sub('0001-01-01 00:00:00.000001', interval '0 00:00:00.000001' day_microsecond)") + testFoldConst("select date_sub('2016-03-31', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_sub('2016-04-30 01:00:00+08:00', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_sub('2016-05-31 01:00:00+00:00', interval '0 10:20:30.123456' day_microsecond)") + testFoldConst("select date_sub('2016-06-30 01:00:00-05:30', interval '0 10:20:30.123456' day_microsecond)") + + // DAY_MICROSECOND extract + qt_day_microsecond_extract_1 """select extract(day_microsecond from dt) from test_add_sub_union_type order by dt""" + qt_day_microsecond_extract_2 """select extract(day_microsecond from '2023-01-02')""" + qt_day_microsecond_extract_3 """select extract(day_microsecond from '2023-01-02 03:04:05.123456')""" + qt_day_microsecond_extract_4 """select extract(day_microsecond from '2023-01-02 03:04:05.123456+08:00')""" + qt_day_microsecond_extract_5 """select extract(day_microsecond from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(day_microsecond from '2023-01-02')") + testFoldConst("select extract(day_microsecond from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(day_microsecond from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(day_microsecond from '2023-01-02 03:04:05.123456-05:30')") + + // HOUR_MINUTE add/sub + qt_hour_minute_add_1 """select date_add('2023-01-02 03:04:05', interval '2:30' hour_minute)""" + qt_hour_minute_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-0:45' hour_minute)""" + qt_hour_minute_add_3 """select date_add(dt, interval iv_hour_minute hour_minute) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_minute_add_4 """select date_add(dt, interval iv_hour_minute hour_minute) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_hour_minute_add_5 """select date_add('2023-01-02 03:04:05', interval '3&45' hour_minute)""" + qt_hour_minute_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1::2' hour_minute)""" + qt_hour_minute_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '5' hour_minute)""" + qt_hour_minute_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '1000:59' hour_minute)""" + qt_hour_minute_add_9 """select date_add('2018-01-31', interval '10:59' hour_minute)""" + qt_hour_minute_add_10 """select date_add('2018-02-28 01:00:00+08:00', interval '10:59' hour_minute)""" + qt_hour_minute_add_11 """select date_add('2018-03-31 01:00:00+00:00', interval '10:59' hour_minute)""" + qt_hour_minute_add_12 """select date_add('2018-04-30 01:00:00-05:30', interval '10:59' hour_minute)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '3&45' hour_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::2' hour_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '5' hour_minute)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1000:59' hour_minute)") + testFoldConst("select date_add('2019-05-31 23:59:59', interval '10:59' hour_minute)") + testFoldConst("select date_add('2019-06-30 23:59:59', interval '-00:00' hour_minute)") + testFoldConst("select date_add('2019-07-31', interval '10:59' hour_minute)") + testFoldConst("select date_add('2019-12-01 01:00:00+08:00', interval '10:59' hour_minute)") + testFoldConst("select date_add('2020-02-29 01:00:00+00:00', interval '10:59' hour_minute)") + testFoldConst("select date_add('2020-03-31 01:00:00-05:30', interval '10:59' hour_minute)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1:2:3' hour_minute)""" + exception "Operation hour_minute_add of" + } + + qt_hour_minute_sub_1 """select date_sub('2023-01-02 03:04:05', interval '2:30' hour_minute)""" + qt_hour_minute_sub_2 """select date_sub(dt, interval iv_hour_minute hour_minute) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_minute_sub_3 """select date_sub('2023-01-02 03:04:05', interval '6@07' hour_minute)""" + qt_hour_minute_sub_4 """select date_sub('2018-08-31', interval '10:59' hour_minute)""" + qt_hour_minute_sub_5 """select date_sub('2018-09-30 01:00:00+08:00', interval '10:59' hour_minute)""" + qt_hour_minute_sub_6 """select date_sub('2018-10-31 01:00:00+00:00', interval '10:59' hour_minute)""" + qt_hour_minute_sub_7 """select date_sub('2018-11-30 01:00:00-05:30', interval '10:59' hour_minute)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '6@07' hour_minute)") + testFoldConst("select date_sub('2019-08-31 23:59:59', interval '10:59' hour_minute)") + testFoldConst("select date_sub('2019-09-30 23:59:59', interval '99:59' hour_minute)") + testFoldConst("select date_sub('2019-10-31', interval '10:59' hour_minute)") + testFoldConst("select date_sub('2019-11-30 01:00:00+08:00', interval '10:59' hour_minute)") + testFoldConst("select date_sub('2019-12-31 01:00:00+00:00', interval '10:59' hour_minute)") + testFoldConst("select date_sub('2020-01-31 01:00:00-05:30', interval '10:59' hour_minute)") + + // HOUR_MINUTE extract + qt_hour_minute_extract_1 """select extract(hour_minute from dt) from test_add_sub_union_type order by dt""" + qt_hour_minute_extract_2 """select extract(hour_minute from '2023-01-02')""" + qt_hour_minute_extract_3 """select extract(hour_minute from '2023-01-02 03:04:05.123456')""" + qt_hour_minute_extract_4 """select extract(hour_minute from '2023-01-02 03:04:05.123456+08:00')""" + qt_hour_minute_extract_5 """select extract(hour_minute from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(hour_minute from '2023-01-02')") + testFoldConst("select extract(hour_minute from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(hour_minute from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(hour_minute from '2023-01-02 03:04:05.123456-05:30')") + + // HOUR_SECOND add/sub + qt_hour_second_add_1 """select date_add('2023-01-02 03:04:05', interval '2:30:40' hour_second)""" + qt_hour_second_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-1:00:05' hour_second)""" + qt_hour_second_add_3 """select date_add(dt, interval iv_hour_second hour_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_second_add_4 """select date_add(dt, interval iv_hour_second hour_second) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_hour_second_add_5 """select date_add('2023-01-02 03:04:05', interval '7&8:9' hour_second)""" + qt_hour_second_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1::2**3' hour_second)""" + qt_hour_second_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '40' hour_second)""" + qt_hour_second_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '5000:59:59' hour_second)""" + qt_hour_second_add_9 """select date_add('2017-06-30', interval '10:20:30' hour_second)""" + qt_hour_second_add_10 """select date_add('2017-07-31 01:00:00+08:00', interval '10:20:30' hour_second)""" + qt_hour_second_add_11 """select date_add('2017-08-31 01:00:00+00:00', interval '10:20:30' hour_second)""" + qt_hour_second_add_12 """select date_add('2017-09-30 01:00:00-05:30', interval '10:20:30' hour_second)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '7&8:9' hour_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::2**3' hour_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '40' hour_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '5000:59:59' hour_second)") + testFoldConst("select date_add('2016-07-31 23:59:50', interval '0:00:15' hour_second)") + testFoldConst("select date_add('2016-06-30 23:59:50', interval '-00:00:00' hour_second)") + testFoldConst("select date_add('2016-05-31', interval '10:20:30' hour_second)") + testFoldConst("select date_add('2016-08-31 01:00:00+08:00', interval '10:20:30' hour_second)") + testFoldConst("select date_add('2016-09-30 01:00:00+00:00', interval '10:20:30' hour_second)") + testFoldConst("select date_add('2016-10-31 01:00:00-05:30', interval '10:20:30' hour_second)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1:2:3:4' hour_second)""" + exception "Operation hour_second_add of" + } + + qt_hour_second_sub_1 """select date_sub('2023-01-02 03:04:05', interval '2:30:40' hour_second)""" + qt_hour_second_sub_2 """select date_sub(dt, interval iv_hour_second hour_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_second_sub_3 """select date_sub('2023-01-02 03:04:05', interval '6@7:8' hour_second)""" + qt_hour_second_sub_4 """select date_sub('2015-12-31', interval '10:20:30' hour_second)""" + qt_hour_second_sub_5 """select date_sub('2015-11-30 01:00:00+08:00', interval '10:20:30' hour_second)""" + qt_hour_second_sub_6 """select date_sub('2015-10-31 01:00:00+00:00', interval '10:20:30' hour_second)""" + qt_hour_second_sub_7 """select date_sub('2015-09-30 01:00:00-05:30', interval '10:20:30' hour_second)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '6@7:8' hour_second)") + testFoldConst("select date_sub('2014-12-31 23:59:50', interval '0:00:15' hour_second)") + testFoldConst("select date_sub('2014-11-30 23:59:50', interval '10*-10:10' hour_second)") + testFoldConst("select date_sub('2014-10-31', interval '10:20:30' hour_second)") + testFoldConst("select date_sub('2014-09-30 01:00:00+08:00', interval '10:20:30' hour_second)") + testFoldConst("select date_sub('2014-08-31 01:00:00+00:00', interval '10:20:30' hour_second)") + testFoldConst("select date_sub('2014-07-31 01:00:00-05:30', interval '10:20:30' hour_second)") + + // HOUR_SECOND extract + qt_hour_second_extract_1 """select extract(hour_second from dt) from test_add_sub_union_type order by dt""" + qt_hour_second_extract_2 """select extract(hour_second from '2023-01-02')""" + qt_hour_second_extract_3 """select extract(hour_second from '2023-01-02 03:04:05.123456')""" + qt_hour_second_extract_4 """select extract(hour_second from '2023-01-02 03:04:05.123456+08:00')""" + qt_hour_second_extract_5 """select extract(hour_second from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(hour_second from '2023-01-02')") + testFoldConst("select extract(hour_second from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(hour_second from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(hour_second from '2023-01-02 03:04:05.123456-05:30')") + + // HOUR_MICROSECOND add/sub + qt_hour_microsecond_add_1 """select date_add('2023-01-02 03:04:05.123456', interval '2:30:40.123456' hour_microsecond)""" + qt_hour_microsecond_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-0:00:00.000001' hour_microsecond)""" + qt_hour_microsecond_add_3 """select date_add(dt, interval iv_hour_microsecond hour_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_microsecond_add_4 """select date_add(dt, interval iv_hour_microsecond hour_microsecond) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_hour_microsecond_add_5 """select date_add('2023-01-02 03:04:05.123456', interval '1!2:3.000004' hour_microsecond)""" + qt_hour_microsecond_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1::2**3..4' hour_microsecond)""" + qt_hour_microsecond_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '5.6' hour_microsecond)""" + qt_hour_microsecond_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '100000:59:59.999999' hour_microsecond)""" + qt_hour_microsecond_add_9 """select date_add('2013-12-31', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_add_10 """select date_add('2013-11-30 01:00:00+08:00', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_add_11 """select date_add('2013-10-31 01:00:00+00:00', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_add_12 """select date_add('2013-09-30 01:00:00-05:30', interval '10:20:30.123456' hour_microsecond)""" + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1!2:3.000004' hour_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::2**3..4' hour_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '5.6' hour_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '100000:59:59.999999' hour_microsecond)") + testFoldConst("select date_add('2008-12-31 23:59:59.999999', interval '0:00:00.000005' hour_microsecond)") + testFoldConst("select date_add('2009-02-28 23:59:59.123456', interval '-00:00:00.000009' hour_microsecond)") + testFoldConst("select date_add('2012-08-31', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_add('2012-07-31 01:00:00+08:00', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_add('2012-06-30 01:00:00+00:00', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_add('2012-05-31 01:00:00-05:30', interval '10:20:30.123456' hour_microsecond)") + test { + sql """select date_add('2023-01-02 03:04:05.123456', interval '1:2:3:4.5' hour_microsecond)""" + exception "Operation hour_microsecond_add of" + } + + qt_hour_microsecond_sub_1 """select date_sub('2023-01-02 03:04:05.123456', interval '2:30:40.123456' hour_microsecond)""" + qt_hour_microsecond_sub_2 """select date_sub(dt, interval iv_hour_microsecond hour_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_hour_microsecond_sub_3 """select date_sub('2023-01-02 03:04:05.123456', interval '9#8:7.000006' hour_microsecond)""" + qt_hour_microsecond_sub_4 """select date_sub('2011-12-31', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_sub_5 """select date_sub('2011-11-30 01:00:00+08:00', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_sub_6 """select date_sub('2011-10-31 01:00:00+00:00', interval '10:20:30.123456' hour_microsecond)""" + qt_hour_microsecond_sub_7 """select date_sub('2011-09-30 01:00:00-05:30', interval '10:20:30.123456' hour_microsecond)""" + testFoldConst("select date_sub('2023-01-02 03:04:05.123456', interval '9#8:7.000006' hour_microsecond)") + testFoldConst("select date_sub('2007-12-31 23:59:59.999999', interval '0:00:00.000005' hour_microsecond)") + testFoldConst("select date_sub('2007-11-30 23:59:59.999999', interval '99:59:59.999999' hour_microsecond)") + testFoldConst("select date_sub('2010-08-31', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_sub('2010-07-31 01:00:00+08:00', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_sub('2010-06-30 01:00:00+00:00', interval '10:20:30.123456' hour_microsecond)") + testFoldConst("select date_sub('2010-05-31 01:00:00-05:30', interval '10:20:30.123456' hour_microsecond)") + + // HOUR_MICROSECOND extract + qt_hour_microsecond_extract_1 """select extract(hour_microsecond from dt) from test_add_sub_union_type order by dt""" + qt_hour_microsecond_extract_2 """select extract(hour_microsecond from '2023-01-02')""" + qt_hour_microsecond_extract_3 """select extract(hour_microsecond from '2023-01-02 03:04:05.123456')""" + qt_hour_microsecond_extract_4 """select extract(hour_microsecond from '2023-01-02 03:04:05.123456+08:00')""" + qt_hour_microsecond_extract_5 """select extract(hour_microsecond from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(hour_microsecond from '2023-01-02')") + testFoldConst("select extract(hour_microsecond from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(hour_microsecond from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(hour_microsecond from '2023-01-02 03:04:05.123456-05:30')") + + // MINUTE_SECOND add/sub + qt_minute_second_add_1 """select date_add('2023-01-02 03:04:05', interval '45:50' minute_second)""" + qt_minute_second_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-10:20' minute_second)""" + qt_minute_second_add_3 """select date_add(dt, interval iv_minute_second minute_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_minute_second_add_4 """select date_add(dt, interval iv_minute_second minute_second) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_minute_second_add_5 """select date_add('2023-01-02 03:04:05', interval '7&8' minute_second)""" + qt_minute_second_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '1::2' minute_second)""" + qt_minute_second_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '30' minute_second)""" + qt_minute_second_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '500000:59' minute_second)""" + qt_minute_second_add_10 """select date_add('2009-12-31', interval '10:20' minute_second)""" + qt_minute_second_add_11 """select date_add('2009-11-30 01:00:00+08:00', interval '10:20' minute_second)""" + qt_minute_second_add_12 """select date_add('2009-10-31 01:00:00+00:00', interval '10:20' minute_second)""" + qt_minute_second_add_13 """select date_add('2009-09-30 01:00:00-05:30', interval '10:20' minute_second)""" + testFoldConst("select date_add('2023-01-02 03:04:05', interval '7&8' minute_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::2' minute_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '30' minute_second)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '500000:59' minute_second)") + testFoldConst("select date_add('2008-11-30 23:59:50', interval '00:15' minute_second)") + testFoldConst("select date_add('2008-10-31 23:59:50', interval '-00:00' minute_second)") + testFoldConst("select date_add('2008-09-30', interval '10:20' minute_second)") + testFoldConst("select date_add('2008-08-31 01:00:00+08:00', interval '10:20' minute_second)") + testFoldConst("select date_add('2008-07-31 01:00:00+00:00', interval '10:20' minute_second)") + testFoldConst("select date_add('2008-06-30 01:00:00-05:30', interval '10:20' minute_second)") + test { + sql """select date_add('2023-01-02 03:04:05', interval '1:2:3' minute_second)""" + exception "Operation minute_second_add of" + } + + qt_minute_second_sub_1 """select date_sub('2023-01-02 03:04:05', interval '45:50' minute_second)""" + qt_minute_second_sub_2 """select date_sub(dt, interval iv_minute_second minute_second) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_minute_second_sub_3 """select date_sub('2023-01-02 03:04:05', interval '9@10' minute_second)""" + qt_minute_second_sub_4 """select date_sub('2007-12-31', interval '10:20' minute_second)""" + qt_minute_second_sub_5 """select date_sub('2007-11-30 01:00:00+08:00', interval '10:20' minute_second)""" + qt_minute_second_sub_6 """select date_sub('2007-10-31 01:00:00+00:00', interval '10:20' minute_second)""" + qt_minute_second_sub_7 """select date_sub('2007-09-30 01:00:00-05:30', interval '10:20' minute_second)""" + testFoldConst("select date_sub('2023-01-02 03:04:05', interval '9@10' minute_second)") + testFoldConst("select date_sub('2006-12-31 23:59:50', interval '00:15' minute_second)") + testFoldConst("select date_sub('2006-11-30 23:59:50', interval '99:59' minute_second)") + testFoldConst("select date_sub('2006-08-31', interval '10:20' minute_second)") + testFoldConst("select date_sub('2006-07-31 01:00:00+08:00', interval '10:20' minute_second)") + testFoldConst("select date_sub('2006-06-30 01:00:00+00:00', interval '10:20' minute_second)") + testFoldConst("select date_sub('2006-05-31 01:00:00-05:30', interval '10:20' minute_second)") + + // MINUTE_SECOND extract + qt_minute_second_extract_1 """select extract(minute_second from dt) from test_add_sub_union_type order by dt""" + qt_minute_second_extract_2 """select extract(minute_second from '2023-01-02')""" + qt_minute_second_extract_3 """select extract(minute_second from '2023-01-02 03:04:05.123456')""" + qt_minute_second_extract_4 """select extract(minute_second from '2023-01-02 03:04:05.123456+08:00')""" + qt_minute_second_extract_5 """select extract(minute_second from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(minute_second from '2023-01-02')") + testFoldConst("select extract(minute_second from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(minute_second from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(minute_second from '2023-01-02 03:04:05.123456-05:30')") + + // MINUTE_MICROSECOND add/sub + qt_minute_microsecond_add_1 """select date_add('2023-01-02 03:04:05.123456', interval '45:50.123456' minute_microsecond)""" + qt_minute_microsecond_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-10:20.000020' minute_microsecond)""" + qt_minute_microsecond_add_3 """select date_add(dt, interval iv_minute_microsecond minute_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_minute_microsecond_add_4 """select date_add(dt, interval iv_minute_microsecond minute_microsecond) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_minute_microsecond_add_5 """select date_add('2023-01-02 03:04:05.123456', interval '3:4,56' minute_microsecond)""" + qt_minute_microsecond_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '7&8.009' minute_microsecond)""" + qt_minute_microsecond_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '1::2..3' minute_microsecond)""" + qt_minute_microsecond_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '9.8' minute_microsecond)""" + qt_minute_microsecond_add_9 """select date_add('2023-01-02 03:04:05.123456', interval '700000:59.999999' minute_microsecond)""" + qt_minute_microsecond_add_10 """select date_add('2007-12-30', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_add_11 """select date_add('2007-11-30 01:00:00+08:00', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_add_12 """select date_add('2007-10-31 01:00:00+00:00', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_add_13 """select date_add('2007-09-30 01:00:00-05:30', interval '10:20.123456' minute_microsecond)""" + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '3:4,56' minute_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '7&8.009' minute_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1::2..3' minute_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '9.8' minute_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '700000:59.999999' minute_microsecond)") + testFoldConst("select date_add('2006-12-31 23:59:59.999999', interval '00:00.000005' minute_microsecond)") + testFoldConst("select date_add('2006-11-30 23:59:59.999999', interval '-00:00.000001' minute_microsecond)") + testFoldConst("select date_add('2006-09-30', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_add('2006-04-30 01:00:00+08:00', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_add('2006-03-31 01:00:00+00:00', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_add('2006-02-28 01:00:00-05:30', interval '10:20.123456' minute_microsecond)") + test { + sql """select date_add('2023-01-02 03:04:05.123456', interval '1:2:3.4' minute_microsecond)""" + exception "Operation minute_microsecond_add of" + } + + qt_minute_microsecond_sub_1 """select date_sub('2023-01-02 03:04:05.123456', interval '45:50.123456' minute_microsecond)""" + qt_minute_microsecond_sub_2 """select date_sub(dt, interval iv_minute_microsecond minute_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_minute_microsecond_sub_3 """select date_sub('2023-01-02 03:04:05.123456', interval '9@10.001' minute_microsecond)""" + qt_minute_microsecond_sub_4 """select date_sub('2005-12-31', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_sub_5 """select date_sub('2005-11-30 01:00:00+08:00', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_sub_6 """select date_sub('2005-10-31 01:00:00+00:00', interval '10:20.123456' minute_microsecond)""" + qt_minute_microsecond_sub_7 """select date_sub('2005-09-30 01:00:00-05:30', interval '10:20.123456' minute_microsecond)""" + testFoldConst("select date_sub('2023-01-02 03:04:05.123456', interval '9@10.001' minute_microsecond)") + testFoldConst("select date_sub('2005-08-31 23:59:59.999999', interval '00:00.000005' minute_microsecond)") + testFoldConst("select date_sub('2005-07-31 23:59:59.123456', interval '00:59.999999' minute_microsecond)") + testFoldConst("select date_sub('2005-06-30', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_sub('2005-04-30 01:00:00+08:00', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_sub('2005-03-31 01:00:00+00:00', interval '10:20.123456' minute_microsecond)") + testFoldConst("select date_sub('2005-02-28 01:00:00-05:30', interval '10:20.123456' minute_microsecond)") + + // MINUTE_MICROSECOND extract + qt_minute_microsecond_extract_1 """select extract(minute_microsecond from dt) from test_add_sub_union_type order by dt""" + qt_minute_microsecond_extract_2 """select extract(minute_microsecond from '2023-01-02')""" + qt_minute_microsecond_extract_3 """select extract(minute_microsecond from '2023-01-02 03:04:05.123456')""" + qt_minute_microsecond_extract_4 """select extract(minute_microsecond from '2023-01-02 03:04:05.123456+08:00')""" + qt_minute_microsecond_extract_5 """select extract(minute_microsecond from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(minute_microsecond from '2023-01-02')") + testFoldConst("select extract(minute_microsecond from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(minute_microsecond from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(minute_microsecond from '2023-01-02 03:04:05.123456-05:30')") + + // SECOND_MICROSECOND add/sub + qt_second_microsecond_add_1 """select date_add('2023-01-02 03:04:05.123456', interval '59.654321' second_microsecond)""" + qt_second_microsecond_add_2 """select date_add('2023-01-02 03:04:05.123456', interval '-5.000005' second_microsecond)""" + qt_second_microsecond_add_3 """select date_add(dt, interval iv_second_microsecond second_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_second_microsecond_add_4 """select date_add(dt, interval iv_second_microsecond second_microsecond) from test_add_sub_union_type where dt='2024-02-29 10:00:00.000000'""" + qt_second_microsecond_add_5 """select date_add('2023-01-02 03:04:05.123456', interval '1,2' second_microsecond)""" + qt_second_microsecond_add_6 """select date_add('2023-01-02 03:04:05.123456', interval '7!8' second_microsecond)""" + qt_second_microsecond_add_7 """select date_add('2023-01-02 03:04:05.123456', interval '1..2' second_microsecond)""" + qt_second_microsecond_add_8 """select date_add('2023-01-02 03:04:05.123456', interval '7' second_microsecond)""" + qt_second_microsecond_add_9 """select date_add('2023-01-02 03:04:05.123456', interval '100000000.999999' second_microsecond)""" + qt_second_microsecond_add_10 """select date_add('2004-12-31', interval '10.123456' second_microsecond)""" + qt_second_microsecond_add_11 """select date_add('2004-11-30 01:00:00+08:00', interval '10.123456' second_microsecond)""" + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1,2' second_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '7!8' second_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '1..2' second_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '7' second_microsecond)") + testFoldConst("select date_add('2023-01-02 03:04:05.123456', interval '100000000.999999' second_microsecond)") + testFoldConst("select date_add('2003-12-31 23:59:59.999999', interval '0.000010' second_microsecond)") + testFoldConst("select date_add('2003-11-30 23:59:59.999999', interval '-0.000001' second_microsecond)") + testFoldConst("select date_add('2003-10-31 01:00:00+08:00', interval '10.123456' second_microsecond)") + test { + sql """select date_add('2023-01-02 03:04:05.123456', interval '1:2.3' second_microsecond)""" + exception "Operation second_microsecond_add of" + } + + qt_second_microsecond_sub_1 """select date_sub('2023-01-02 03:04:05.123456', interval '59.654321' second_microsecond)""" + qt_second_microsecond_sub_2 """select date_sub(dt, interval iv_second_microsecond second_microsecond) from test_add_sub_union_type where dt='2023-01-02 03:04:05.123456'""" + qt_second_microsecond_sub_3 """select date_sub('2023-01-02 03:04:05.123456', interval '9@8' second_microsecond)""" + qt_second_microsecond_sub_4 """select date_sub('2002-12-31', interval '10.123456' second_microsecond)""" + qt_second_microsecond_sub_5 """select date_sub('2002-11-30 01:00:00+08:00', interval '10.123456' second_microsecond)""" + testFoldConst("select date_sub('2023-01-02 03:04:05.123456', interval '9@8' second_microsecond)") + testFoldConst("select date_sub('2002-12-30 23:59:59.999999', interval '0.000010' second_microsecond)") + testFoldConst("select date_sub('0001-01-01 00:00:00.000000', interval '0.000001' second_microsecond)") + testFoldConst("select date_sub('2002-10-31 01:00:00+08:00', interval '10.123456' second_microsecond)") + + // SECOND_MICROSECOND extract + qt_second_microsecond_extract_1 """select extract(second_microsecond from dt) from test_add_sub_union_type order by dt""" + qt_second_microsecond_extract_2 """select extract(second_microsecond from '2023-01-02')""" + qt_second_microsecond_extract_3 """select extract(second_microsecond from '2023-01-02 03:04:05.123456')""" + qt_second_microsecond_extract_4 """select extract(second_microsecond from '2023-01-02 03:04:05.123456+08:00')""" + qt_second_microsecond_extract_5 """select extract(second_microsecond from '2023-01-02 03:04:05.123456-05:30')""" + testFoldConst("select extract(second_microsecond from '2023-01-02')") + testFoldConst("select extract(second_microsecond from '2023-01-02 03:04:05.123456')") + testFoldConst("select extract(second_microsecond from '2023-01-02 03:04:05.123456+08:00')") + testFoldConst("select extract(second_microsecond from '2023-01-02 03:04:05.123456-05:30')") + +} diff --git a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy index 23c3d85e3b1492..fa99e4d50c86c8 100644 --- a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy +++ b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_date_function.groovy @@ -253,12 +253,6 @@ suite("test_date_function") { qt_sql """ select date_add(test_datetime, INTERVAL 2 SECOND) result from ${tableName}; """ qt_sql """ select date_add(test_datetime, INTERVAL '1 00:00:01' DAY_SECOND) result from ${tableName}; """ - test { - sql """ select date_add(test_datetime, INTERVAL '1 xx:00:01' DAY_SECOND) result from ${tableName}; """ - // check exception message contains - exception "Invalid hours format" - } - explain { sql """select * from ${tableName} where test_datetime >= date_add('2024-01-16',INTERVAL 1 day);""" contains "2024-01-17" diff --git a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy index cdff84f949b518..5c717feb7c14e9 100644 --- a/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy +++ b/regression-test/suites/query_p0/sql_functions/datetime_functions/test_dateadd_with_other_timeunit.groovy @@ -69,46 +69,15 @@ suite("test_dateadd_with_other_timeunit") { qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:-1:1" DAY_SECOND); """ qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -1:-1:-1" DAY_SECOND); """ - test { - sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1 43" DAY_SECOND); """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1xxx" DAY_SECOND); """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL "1 1:1:1.1234" DAY_SECOND); """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1 34" DAY_SECOND); """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1xx" DAY_SECOND); """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1' DAY_SECOND) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1 2' DAY_SECOND) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1 2:3' DAY_SECOND) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1 2:3:4.5678' DAY_SECOND) result from ${tableName}; """ - exception "Invalid seconds format" - - sql """ select date_add(test_datetime, INTERVAL 'xx 00:00:01' DAY_SECOND) result from ${tableName}; """ - exception "Invalid days format" - - sql """ select date_add(test_datetime, interval '1 xx:00:01' day_second) result from ${tableName}; """ - exception "Invalid hours format" - - sql """ select date_add(test_datetime, INTERVAL '1 00:xx:01' DAY_SECOND) result from ${tableName}; """ - exception "Invalid minutes format" - - sql """ select date_add(test_datetime, INTERVAL '1 00:00:xx' DAY_SECOND) result from ${tableName}; """ - exception "Invalid seconds format" - } + qt_add_day_second_1 """ select date_add("2025-10-29 10:10:10", INTERVAL "-1 -1:1:1xxx" DAY_SECOND); """ + qt_add_day_second_2 """ select date_add("2025-10-29", INTERVAL "-1 -1:1:1xx" DAY_SECOND); """ + qt_add_day_second_3 """ select date_add(test_datetime, INTERVAL '1' DAY_SECOND) result from ${tableName}; """ + qt_add_day_second_4 """ select date_add(test_datetime, INTERVAL '1 2' DAY_SECOND) result from ${tableName}; """ + qt_add_day_second_5 """ select date_add(test_datetime, INTERVAL '1 2:3' DAY_SECOND) result from ${tableName}; """ + qt_add_day_second_6 """ select date_add(test_datetime, INTERVAL 'xx 00:00:01' DAY_SECOND) result from ${tableName}; """ + qt_add_day_second_7 """ select date_add(test_datetime, interval '1 xx:00:01' day_second) result from ${tableName}; """ + qt_add_day_second_8 """ select date_add(test_datetime, INTERVAL '1 00:xx:01' DAY_SECOND) result from ${tableName}; """ + qt_add_day_second_9 """ select date_add(test_datetime, INTERVAL '1 00:00:xx' DAY_SECOND) result from ${tableName}; """ // DAY_HOUR testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1 1" DAY_HOUR); """ @@ -151,26 +120,12 @@ suite("test_dateadd_with_other_timeunit") { qt_sql """ select date_add("2025-10-29", INTERVAL "-1 10" DAY_HOUR); """ qt_sql """ select date_add("2025-10-29", INTERVAL "-1 -10" DAY_HOUR); """ - test { - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1' DAY_HOUR) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx 10' DAY_HOUR) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1 xx' DAY_HOUR) ; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1' DAY_HOUR) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL 'xx 10' DAY_HOUR) result from ${tableName}; """ - exception "Invalid days format" - - sql """ select date_add(test_datetime, INTERVAL '1 xx' DAY_HOUR) result from ${tableName}; """ - exception "Invalid hours format" - } - + qt_add_day_hour_1 """ select date_add("2025-10-29 10:10:10", INTERVAL '1' DAY_HOUR); """ + qt_add_day_hour_2 """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx 10' DAY_HOUR) ; """ + qt_add_day_hour_3 """ select date_add("2025-10-29 10:10:10", INTERVAL '1 xx' DAY_HOUR) ; """ + qt_add_day_hour_4 """ select date_add(test_datetime, INTERVAL '1' DAY_HOUR) result from ${tableName}; """ + qt_add_day_hour_5 """ select date_add(test_datetime, INTERVAL 'xx 10' DAY_HOUR) result from ${tableName}; """ + qt_add_day_hour_6 """ select date_add(test_datetime, INTERVAL '1 xx' DAY_HOUR) result from ${tableName}; """ // MINUTE_SECOND testFoldConst """ select date_add("2025-10-29 10:10:10", INTERVAL "1:1" MINUTE_SECOND); """ @@ -213,25 +168,12 @@ suite("test_dateadd_with_other_timeunit") { qt_sql """ select date_add("2025-10-29", INTERVAL "-1:10" MINUTE_SECOND); """ qt_sql """ select date_add("2025-10-29", INTERVAL "-1:-10" MINUTE_SECOND); """ - test { - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1' MINUTE_SECOND) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx:10' MINUTE_SECOND) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1:xx' MINUTE_SECOND) ; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1' MINUTE_SECOND) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL 'xx:10' MINUTE_SECOND) result from ${tableName}; """ - exception "Invalid minutes format" - - sql """ select date_add(test_datetime, INTERVAL '1:xx' MINUTE_SECOND) result from ${tableName}; """ - exception "Invalid seconds format" - } + qt_add_minute_second_1 """ select date_add("2025-10-29 10:10:10", INTERVAL '1' MINUTE_SECOND) ; """ + qt_add_minute_second_2 """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx:10' MINUTE_SECOND) ; """ + qt_add_minute_second_3 """ select date_add("2025-10-29 10:10:10", INTERVAL '1:xx' MINUTE_SECOND) ; """ + qt_add_minute_second_4 """ select date_add(test_datetime, INTERVAL '1' MINUTE_SECOND) result from ${tableName}; """ + qt_add_minute_second_5 """ select date_add(test_datetime, INTERVAL 'xx:10' MINUTE_SECOND) result from ${tableName}; """ + qt_add_minute_second_6 """ select date_add(test_datetime, INTERVAL '1:xx' MINUTE_SECOND) result from ${tableName}; """ // SECOND_MICROSECOND testFoldConst """ select date_add("2025-10-29 10:10:10.123456", INTERVAL "1.1" SECOND_MICROSECOND); """ @@ -274,24 +216,11 @@ suite("test_dateadd_with_other_timeunit") { qt_sql """ select date_add("2025-10-29", INTERVAL "-1.1234567" SECOND_MICROSECOND); """ qt_sql """ select date_add("2025-10-29", INTERVAL "-1.-1234567" SECOND_MICROSECOND); """ - test { - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1' SECOND_MICROSECOND) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx.10' SECOND_MICROSECOND) ; """ - exception "Invalid time format" - - sql """ select date_add("2025-10-29 10:10:10", INTERVAL '1.xx' SECOND_MICROSECOND) ; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL '1' SECOND_MICROSECOND) result from ${tableName}; """ - exception "Invalid time format" - - sql """ select date_add(test_datetime, INTERVAL 'xx.10' SECOND_MICROSECOND) result from ${tableName}; """ - exception "Invalid seconds format" - - sql """ select date_add(test_datetime, INTERVAL '1.xx' SECOND_MICROSECOND) result from ${tableName}; """ - exception "Invalid microseconds format" - } + qt_add_second_microsecond_1 """ select date_add("2025-10-29 10:10:10", INTERVAL '1' SECOND_MICROSECOND) ; """ + qt_add_second_microsecond_2 """ select date_add("2025-10-29 10:10:10", INTERVAL 'xx.10' SECOND_MICROSECOND) ; """ + qt_add_second_microsecond_3 """ select date_add("2025-10-29 10:10:10", INTERVAL '1.xx' SECOND_MICROSECOND) ; """ + qt_add_second_microsecond_4 """ select date_add(test_datetime, INTERVAL '1' SECOND_MICROSECOND) result from ${tableName}; """ + qt_add_second_microsecond_5 """ select date_add(test_datetime, INTERVAL 'xx.10' SECOND_MICROSECOND) result from ${tableName}; """ + qt_add_second_microsecond_6 """ select date_add(test_datetime, INTERVAL '1.xx' SECOND_MICROSECOND) result from ${tableName}; """ }