From 8648ebf75c5b4ce8bd41e4e7e657c081414c0728 Mon Sep 17 00:00:00 2001 From: Vasily Nemkov Date: Sat, 12 Oct 2019 10:03:38 +0300 Subject: [PATCH] Initial implementation of DateTime64 parsing functions; --- dbms/src/DataTypes/DataTypeDateTime.cpp | 7 +- dbms/src/DataTypes/DataTypeDateTime.h | 2 + dbms/src/DataTypes/DataTypeDecimalBase.h | 120 ------------------ dbms/src/Formats/ProtobufReader.cpp | 2 +- dbms/src/Functions/FunctionsConversion.cpp | 6 + dbms/src/Functions/FunctionsConversion.h | 90 ++++++++++--- dbms/src/IO/ReadHelpers.h | 27 +++- dbms/src/IO/parseDateTimeBestEffort.cpp | 30 ++++- dbms/src/IO/parseDateTimeBestEffort.h | 4 + dbms/src/Interpreters/convertFieldToType.cpp | 2 +- .../00921_datetime64_compatibility.python | 3 - 11 files changed, 141 insertions(+), 152 deletions(-) diff --git a/dbms/src/DataTypes/DataTypeDateTime.cpp b/dbms/src/DataTypes/DataTypeDateTime.cpp index be7f85c2bf5..985a044340a 100644 --- a/dbms/src/DataTypes/DataTypeDateTime.cpp +++ b/dbms/src/DataTypes/DataTypeDateTime.cpp @@ -35,14 +35,15 @@ static inline void readText(time_t & x, ReadBuffer & istr, const FormatSettings } } -static inline void readText(DateTime64 & x, UInt32 scale, ReadBuffer & istr, const FormatSettings & settings, const DateLUTImpl & time_zone, const DateLUTImpl & /*utc_time_zone*/) +static inline void readText(DateTime64 & x, UInt32 scale, ReadBuffer & istr, const FormatSettings & settings, const DateLUTImpl & time_zone, const DateLUTImpl & utc_time_zone) { switch (settings.date_time_input_format) { case FormatSettings::DateTimeInputFormat::Basic: - readDateTimeText(x, scale, istr, time_zone); + readDateTime64Text(x, scale, istr, time_zone); return; - default: + case FormatSettings::DateTimeInputFormat::BestEffort: + parseDateTime64BestEffort(x, scale, istr, time_zone, utc_time_zone); return; } } diff --git a/dbms/src/DataTypes/DataTypeDateTime.h b/dbms/src/DataTypes/DataTypeDateTime.h index a978bf6962d..0ec045ae1c0 100644 --- a/dbms/src/DataTypes/DataTypeDateTime.h +++ b/dbms/src/DataTypes/DataTypeDateTime.h @@ -108,5 +108,7 @@ public: bool equals(const IDataType & rhs) const override; }; +template <> inline constexpr bool IsDataTypeDecimal = true; + } diff --git a/dbms/src/DataTypes/DataTypeDecimalBase.h b/dbms/src/DataTypes/DataTypeDecimalBase.h index 5d23cebc502..0b8ff37c480 100644 --- a/dbms/src/DataTypes/DataTypeDecimalBase.h +++ b/dbms/src/DataTypes/DataTypeDecimalBase.h @@ -171,7 +171,6 @@ protected: }; -// TODO (vnemkov): enable only if both tx and ty are derived from DecimalBase and are essentially same type with different type-params. template typename DecimalType> typename std::enable_if_t<(sizeof(T) >= sizeof(U)), DecimalType> decimalResultType(const DecimalType & tx, const DecimalType & ty, bool is_multiply, bool is_divide) @@ -209,128 +208,10 @@ const DecimalType decimalResultType(const DataTypeNumber &, const DecimalT } -////// TODO (vnemkov): make that work for DecimalBase-derived types -//template typename DecimalType> -//inline const DecimalType * checkDecimal(const IDataType & data_type) -//{ -// return typeid_cast *>(&data_type); -//} - -//inline UInt32 getDecimalScale(const IDataType & data_type, UInt32 default_value = std::numeric_limits::max()) -//{ -// if (auto * decimal_type = checkDecimal(data_type)) -// return decimal_type->getScale(); -// if (auto * decimal_type = checkDecimal(data_type)) -// return decimal_type->getScale(); -// if (auto * decimal_type = checkDecimal(data_type)) -// return decimal_type->getScale(); -// return default_value; -//} - /// - template constexpr bool IsDataTypeDecimal = false; template constexpr bool IsDataTypeDecimalOrNumber = IsDataTypeDecimal || IsDataTypeNumber; -//template -//inline std::enable_if_t && IsDataTypeDecimal, typename ToDataType::FieldType> -//convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_from, UInt32 scale_to) -//{ -// using FromFieldType = typename FromDataType::FieldType; -// using ToFieldType = typename ToDataType::FieldType; -// using MaxFieldType = std::conditional_t<(sizeof(FromFieldType) > sizeof(ToFieldType)), FromFieldType, ToFieldType>; -// using MaxNativeType = typename MaxFieldType::NativeType; - -// MaxNativeType converted_value; -// if (scale_to > scale_from) -// { -// converted_value = DataTypeDecimal::getScaleMultiplier(scale_to - scale_from); -// if (common::mulOverflow(static_cast(value), converted_value, converted_value)) -// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW); -// } -// else -// converted_value = value / DataTypeDecimal::getScaleMultiplier(scale_from - scale_to); - -// if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType)) -// { -// if (converted_value < std::numeric_limits::min() || -// converted_value > std::numeric_limits::max()) -// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW); -// } - -// return converted_value; -//} - -//template -//inline std::enable_if_t && IsDataTypeNumber, typename ToDataType::FieldType> -//convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale) -//{ -// using FromFieldType = typename FromDataType::FieldType; -// using ToFieldType = typename ToDataType::FieldType; - -// if constexpr (std::is_floating_point_v) -// return static_cast(value) / FromDataType::getScaleMultiplier(scale); -// else -// { -// FromFieldType converted_value = convertDecimals(value, scale, 0); - -// if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType) || !std::numeric_limits::is_signed) -// { -// if constexpr (std::numeric_limits::is_signed) -// { -// if (converted_value < std::numeric_limits::min() || -// converted_value > std::numeric_limits::max()) -// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW); -// } -// else -// { -// using CastIntType = std::conditional_t, Int128, Int64>; - -// if (converted_value < 0 || -// converted_value > static_cast(std::numeric_limits::max())) -// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW); -// } -// } -// return converted_value; -// } -//} - -//template -//inline std::enable_if_t && IsDataTypeDecimal, typename ToDataType::FieldType> -//convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale) -//{ -// using FromFieldType = typename FromDataType::FieldType; -// using ToNativeType = typename ToDataType::FieldType::NativeType; - -// if constexpr (std::is_floating_point_v) -// { -// if (!std::isfinite(value)) -// throw Exception("Decimal convert overflow. Cannot convert infinity or NaN to decimal", ErrorCodes::DECIMAL_OVERFLOW); - -// auto out = value * ToDataType::getScaleMultiplier(scale); -// if constexpr (std::is_same_v) -// { -// static constexpr __int128 min_int128 = __int128(0x8000000000000000ll) << 64; -// static constexpr __int128 max_int128 = (__int128(0x7fffffffffffffffll) << 64) + 0xffffffffffffffffll; -// if (out <= static_cast(min_int128) || out >= static_cast(max_int128)) -// throw Exception("Decimal convert overflow. Float is out of Decimal range", ErrorCodes::DECIMAL_OVERFLOW); -// } -// else -// { -// if (out <= std::numeric_limits::min() || out >= std::numeric_limits::max()) -// throw Exception("Decimal convert overflow. Float is out of Decimal range", ErrorCodes::DECIMAL_OVERFLOW); -// } -// return out; -// } -// else -// { -// if constexpr (std::is_same_v) -// if (value > static_cast(std::numeric_limits::max())) -// return convertDecimals, ToDataType>(value, 0, scale); -// return convertDecimals, ToDataType>(value, 0, scale); -// } -//} - template