From 61ad74bc58123bcfcae7881190e7cf322bd8126c Mon Sep 17 00:00:00 2001 From: Vasily Nemkov Date: Tue, 5 Nov 2019 14:59:46 +0300 Subject: [PATCH] Fixed parsing DateTime and/or DateTime64 with parseXXXOrNull --- dbms/src/DataTypes/DataTypeDate.h | 4 +++- dbms/src/DataTypes/DataTypeDateTime.h | 4 +++- dbms/src/DataTypes/DataTypeDateTime64.h | 4 ++-- dbms/src/DataTypes/DataTypesDecimal.h | 18 +++++++++--------- dbms/src/Functions/FunctionsConversion.h | 8 ++++++-- 5 files changed, 23 insertions(+), 15 deletions(-) diff --git a/dbms/src/DataTypes/DataTypeDate.h b/dbms/src/DataTypes/DataTypeDate.h index ee3d97ecbff..dcbdd516200 100644 --- a/dbms/src/DataTypes/DataTypeDate.h +++ b/dbms/src/DataTypes/DataTypeDate.h @@ -9,8 +9,10 @@ namespace DB class DataTypeDate final : public DataTypeNumberBase { public: + static constexpr auto family_name = "Date"; + TypeIndex getTypeId() const override { return TypeIndex::Date; } - const char * getFamilyName() const override { return "Date"; } + const char * getFamilyName() const override { return family_name; } void serializeText(const IColumn & column, size_t row_num, WriteBuffer & ostr, const FormatSettings &) const override; void deserializeWholeText(IColumn & column, ReadBuffer & istr, const FormatSettings &) const override; diff --git a/dbms/src/DataTypes/DataTypeDateTime.h b/dbms/src/DataTypes/DataTypeDateTime.h index 34e5acedc36..ec445016a5e 100644 --- a/dbms/src/DataTypes/DataTypeDateTime.h +++ b/dbms/src/DataTypes/DataTypeDateTime.h @@ -48,7 +48,9 @@ public: explicit DataTypeDateTime(const String & time_zone_name = ""); explicit DataTypeDateTime(const TimezoneMixin & time_zone); - const char * getFamilyName() const override { return "DateTime"; } + static constexpr auto family_name = "DateTime"; + + const char * getFamilyName() const override { return family_name; } String doGetName() const override; TypeIndex getTypeId() const override { return TypeIndex::DateTime; } diff --git a/dbms/src/DataTypes/DataTypeDateTime64.h b/dbms/src/DataTypes/DataTypeDateTime64.h index b9e7087fdb9..ece4a6eba77 100644 --- a/dbms/src/DataTypes/DataTypeDateTime64.h +++ b/dbms/src/DataTypes/DataTypeDateTime64.h @@ -17,14 +17,14 @@ class DataTypeDateTime64 final : public DataTypeDecimalBase, public { public: static constexpr UInt8 default_scale = 3; - static constexpr auto familyName = "DateTime64"; + static constexpr auto family_name = "DateTime64"; explicit DataTypeDateTime64(UInt32 scale_, const std::string & time_zone_name = ""); // reuse timezone from other DateTime/DateTime64 DataTypeDateTime64(UInt32 scale_, const TimezoneMixin & time_zone_info); - const char * getFamilyName() const override { return familyName; } + const char * getFamilyName() const override { return family_name; } std::string doGetName() const override; TypeIndex getTypeId() const override { return TypeIndex::DateTime64; } diff --git a/dbms/src/DataTypes/DataTypesDecimal.h b/dbms/src/DataTypes/DataTypesDecimal.h index fa11307d441..30b67652888 100644 --- a/dbms/src/DataTypes/DataTypesDecimal.h +++ b/dbms/src/DataTypes/DataTypesDecimal.h @@ -33,9 +33,9 @@ public: using typename Base::ColumnType; using Base::Base; - static constexpr auto familyName = "Decimal"; + static constexpr auto family_name = "Decimal"; - const char * getFamilyName() const override { return familyName; } + const char * getFamilyName() const override { return family_name; } std::string doGetName() const override; TypeIndex getTypeId() const override { return TypeId::value; } bool canBePromoted() const override { return true; } @@ -100,7 +100,7 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro { converted_value = DataTypeDecimal::getScaleMultiplier(scale_to - scale_from); if (common::mulOverflow(static_cast(value), converted_value, converted_value)) - throw Exception(std::string(ToDataType::familyName) + " convert overflow", + throw Exception(std::string(ToDataType::family_name) + " convert overflow", ErrorCodes::DECIMAL_OVERFLOW); } else @@ -110,7 +110,7 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro { if (converted_value < std::numeric_limits::min() || converted_value > std::numeric_limits::max()) - throw Exception(std::string(ToDataType::familyName) + " convert overflow", + throw Exception(std::string(ToDataType::family_name) + " convert overflow", ErrorCodes::DECIMAL_OVERFLOW); } @@ -136,7 +136,7 @@ convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale) { if (converted_value < std::numeric_limits::min() || converted_value > std::numeric_limits::max()) - throw Exception(std::string(FromDataType::familyName) + " convert overflow", + throw Exception(std::string(FromDataType::family_name) + " convert overflow", ErrorCodes::DECIMAL_OVERFLOW); } else @@ -145,7 +145,7 @@ convertFromDecimal(const typename FromDataType::FieldType & value, UInt32 scale) if (converted_value < 0 || converted_value > static_cast(std::numeric_limits::max())) - throw Exception(std::string(FromDataType::familyName) + " convert overflow", + throw Exception(std::string(FromDataType::family_name) + " convert overflow", ErrorCodes::DECIMAL_OVERFLOW); } } @@ -163,7 +163,7 @@ convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale) if constexpr (std::is_floating_point_v) { if (!std::isfinite(value)) - throw Exception(std::string(ToDataType::familyName) + " convert overflow. Cannot convert infinity or NaN to decimal", + throw Exception(std::string(ToDataType::family_name) + " convert overflow. Cannot convert infinity or NaN to decimal", ErrorCodes::DECIMAL_OVERFLOW); auto out = value * ToDataType::getScaleMultiplier(scale); @@ -172,13 +172,13 @@ convertToDecimal(const typename FromDataType::FieldType & value, UInt32 scale) 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(std::string(ToDataType::familyName) + " convert overflow. Float is out of Decimal range", + throw Exception(std::string(ToDataType::family_name) + " 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(std::string(ToDataType::familyName) + " convert overflow. Float is out of Decimal range", + throw Exception(std::string(ToDataType::family_name) + " convert overflow. Float is out of Decimal range", ErrorCodes::DECIMAL_OVERFLOW); } return out; diff --git a/dbms/src/Functions/FunctionsConversion.h b/dbms/src/Functions/FunctionsConversion.h index 8f7d18f8d4d..b9de494451b 100644 --- a/dbms/src/Functions/FunctionsConversion.h +++ b/dbms/src/Functions/FunctionsConversion.h @@ -555,12 +555,16 @@ struct ConvertThroughParsing /// For conversion to DateTime type, second argument with time zone could be specified. if constexpr (std::is_same_v || std::is_same_v) { + const auto result_type = removeNullable(block.getByPosition(result).type); // Time zone is already figured out during result type resultion, no need to do it here. - if (const auto dt_col = checkAndGetDataType(block.getByPosition(result).type.get())) + if (const auto dt_col = checkAndGetDataType(result_type.get())) local_time_zone = &dt_col->getTimeZone(); else { - throw Exception("Can't get timezone info from result type", ErrorCodes::ILLEGAL_COLUMN); + throw Exception("Can't get timezone info from result type, expected " + + std::string(ToDataType::family_name) + + " got " + block.getByPosition(result).type->getName(), + ErrorCodes::ILLEGAL_COLUMN); } if constexpr (parsing_mode == ConvertFromStringParsingMode::BestEffort)