Fixed parsing DateTime and/or DateTime64 with parseXXXOrNull

This commit is contained in:
Vasily Nemkov 2019-11-05 14:59:46 +03:00
parent 9d3c819897
commit 61ad74bc58
5 changed files with 23 additions and 15 deletions

View File

@ -9,8 +9,10 @@ namespace DB
class DataTypeDate final : public DataTypeNumberBase<UInt16>
{
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;

View File

@ -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; }

View File

@ -17,14 +17,14 @@ class DataTypeDateTime64 final : public DataTypeDecimalBase<DateTime64>, 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; }

View File

@ -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<T>::value; }
bool canBePromoted() const override { return true; }
@ -100,7 +100,7 @@ convertDecimals(const typename FromDataType::FieldType & value, UInt32 scale_fro
{
converted_value = DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_to - scale_from);
if (common::mulOverflow(static_cast<MaxNativeType>(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<typename ToFieldType::NativeType>::min() ||
converted_value > std::numeric_limits<typename ToFieldType::NativeType>::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<ToFieldType>::min() ||
converted_value > std::numeric_limits<ToFieldType>::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<CastIntType>(std::numeric_limits<ToFieldType>::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<FromFieldType>)
{
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<ToNativeType>(min_int128) || out >= static_cast<ToNativeType>(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<ToNativeType>::min() || out >= std::numeric_limits<ToNativeType>::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;

View File

@ -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<ToDataType, DataTypeDateTime> || std::is_same_v<ToDataType, DataTypeDateTime64>)
{
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<ToDataType>(block.getByPosition(result).type.get()))
if (const auto dt_col = checkAndGetDataType<ToDataType>(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)