diff --git a/dbms/src/DataTypes/DataTypeDateTime64.cpp b/dbms/src/DataTypes/DataTypeDateTime64.cpp index 4a79da72214..d790dd60ce4 100644 --- a/dbms/src/DataTypes/DataTypeDateTime64.cpp +++ b/dbms/src/DataTypes/DataTypeDateTime64.cpp @@ -24,7 +24,7 @@ namespace DB { DataTypeDateTime64::DataTypeDateTime64(UInt32 scale_, const std::string & time_zone_name) - : DataTypeDecimalBase(DecimalUtils::maxPrecision() - scale_, scale_), + : DataTypeDecimalBase(DecimalUtils::maxPrecision(), scale_), TimezoneMixin(time_zone_name) { } diff --git a/dbms/src/DataTypes/getLeastSupertype.cpp b/dbms/src/DataTypes/getLeastSupertype.cpp index 9291426ea48..d45c9872394 100644 --- a/dbms/src/DataTypes/getLeastSupertype.cpp +++ b/dbms/src/DataTypes/getLeastSupertype.cpp @@ -230,20 +230,28 @@ DataTypePtr getLeastSupertype(const DataTypes & types) // big enough to hold max whole-value of any type from `types`. // That would sacrifice scale when comparing DateTime64 of different scales. - UInt32 max_datetime64_precision = 0; + UInt32 max_datetime64_whole_precision = 0; for (const auto & t : types) { if (auto dt64 = typeid_cast(t.get())) { - const auto precision = dt64->getPrecision(); - max_datetime64_precision = std::max(precision, max_datetime64_precision); + const auto whole_precision = dt64->getPrecision() - dt64->getScale(); + max_datetime64_whole_precision = std::max(whole_precision, max_datetime64_whole_precision); } } - const UInt32 least_decimal_precision = have_datetime ? leastDecimalPrecisionFor(TypeIndex::UInt32) : have_date ? leastDecimalPrecisionFor(TypeIndex::UInt16) : 0; - max_datetime64_precision = std::max(least_decimal_precision, max_datetime64_precision); + UInt32 least_decimal_precision = 0; + if (have_datetime) + { + least_decimal_precision = leastDecimalPrecisionFor(TypeIndex::UInt32); + } + else if (have_date) + { + least_decimal_precision = leastDecimalPrecisionFor(TypeIndex::UInt16); + } + max_datetime64_whole_precision = std::max(least_decimal_precision, max_datetime64_whole_precision); - const UInt32 scale = DataTypeDateTime64::maxPrecision() - max_datetime64_precision; + const UInt32 scale = DataTypeDateTime64::maxPrecision() - max_datetime64_whole_precision; return std::make_shared(scale); } } diff --git a/dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h b/dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h index 8586e4952d8..08894481db5 100644 --- a/dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h +++ b/dbms/src/Functions/FunctionDateOrDateTimeAddInterval.h @@ -228,14 +228,14 @@ struct SubtractIntervalImpl : public Transform } }; -struct SubtractSecondsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractSeconds"; }; -struct SubtractMinutesImpl : SubtractIntervalImpl { static constexpr auto name = "subtractMinutes"; }; -struct SubtractHoursImpl : SubtractIntervalImpl { static constexpr auto name = "subtractHours"; }; -struct SubtractDaysImpl : SubtractIntervalImpl { static constexpr auto name = "subtractDays"; }; -struct SubtractWeeksImpl : SubtractIntervalImpl { static constexpr auto name = "subtractWeeks"; }; -struct SubtractMonthsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractMonths"; }; +struct SubtractSecondsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractSeconds"; }; +struct SubtractMinutesImpl : SubtractIntervalImpl { static constexpr auto name = "subtractMinutes"; }; +struct SubtractHoursImpl : SubtractIntervalImpl { static constexpr auto name = "subtractHours"; }; +struct SubtractDaysImpl : SubtractIntervalImpl { static constexpr auto name = "subtractDays"; }; +struct SubtractWeeksImpl : SubtractIntervalImpl { static constexpr auto name = "subtractWeeks"; }; +struct SubtractMonthsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractMonths"; }; struct SubtractQuartersImpl : SubtractIntervalImpl { static constexpr auto name = "subtractQuarters"; }; -struct SubtractYearsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractYears"; }; +struct SubtractYearsImpl : SubtractIntervalImpl { static constexpr auto name = "subtractYears"; }; template @@ -387,8 +387,6 @@ public: return resolveReturnType(arguments); default: { - // TODO (vnemkov): quick and dirty way to check, remove before merging. - assert(false); throw Exception("Invalid type of 1st argument of function " + getName() + ": " + arguments[0].type->getName() + ", expected: Date, DateTime or DateTime64.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); diff --git a/dbms/src/Functions/FunctionHelpers.h b/dbms/src/Functions/FunctionHelpers.h index 933b3c83ff3..5f0488228f3 100644 --- a/dbms/src/Functions/FunctionHelpers.h +++ b/dbms/src/Functions/FunctionHelpers.h @@ -90,6 +90,7 @@ void validateArgumentType(const IFunction & func, const DataTypes & arguments, size_t argument_index, bool (* validator_func)(const IDataType &), const char * expected_type_description); +// Simple validator that is used in conjunction with validateFunctionArgumentTypes() to check if function arguments are as expected. struct FunctionArgumentTypeValidator { bool (* validator_func)(const IDataType &); @@ -99,8 +100,20 @@ struct FunctionArgumentTypeValidator using FunctionArgumentTypeValidators = std::vector; /** Validate that function arguments match specification. - * first, check that mandatory args present and have valid type. - * second, check optional arguents types, skipping ones that are missing. + * + * Designed to simplify argument validation + * for functions with variable arguments (e.g. depending on result type or other trait). + * first, checks that mandatory args present and have valid type. + * second, checks optional arguents types, skipping ones that are missing. + * + * Please note that if you have several optional arguments, like f([a, b, c]), + * only these calls are considered valid: + * f(a) + * f(a, b) + * f(a, b, c) + * + * But NOT these: f(a, c), f(b, c) + * In other words you can't skip * * If any mandatory arg is missing, throw an exception, with explicit description of expected arguments. */ diff --git a/dbms/src/Functions/FunctionsCoding.h b/dbms/src/Functions/FunctionsCoding.h index e85c641bccb..78c0dd84fa6 100644 --- a/dbms/src/Functions/FunctionsCoding.h +++ b/dbms/src/Functions/FunctionsCoding.h @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include diff --git a/dbms/src/Functions/FunctionsConversion.h b/dbms/src/Functions/FunctionsConversion.h index d1d0b33edfa..1d780749a73 100644 --- a/dbms/src/Functions/FunctionsConversion.h +++ b/dbms/src/Functions/FunctionsConversion.h @@ -1158,7 +1158,9 @@ public: } else if constexpr (std::is_same_v) { - UInt64 scale = extractToDecimalScale(arguments[1]); + UInt64 scale = DataTypeDateTime64::default_scale; + if (arguments.size() > 0) + scale = extractToDecimalScale(arguments[1]); const auto timezone = extractTimeZoneNameFromFunctionArguments(arguments, 2, 0); res = std::make_shared(scale, timezone); } diff --git a/dbms/src/Functions/FunctionsExternalDictionaries.h b/dbms/src/Functions/FunctionsExternalDictionaries.h index 2ea2c387c3d..a47dacf5deb 100644 --- a/dbms/src/Functions/FunctionsExternalDictionaries.h +++ b/dbms/src/Functions/FunctionsExternalDictionaries.h @@ -6,7 +6,6 @@ #include #include #include -#include #include #include diff --git a/dbms/src/Functions/FunctionsHashing.h b/dbms/src/Functions/FunctionsHashing.h index 33474334198..a0d6807b3e5 100644 --- a/dbms/src/Functions/FunctionsHashing.h +++ b/dbms/src/Functions/FunctionsHashing.h @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include