diff --git a/src/Functions/FunctionDateOrDateTimeAddInterval.h b/src/Functions/FunctionDateOrDateTimeAddInterval.h index 2259cc71f07..3002e330f0c 100644 --- a/src/Functions/FunctionDateOrDateTimeAddInterval.h +++ b/src/Functions/FunctionDateOrDateTimeAddInterval.h @@ -685,37 +685,27 @@ public: } else if constexpr (std::is_same_v) { - if (typeid_cast(arguments[0].type.get())) + static constexpr auto target_scale = std::invoke( + []() -> std::optional + { + if constexpr (std::is_base_of_v) + return 9; + else if constexpr (std::is_base_of_v) + return 6; + else if constexpr (std::is_base_of_v) + return 3; + + return {}; + }); + + auto timezone = extractTimeZoneNameFromFunctionArguments(arguments, 2, 0); + if (const auto* datetime64_type = typeid_cast(arguments[0].type.get())) { - const auto & datetime64_type = assert_cast(*arguments[0].type); - - auto from_scale = datetime64_type.getScale(); - auto scale = from_scale; - - if (std::is_same_v) - scale = 9; - else if (std::is_same_v) - scale = 6; - else if (std::is_same_v) - scale = 3; - - scale = std::max(scale, from_scale); - - return std::make_shared(scale, extractTimeZoneNameFromFunctionArguments(arguments, 2, 0)); + const auto from_scale = datetime64_type->getScale(); + return std::make_shared(std::max(from_scale, target_scale.value_or(from_scale)), std::move(timezone)); } - else - { - auto scale = DataTypeDateTime64::default_scale; - if (std::is_same_v) - scale = 9; - else if (std::is_same_v) - scale = 6; - else if (std::is_same_v) - scale = 3; - - return std::make_shared(scale, extractTimeZoneNameFromFunctionArguments(arguments, 2, 0)); - } + return std::make_shared(target_scale.value_or(DataTypeDateTime64::default_scale), std::move(timezone)); } throw Exception(ErrorCodes::LOGICAL_ERROR, "Unexpected result type in datetime add interval function"); diff --git a/tests/queries/0_stateless/02207_subseconds_intervals.reference b/tests/queries/0_stateless/02207_subseconds_intervals.reference index f2e40137851..91f0ecb8606 100644 --- a/tests/queries/0_stateless/02207_subseconds_intervals.reference +++ b/tests/queries/0_stateless/02207_subseconds_intervals.reference @@ -60,3 +60,19 @@ test add[...]seconds() 2220-12-12 12:12:12.124 2220-12-12 12:12:12.121 2220-12-12 12:12:12.124456 +test subtract[...]seconds() +- test nanoseconds +2022-12-31 23:59:59.999999999 +2022-12-31 23:59:59.999999900 +2023-01-01 00:00:00.000000001 +2023-01-01 00:00:00.000000100 +- test microseconds +2022-12-31 23:59:59.999999 +2022-12-31 23:59:59.999900 +2023-01-01 00:00:00.000001 +2023-01-01 00:00:00.000100 +- test milliseconds +2022-12-31 23:59:59.999 +2022-12-31 23:59:59.900 +2023-01-01 00:00:00.001 +2023-01-01 00:00:00.100 diff --git a/tests/queries/0_stateless/02207_subseconds_intervals.sql b/tests/queries/0_stateless/02207_subseconds_intervals.sql index a7ce03d9330..c30b3c460dc 100644 --- a/tests/queries/0_stateless/02207_subseconds_intervals.sql +++ b/tests/queries/0_stateless/02207_subseconds_intervals.sql @@ -92,3 +92,22 @@ select addMilliseconds(toDateTime64('1930-12-12 12:12:12.123456', 6), 1); -- Bel select addMilliseconds(toDateTime64('2220-12-12 12:12:12.123', 3), 1); -- Above normal range, source scale matches result select addMilliseconds(toDateTime64('2220-12-12 12:12:12.12', 2), 1); -- Above normal range, source scale less than result select addMilliseconds(toDateTime64('2220-12-12 12:12:12.123456', 6), 1); -- Above normal range, source scale greater than result + +select 'test subtract[...]seconds()'; +select '- test nanoseconds'; +select subtractNanoseconds(toDateTime64('2023-01-01 00:00:00.0000000', 7, 'UTC'), 1); +select subtractNanoseconds(toDateTime64('2023-01-01 00:00:00.0000000', 7, 'UTC'), 100); +select subtractNanoseconds(toDateTime64('2023-01-01 00:00:00.0000000', 7, 'UTC'), -1); +select subtractNanoseconds(toDateTime64('2023-01-01 00:00:00.0000000', 7, 'UTC'), -100); + +select '- test microseconds'; +select subtractMicroseconds(toDateTime64('2023-01-01 00:00:00.0000', 4, 'UTC'), 1); +select subtractMicroseconds(toDateTime64('2023-01-01 00:00:00.0000', 4, 'UTC'), 100); +select subtractMicroseconds(toDateTime64('2023-01-01 00:00:00.0000', 4, 'UTC'), -1); +select subtractMicroseconds(toDateTime64('2023-01-01 00:00:00.0000', 4, 'UTC'), -100); + +select '- test milliseconds'; +select subtractMilliseconds(toDateTime64('2023-01-01 00:00:00.0', 1, 'UTC'), 1); +select subtractMilliseconds(toDateTime64('2023-01-01 00:00:00.0', 1, 'UTC'), 100); +select subtractMilliseconds(toDateTime64('2023-01-01 00:00:00.0', 1, 'UTC'), -1); +select subtractMilliseconds(toDateTime64('2023-01-01 00:00:00.0', 1, 'UTC'), -100);