diff --git a/src/Functions/FunctionDateOrDateTimeAddInterval.h b/src/Functions/FunctionDateOrDateTimeAddInterval.h index 8f6b1370935..34e4795f24f 100644 --- a/src/Functions/FunctionDateOrDateTimeAddInterval.h +++ b/src/Functions/FunctionDateOrDateTimeAddInterval.h @@ -1,4 +1,6 @@ #pragma once +#include +#include #include #include @@ -280,7 +282,7 @@ struct Adder vec_to.resize(size); for (size_t i = 0; i < size; ++i) - vec_to[i] = transform.execute(vec_from[i], delta, time_zone); + vec_to[i] = transform.execute(vec_from[i], checkOverflow(delta), time_zone); } template @@ -310,12 +312,22 @@ struct Adder } private: + + template + static Int64 checkOverflow(Value val) + { + Int64 result; + if (accurate::convertNumeric(val, result)) + return result; + throw DB::Exception("Numeric overflow", ErrorCodes::DECIMAL_OVERFLOW); + } + template NO_INLINE NO_SANITIZE_UNDEFINED void vectorVector( const FromVectorType & vec_from, ToVectorType & vec_to, const DeltaColumnType & delta, const DateLUTImpl & time_zone, size_t size) const { for (size_t i = 0; i < size; ++i) - vec_to[i] = transform.execute(vec_from[i], delta.getData()[i], time_zone); + vec_to[i] = transform.execute(vec_from[i], checkOverflow(delta.getData()[i]), time_zone); } template @@ -323,7 +335,7 @@ private: const FromType & from, ToVectorType & vec_to, const DeltaColumnType & delta, const DateLUTImpl & time_zone, size_t size) const { for (size_t i = 0; i < size; ++i) - vec_to[i] = transform.execute(from, delta.getData()[i], time_zone); + vec_to[i] = transform.execute(from, checkOverflow(delta.getData()[i]), time_zone); } }; @@ -346,10 +358,9 @@ struct DateTimeAddIntervalImpl auto result_col = result_type->createColumn(); auto col_to = assert_cast(result_col.get()); + const IColumn & delta_column = *arguments[1].column; if (const auto * sources = checkAndGetColumn(source_col.get())) { - const IColumn & delta_column = *arguments[1].column; - if (const auto * delta_const_column = typeid_cast(&delta_column)) op.vectorConstant(sources->getData(), col_to->getData(), delta_const_column->getInt(0), time_zone); else @@ -360,13 +371,12 @@ struct DateTimeAddIntervalImpl op.constantVector( sources_const->template getValue(), col_to->getData(), - *arguments[1].column, time_zone); + delta_column, time_zone); } else { - throw Exception("Illegal column " + arguments[0].column->getName() - + " of first argument of function " + Transform::name, - ErrorCodes::ILLEGAL_COLUMN); + throw Exception(ErrorCodes::ILLEGAL_COLUMN, "Illegal column {} of first argument of function {}", + arguments[0].column->getName(), Transform::name); } return result_col; diff --git a/tests/queries/0_stateless/01662_date_ubsan.reference b/tests/queries/0_stateless/01662_date_ubsan.reference index 3c90ee8960e..b9bff160f6b 100644 --- a/tests/queries/0_stateless/01662_date_ubsan.reference +++ b/tests/queries/0_stateless/01662_date_ubsan.reference @@ -1,34 +1,5 @@ --- { echo } --- tests with INT64_MIN (via overflow) -SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -2021-01-01 00:00:00 -SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -2021-01-01 00:00:00 -SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -2021-01-01 00:00:00 -SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -2021-01-01 00:00:00 -SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -2021-01-01 00:00:00 --- tests with INT64_MAX -SELECT addMinutes(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); 2019-12-31 23:59:00 -SELECT addHours(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); 2019-12-31 23:00:00 -SELECT addWeeks(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); 2019-12-25 00:00:00 -SELECT addDays(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); 2019-12-31 00:00:00 -SELECT addYears(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); 2019-01-01 00:00:00 --- tests with inf -SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -2021-01-01 00:00:00 -SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -2021-01-01 00:00:00 -SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -2021-01-01 00:00:00 -SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -2021-01-01 00:00:00 -SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -2021-01-01 00:00:00 diff --git a/tests/queries/0_stateless/01662_date_ubsan.sql b/tests/queries/0_stateless/01662_date_ubsan.sql index 784853bef3d..fd197044fad 100644 --- a/tests/queries/0_stateless/01662_date_ubsan.sql +++ b/tests/queries/0_stateless/01662_date_ubsan.sql @@ -1,19 +1,18 @@ --- { echo } --- tests with INT64_MIN (via overflow) -SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- tests with INT64_MAX SELECT addMinutes(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); SELECT addHours(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); SELECT addWeeks(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); SELECT addDays(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); SELECT addYears(toDateTime('2020-01-01 00:00:00', 'GMT'), 9223372036854775807); +-- tests with INT64_MIN (via overflow) +SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- { serverError DECIMAL_OVERFLOW } +SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- { serverError DECIMAL_OVERFLOW } +SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- { serverError DECIMAL_OVERFLOW } +SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- { serverError DECIMAL_OVERFLOW } +SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), 9223372036854775808); -- { serverError DECIMAL_OVERFLOW } -- tests with inf -SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); +SELECT addMinutes(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -- { serverError DECIMAL_OVERFLOW } +SELECT addHours(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -- { serverError DECIMAL_OVERFLOW } +SELECT addWeeks(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -- { serverError DECIMAL_OVERFLOW } +SELECT addDays(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -- { serverError DECIMAL_OVERFLOW } +SELECT addYears(toDateTime('2021-01-01 00:00:00', 'GMT'), inf); -- { serverError DECIMAL_OVERFLOW }