mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-25 17:12:03 +00:00
Initial implementation of DateTime64 parsing functions;
This commit is contained in:
parent
b6b080745b
commit
8648ebf75c
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -108,5 +108,7 @@ public:
|
||||
bool equals(const IDataType & rhs) const override;
|
||||
};
|
||||
|
||||
template <> inline constexpr bool IsDataTypeDecimal<DataTypeDateTime64> = true;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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 T, typename U, template <typename> typename DecimalType>
|
||||
typename std::enable_if_t<(sizeof(T) >= sizeof(U)), DecimalType<T>>
|
||||
decimalResultType(const DecimalType<T> & tx, const DecimalType<U> & ty, bool is_multiply, bool is_divide)
|
||||
@ -209,128 +208,10 @@ const DecimalType<U> decimalResultType(const DataTypeNumber<T> &, const DecimalT
|
||||
}
|
||||
|
||||
|
||||
////// TODO (vnemkov): make that work for DecimalBase-derived types
|
||||
//template <typename T, template <typename> typename DecimalType>
|
||||
//inline const DecimalType<T> * checkDecimal(const IDataType & data_type)
|
||||
//{
|
||||
// return typeid_cast<const DecimalType<T> *>(&data_type);
|
||||
//}
|
||||
|
||||
//inline UInt32 getDecimalScale(const IDataType & data_type, UInt32 default_value = std::numeric_limits<UInt32>::max())
|
||||
//{
|
||||
// if (auto * decimal_type = checkDecimal<Decimal32>(data_type))
|
||||
// return decimal_type->getScale();
|
||||
// if (auto * decimal_type = checkDecimal<Decimal64>(data_type))
|
||||
// return decimal_type->getScale();
|
||||
// if (auto * decimal_type = checkDecimal<Decimal128>(data_type))
|
||||
// return decimal_type->getScale();
|
||||
// return default_value;
|
||||
//}
|
||||
|
||||
///
|
||||
|
||||
template <typename DataType> constexpr bool IsDataTypeDecimal = false;
|
||||
template <typename DataType> constexpr bool IsDataTypeDecimalOrNumber = IsDataTypeDecimal<DataType> || IsDataTypeNumber<DataType>;
|
||||
|
||||
//template <typename FromDataType, typename ToDataType>
|
||||
//inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsDataTypeDecimal<ToDataType>, 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<MaxFieldType>::getScaleMultiplier(scale_to - scale_from);
|
||||
// if (common::mulOverflow(static_cast<MaxNativeType>(value), converted_value, converted_value))
|
||||
// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
// }
|
||||
// else
|
||||
// converted_value = value / DataTypeDecimal<MaxFieldType>::getScaleMultiplier(scale_from - scale_to);
|
||||
|
||||
// if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType))
|
||||
// {
|
||||
// if (converted_value < std::numeric_limits<typename ToFieldType::NativeType>::min() ||
|
||||
// converted_value > std::numeric_limits<typename ToFieldType::NativeType>::max())
|
||||
// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
// }
|
||||
|
||||
// return converted_value;
|
||||
//}
|
||||
|
||||
//template <typename FromDataType, typename ToDataType>
|
||||
//inline std::enable_if_t<IsDataTypeDecimal<FromDataType> && IsDataTypeNumber<ToDataType>, 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<ToFieldType>)
|
||||
// return static_cast<ToFieldType>(value) / FromDataType::getScaleMultiplier(scale);
|
||||
// else
|
||||
// {
|
||||
// FromFieldType converted_value = convertDecimals<FromDataType, FromDataType>(value, scale, 0);
|
||||
|
||||
// if constexpr (sizeof(FromFieldType) > sizeof(ToFieldType) || !std::numeric_limits<ToFieldType>::is_signed)
|
||||
// {
|
||||
// if constexpr (std::numeric_limits<ToFieldType>::is_signed)
|
||||
// {
|
||||
// if (converted_value < std::numeric_limits<ToFieldType>::min() ||
|
||||
// converted_value > std::numeric_limits<ToFieldType>::max())
|
||||
// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// using CastIntType = std::conditional_t<std::is_same_v<ToFieldType, UInt64>, Int128, Int64>;
|
||||
|
||||
// if (converted_value < 0 ||
|
||||
// converted_value > static_cast<CastIntType>(std::numeric_limits<ToFieldType>::max()))
|
||||
// throw Exception("Decimal convert overflow", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
// }
|
||||
// }
|
||||
// return converted_value;
|
||||
// }
|
||||
//}
|
||||
|
||||
//template <typename FromDataType, typename ToDataType>
|
||||
//inline std::enable_if_t<IsDataTypeNumber<FromDataType> && IsDataTypeDecimal<ToDataType>, 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<FromFieldType>)
|
||||
// {
|
||||
// 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<ToNativeType, Int128>)
|
||||
// {
|
||||
// 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("Decimal 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("Decimal convert overflow. Float is out of Decimal range", ErrorCodes::DECIMAL_OVERFLOW);
|
||||
// }
|
||||
// return out;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// if constexpr (std::is_same_v<FromFieldType, UInt64>)
|
||||
// if (value > static_cast<UInt64>(std::numeric_limits<Int64>::max()))
|
||||
// return convertDecimals<DataTypeDecimal<Decimal128>, ToDataType>(value, 0, scale);
|
||||
// return convertDecimals<DataTypeDecimal<Decimal64>, ToDataType>(value, 0, scale);
|
||||
// }
|
||||
//}
|
||||
|
||||
template <template <typename> typename DecimalType>
|
||||
DataTypePtr createDecimal(UInt64 precision_value, UInt64 scale_value)
|
||||
{
|
||||
@ -352,5 +233,4 @@ extern template class DataTypeDecimalBase<Decimal64>;
|
||||
extern template class DataTypeDecimalBase<Decimal128>;
|
||||
extern template class DataTypeDecimalBase<DateTime64>;
|
||||
|
||||
|
||||
}
|
||||
|
@ -616,7 +616,7 @@ public:
|
||||
if (!readTempString())
|
||||
return false;
|
||||
ReadBufferFromString buf(temp_string);
|
||||
readDateTimeText(date_time, scale, buf);
|
||||
readDateTime64Text(date_time, scale, buf);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,7 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
|
||||
factory.registerFunction<FunctionToDate>();
|
||||
factory.registerFunction<FunctionToDateTime>();
|
||||
factory.registerFunction<FunctionToDateTime64>();
|
||||
factory.registerFunction<FunctionToUUID>();
|
||||
factory.registerFunction<FunctionToString>();
|
||||
factory.registerFunction<FunctionToFixedString>();
|
||||
@ -65,6 +66,7 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionToFloat64OrZero>();
|
||||
factory.registerFunction<FunctionToDateOrZero>();
|
||||
factory.registerFunction<FunctionToDateTimeOrZero>();
|
||||
factory.registerFunction<FunctionToDateTime64OrZero>();
|
||||
|
||||
factory.registerFunction<FunctionToDecimal32OrZero>();
|
||||
factory.registerFunction<FunctionToDecimal64OrZero>();
|
||||
@ -82,6 +84,7 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionToFloat64OrNull>();
|
||||
factory.registerFunction<FunctionToDateOrNull>();
|
||||
factory.registerFunction<FunctionToDateTimeOrNull>();
|
||||
factory.registerFunction<FunctionToDateTime64OrNull>();
|
||||
|
||||
factory.registerFunction<FunctionToDecimal32OrNull>();
|
||||
factory.registerFunction<FunctionToDecimal64OrNull>();
|
||||
@ -90,6 +93,9 @@ void registerFunctionsConversion(FunctionFactory & factory)
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffort>();
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffortOrZero>();
|
||||
factory.registerFunction<FunctionParseDateTimeBestEffortOrNull>();
|
||||
factory.registerFunction<FunctionParseDateTime64BestEffort>();
|
||||
factory.registerFunction<FunctionParseDateTime64BestEffortOrZero>();
|
||||
factory.registerFunction<FunctionParseDateTime64BestEffortOrNull>();
|
||||
|
||||
factory.registerFunction<FunctionConvert<DataTypeInterval, NameToIntervalSecond, PositiveMonotonicity>>();
|
||||
factory.registerFunction<FunctionConvert<DataTypeInterval, NameToIntervalMinute, PositiveMonotonicity>>();
|
||||
|
@ -498,7 +498,7 @@ struct ConvertThroughParsing
|
||||
const DateLUTImpl * utc_time_zone [[maybe_unused]] = nullptr;
|
||||
|
||||
/// For conversion to DateTime type, second argument with time zone could be specified.
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime>)
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime> || std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
local_time_zone = &extractTimeZoneFromFunctionArguments(block, arguments, 1, 0);
|
||||
|
||||
@ -523,10 +523,17 @@ struct ConvertThroughParsing
|
||||
size_t size = input_rows_count;
|
||||
typename ColVecTo::MutablePtr col_to = nullptr;
|
||||
|
||||
if constexpr (IsDataTypeDecimal<ToDataType>)
|
||||
if constexpr (IsDataTypeDecimal<ToDataType> || std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
UInt32 scale = additions;
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
ToDataType check_bounds_in_ctor(scale, local_time_zone ? local_time_zone->getTimeZone() : String{});
|
||||
}
|
||||
else
|
||||
{
|
||||
ToDataType check_bounds_in_ctor(ToDataType::maxPrecision(), scale);
|
||||
}
|
||||
col_to = ColVecTo::create(size, scale);
|
||||
}
|
||||
else
|
||||
@ -570,13 +577,26 @@ struct ConvertThroughParsing
|
||||
{
|
||||
if constexpr (parsing_mode == ConvertFromStringParsingMode::BestEffort)
|
||||
{
|
||||
time_t res;
|
||||
parseDateTimeBestEffort(res, read_buffer, *local_time_zone, *utc_time_zone);
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
DateTime64 res;
|
||||
parseDateTime64BestEffort(res, vec_to.getScale(), read_buffer, *local_time_zone, *utc_time_zone);
|
||||
vec_to[i] = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (IsDataTypeDecimal<ToDataType>)
|
||||
time_t res;
|
||||
parseDateTimeBestEffort(res, read_buffer, *local_time_zone, *utc_time_zone);
|
||||
vec_to[i] = res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
readDateTimeText(vec_to[i], vec_to.getScale(), read_buffer, local_time_zone);
|
||||
}
|
||||
else if constexpr (IsDataTypeDecimal<ToDataType>)
|
||||
ToDataType::readText(vec_to[i], read_buffer, ToDataType::maxPrecision(), vec_to.getScale());
|
||||
else
|
||||
parseImpl<ToDataType>(vec_to[i], read_buffer, local_time_zone);
|
||||
@ -591,13 +611,28 @@ struct ConvertThroughParsing
|
||||
|
||||
if constexpr (parsing_mode == ConvertFromStringParsingMode::BestEffort)
|
||||
{
|
||||
time_t res;
|
||||
parsed = tryParseDateTimeBestEffort(res, read_buffer, *local_time_zone, *utc_time_zone);
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
DateTime64 res;
|
||||
parsed = tryParseDateTime64BestEffort(res, vec_to.getScale(), read_buffer, *local_time_zone, *utc_time_zone);
|
||||
vec_to[i] = res;
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (IsDataTypeDecimal<ToDataType>)
|
||||
time_t res;
|
||||
parsed = tryParseDateTimeBestEffort(res, read_buffer, *local_time_zone, *utc_time_zone);
|
||||
vec_to[i] = res;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
|
||||
{
|
||||
DateTime64 value;
|
||||
parsed = tryReadDateTime64Text(value, vec_to.getScale(), read_buffer, *local_time_zone);
|
||||
vec_to[i] = value;
|
||||
}
|
||||
else if constexpr (IsDataTypeDecimal<ToDataType>)
|
||||
parsed = ToDataType::tryReadText(vec_to[i], read_buffer, ToDataType::maxPrecision(), vec_to.getScale());
|
||||
else
|
||||
parsed = tryParseImpl<ToDataType>(vec_to[i], read_buffer, local_time_zone);
|
||||
@ -746,6 +781,7 @@ struct ConvertImpl<DataTypeFixedString, DataTypeString, Name>
|
||||
/// Declared early because used below.
|
||||
struct NameToDate { static constexpr auto name = "toDate"; };
|
||||
struct NameToDateTime { static constexpr auto name = "toDateTime"; };
|
||||
struct NameToDateTime64 { static constexpr auto name = "toDateTime64"; };
|
||||
struct NameToString { static constexpr auto name = "toString"; };
|
||||
struct NameToDecimal32 { static constexpr auto name = "toDecimal32"; };
|
||||
struct NameToDecimal64 { static constexpr auto name = "toDecimal64"; };
|
||||
@ -936,9 +972,18 @@ private:
|
||||
|
||||
if constexpr (IsDataTypeDecimal<RightDataType>)
|
||||
{
|
||||
if (arguments.size() != 2)
|
||||
if constexpr (std::is_same_v<RightDataType, DataTypeDateTime64>)
|
||||
{
|
||||
// account for optional timezone argument
|
||||
if (arguments.size() != 2 && arguments.size() != 3)
|
||||
throw Exception{"Function " + getName() + " expects 2 or 3 arguments for DataTypeDateTime64.",
|
||||
ErrorCodes::TOO_FEW_ARGUMENTS_FOR_FUNCTION};
|
||||
}
|
||||
else if (arguments.size() != 2)
|
||||
{
|
||||
throw Exception{"Function " + getName() + " expects 2 arguments for Decimal.",
|
||||
ErrorCodes::TOO_FEW_ARGUMENTS_FOR_FUNCTION};
|
||||
}
|
||||
|
||||
const ColumnWithTypeAndName & scale_column = block.getByPosition(arguments[1]);
|
||||
UInt32 scale = extractToDecimalScale(scale_column);
|
||||
@ -985,7 +1030,8 @@ public:
|
||||
static constexpr bool to_decimal =
|
||||
std::is_same_v<ToDataType, DataTypeDecimal<Decimal32>> ||
|
||||
std::is_same_v<ToDataType, DataTypeDecimal<Decimal64>> ||
|
||||
std::is_same_v<ToDataType, DataTypeDecimal<Decimal128>>;
|
||||
std::is_same_v<ToDataType, DataTypeDecimal<Decimal128>> ||
|
||||
std::is_same_v<ToDataType, DataTypeDateTime64>;
|
||||
|
||||
static FunctionPtr create(const Context &) { return std::make_shared<FunctionConvertFromString>(); }
|
||||
|
||||
@ -1409,8 +1455,7 @@ using FunctionToFloat32 = FunctionConvert<DataTypeFloat32, NameToFloat32, ToNumb
|
||||
using FunctionToFloat64 = FunctionConvert<DataTypeFloat64, NameToFloat64, ToNumberMonotonicity<Float64>>;
|
||||
using FunctionToDate = FunctionConvert<DataTypeDate, NameToDate, ToNumberMonotonicity<UInt16>>;
|
||||
using FunctionToDateTime = FunctionConvert<DataTypeDateTime, NameToDateTime, ToNumberMonotonicity<UInt32>>;
|
||||
// TODO (vnemkov): enable and test toDateTime64 function
|
||||
//using FunctionToDateTime64 = FunctionConvert<DataTypeDateTime, NameToDateTime, UnknownMonotonicity>;
|
||||
using FunctionToDateTime64 = FunctionConvert<DataTypeDateTime, NameToDateTime64, UnknownMonotonicity>;
|
||||
using FunctionToUUID = FunctionConvert<DataTypeUUID, NameToUUID, ToNumberMonotonicity<UInt128>>;
|
||||
using FunctionToString = FunctionConvert<DataTypeString, NameToString, ToStringMonotonicity>;
|
||||
using FunctionToUnixTimestamp = FunctionConvert<DataTypeUInt32, NameToUnixTimestamp, ToNumberMonotonicity<UInt32>>;
|
||||
@ -1433,6 +1478,7 @@ template <> struct FunctionTo<DataTypeFloat32> { using Type = FunctionToFloat32;
|
||||
template <> struct FunctionTo<DataTypeFloat64> { using Type = FunctionToFloat64; };
|
||||
template <> struct FunctionTo<DataTypeDate> { using Type = FunctionToDate; };
|
||||
template <> struct FunctionTo<DataTypeDateTime> { using Type = FunctionToDateTime; };
|
||||
template <> struct FunctionTo<DataTypeDateTime64> { using Type = FunctionToDateTime64; };
|
||||
template <> struct FunctionTo<DataTypeUUID> { using Type = FunctionToUUID; };
|
||||
template <> struct FunctionTo<DataTypeString> { using Type = FunctionToString; };
|
||||
template <> struct FunctionTo<DataTypeFixedString> { using Type = FunctionToFixedString; };
|
||||
@ -1457,6 +1503,7 @@ struct NameToFloat32OrZero { static constexpr auto name = "toFloat32OrZero"; };
|
||||
struct NameToFloat64OrZero { static constexpr auto name = "toFloat64OrZero"; };
|
||||
struct NameToDateOrZero { static constexpr auto name = "toDateOrZero"; };
|
||||
struct NameToDateTimeOrZero { static constexpr auto name = "toDateTimeOrZero"; };
|
||||
struct NameToDateTime64OrZero { static constexpr auto name = "toDateTime64OrZero"; };
|
||||
struct NameToDecimal32OrZero { static constexpr auto name = "toDecimal32OrZero"; };
|
||||
struct NameToDecimal64OrZero { static constexpr auto name = "toDecimal64OrZero"; };
|
||||
struct NameToDecimal128OrZero { static constexpr auto name = "toDecimal128OrZero"; };
|
||||
@ -1473,6 +1520,7 @@ using FunctionToFloat32OrZero = FunctionConvertFromString<DataTypeFloat32, NameT
|
||||
using FunctionToFloat64OrZero = FunctionConvertFromString<DataTypeFloat64, NameToFloat64OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDateOrZero = FunctionConvertFromString<DataTypeDate, NameToDateOrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDateTimeOrZero = FunctionConvertFromString<DataTypeDateTime, NameToDateTimeOrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDateTime64OrZero = FunctionConvertFromString<DataTypeDateTime64, NameToDateTime64OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDecimal32OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal32>, NameToDecimal32OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDecimal64OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal64>, NameToDecimal64OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
using FunctionToDecimal128OrZero = FunctionConvertFromString<DataTypeDecimal<Decimal128>, NameToDecimal128OrZero, ConvertFromStringExceptionMode::Zero>;
|
||||
@ -1489,6 +1537,7 @@ struct NameToFloat32OrNull { static constexpr auto name = "toFloat32OrNull"; };
|
||||
struct NameToFloat64OrNull { static constexpr auto name = "toFloat64OrNull"; };
|
||||
struct NameToDateOrNull { static constexpr auto name = "toDateOrNull"; };
|
||||
struct NameToDateTimeOrNull { static constexpr auto name = "toDateTimeOrNull"; };
|
||||
struct NameToDateTime64OrNull { static constexpr auto name = "toDateTime64OrNull"; };
|
||||
struct NameToDecimal32OrNull { static constexpr auto name = "toDecimal32OrNull"; };
|
||||
struct NameToDecimal64OrNull { static constexpr auto name = "toDecimal64OrNull"; };
|
||||
struct NameToDecimal128OrNull { static constexpr auto name = "toDecimal128OrNull"; };
|
||||
@ -1505,6 +1554,7 @@ using FunctionToFloat32OrNull = FunctionConvertFromString<DataTypeFloat32, NameT
|
||||
using FunctionToFloat64OrNull = FunctionConvertFromString<DataTypeFloat64, NameToFloat64OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDateOrNull = FunctionConvertFromString<DataTypeDate, NameToDateOrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDateTimeOrNull = FunctionConvertFromString<DataTypeDateTime, NameToDateTimeOrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDateTime64OrNull = FunctionConvertFromString<DataTypeDateTime64, NameToDateTime64OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDecimal32OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal32>, NameToDecimal32OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDecimal64OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal64>, NameToDecimal64OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
using FunctionToDecimal128OrNull = FunctionConvertFromString<DataTypeDecimal<Decimal128>, NameToDecimal128OrNull, ConvertFromStringExceptionMode::Null>;
|
||||
@ -1512,6 +1562,10 @@ using FunctionToDecimal128OrNull = FunctionConvertFromString<DataTypeDecimal<Dec
|
||||
struct NameParseDateTimeBestEffort { static constexpr auto name = "parseDateTimeBestEffort"; };
|
||||
struct NameParseDateTimeBestEffortOrZero { static constexpr auto name = "parseDateTimeBestEffortOrZero"; };
|
||||
struct NameParseDateTimeBestEffortOrNull { static constexpr auto name = "parseDateTimeBestEffortOrNull"; };
|
||||
struct NameParseDateTime64BestEffort { static constexpr auto name = "parseDateTime64BestEffort"; };
|
||||
struct NameParseDateTime64BestEffortOrZero { static constexpr auto name = "parseDateTime64BestEffortOrZero"; };
|
||||
struct NameParseDateTime64BestEffortOrNull { static constexpr auto name = "parseDateTime64BestEffortOrNull"; };
|
||||
|
||||
|
||||
using FunctionParseDateTimeBestEffort = FunctionConvertFromString<
|
||||
DataTypeDateTime, NameParseDateTimeBestEffort, ConvertFromStringExceptionMode::Throw, ConvertFromStringParsingMode::BestEffort>;
|
||||
@ -1520,6 +1574,12 @@ using FunctionParseDateTimeBestEffortOrZero = FunctionConvertFromString<
|
||||
using FunctionParseDateTimeBestEffortOrNull = FunctionConvertFromString<
|
||||
DataTypeDateTime, NameParseDateTimeBestEffortOrNull, ConvertFromStringExceptionMode::Null, ConvertFromStringParsingMode::BestEffort>;
|
||||
|
||||
using FunctionParseDateTime64BestEffort = FunctionConvertFromString<
|
||||
DataTypeDateTime64, NameParseDateTime64BestEffort, ConvertFromStringExceptionMode::Throw, ConvertFromStringParsingMode::BestEffort>;
|
||||
using FunctionParseDateTime64BestEffortOrZero = FunctionConvertFromString<
|
||||
DataTypeDateTime64, NameParseDateTime64BestEffortOrZero, ConvertFromStringExceptionMode::Zero, ConvertFromStringParsingMode::BestEffort>;
|
||||
using FunctionParseDateTime64BestEffortOrNull = FunctionConvertFromString<
|
||||
DataTypeDateTime64, NameParseDateTime64BestEffortOrNull, ConvertFromStringExceptionMode::Null, ConvertFromStringParsingMode::BestEffort>;
|
||||
|
||||
class PreparedFunctionCast : public PreparedFunctionImpl
|
||||
{
|
||||
|
@ -630,12 +630,8 @@ inline ReturnType readDateTimeTextImpl(time_t & datetime, ReadBuffer & buf, cons
|
||||
return readDateTimeTextFallback<ReturnType>(datetime, buf, date_lut);
|
||||
}
|
||||
|
||||
inline void readDateTimeText(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
{
|
||||
readDateTimeTextImpl<void>(datetime, buf, date_lut);
|
||||
}
|
||||
|
||||
inline void readDateTimeText(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
template <typename ReturnType>
|
||||
inline ReturnType readDateTimeTextImpl(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut)
|
||||
{
|
||||
DB::DecimalComponents<DateTime64::NativeType> c;
|
||||
readDateTimeTextImpl<void>(c.whole, buf, date_lut);
|
||||
@ -645,7 +641,7 @@ inline void readDateTimeText(DateTime64 & datetime64, UInt32 scale, ReadBuffer &
|
||||
{
|
||||
if (separator != '.')
|
||||
{
|
||||
throw Exception("Cannot parse DateTime64 from text.", ErrorCodes::CANNOT_PARSE_DATETIME);
|
||||
return ReturnType(false);
|
||||
}
|
||||
}
|
||||
|
||||
@ -655,6 +651,18 @@ inline void readDateTimeText(DateTime64 & datetime64, UInt32 scale, ReadBuffer &
|
||||
|
||||
c.fractional *= common::exp10_i64(scale - fractional_length);
|
||||
datetime64 = decimalFromComponents<DateTime64>(c, scale);
|
||||
|
||||
return ReturnType(false);
|
||||
}
|
||||
|
||||
inline void readDateTimeText(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
{
|
||||
readDateTimeTextImpl<void>(datetime, buf, date_lut);
|
||||
}
|
||||
|
||||
inline void readDateTime64Text(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
{
|
||||
readDateTimeTextImpl<void>(datetime64, scale, buf, date_lut);
|
||||
}
|
||||
|
||||
inline bool tryReadDateTimeText(time_t & datetime, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
@ -662,6 +670,11 @@ inline bool tryReadDateTimeText(time_t & datetime, ReadBuffer & buf, const DateL
|
||||
return readDateTimeTextImpl<bool>(datetime, buf, date_lut);
|
||||
}
|
||||
|
||||
inline bool tryReadDateTime64Text(DateTime64 & datetime64, UInt32 scale, ReadBuffer & buf, const DateLUTImpl & date_lut = DateLUT::instance())
|
||||
{
|
||||
return readDateTimeTextImpl<bool>(datetime64, scale, buf, date_lut);
|
||||
}
|
||||
|
||||
inline void readDateTimeText(LocalDateTime & datetime, ReadBuffer & buf)
|
||||
{
|
||||
char s[19];
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <IO/WriteHelpers.h>
|
||||
#include <IO/parseDateTimeBestEffort.h>
|
||||
|
||||
#include <limits>
|
||||
|
||||
namespace DB
|
||||
{
|
||||
@ -66,7 +67,7 @@ inline void readDecimalNumber(T & res, const char * src)
|
||||
|
||||
|
||||
template <typename ReturnType>
|
||||
ReturnType parseDateTimeBestEffortImpl(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone)
|
||||
ReturnType parseDateTimeBestEffortImpl(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone, Int64 * fractional = nullptr)
|
||||
{
|
||||
auto on_error = [](const std::string & message [[maybe_unused]], int code [[maybe_unused]])
|
||||
{
|
||||
@ -360,7 +361,12 @@ ReturnType parseDateTimeBestEffortImpl(time_t & res, ReadBuffer & in, const Date
|
||||
++in.position();
|
||||
|
||||
/// Just ignore fractional part of second.
|
||||
readDigits(digits, sizeof(digits), in);
|
||||
num_digits = readDigits(digits, sizeof(digits), in);
|
||||
if (fractional)
|
||||
{
|
||||
using FractionalType = typename std::decay<decltype(*fractional)>::type;
|
||||
readDecimalNumber<std::numeric_limits<FractionalType>::digits10>(*fractional, digits);
|
||||
}
|
||||
}
|
||||
else if (c == '+' || c == '-')
|
||||
{
|
||||
@ -535,4 +541,24 @@ bool tryParseDateTimeBestEffort(time_t & res, ReadBuffer & in, const DateLUTImpl
|
||||
return parseDateTimeBestEffortImpl<bool>(res, in, local_time_zone, utc_time_zone);
|
||||
}
|
||||
|
||||
void parseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone)
|
||||
{
|
||||
DateTime64::NativeType whole;
|
||||
DateTime64::NativeType fractional;
|
||||
parseDateTimeBestEffortImpl<void>(whole, in, local_time_zone, utc_time_zone, &fractional);
|
||||
|
||||
res = decimalFromComponents<DateTime64>(whole, fractional, scale);
|
||||
}
|
||||
|
||||
bool tryParseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone)
|
||||
{
|
||||
DateTime64::NativeType whole;
|
||||
DateTime64::NativeType fractional;
|
||||
const auto result = parseDateTimeBestEffortImpl<bool>(whole, in, local_time_zone, utc_time_zone, &fractional);
|
||||
|
||||
res = decimalFromComponents<DateTime64>(whole, fractional, scale);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <Core/Types.h>
|
||||
|
||||
class DateLUTImpl;
|
||||
|
||||
namespace DB
|
||||
@ -55,5 +57,7 @@ class ReadBuffer;
|
||||
|
||||
void parseDateTimeBestEffort(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
|
||||
bool tryParseDateTimeBestEffort(time_t & res, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
|
||||
void parseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
|
||||
bool tryParseDateTime64BestEffort(DateTime64 & res, UInt32 scale, ReadBuffer & in, const DateLUTImpl & local_time_zone, const DateLUTImpl & utc_time_zone);
|
||||
|
||||
}
|
||||
|
@ -151,7 +151,7 @@ DateTime64::NativeType stringToDateTime64(const String & s, UInt32 scale)
|
||||
ReadBufferFromString in(s);
|
||||
DateTime64 datetime64 {0};
|
||||
|
||||
readDateTimeText(datetime64, scale, in);
|
||||
readDateTime64Text(datetime64, scale, in);
|
||||
if (!in.eof())
|
||||
throw Exception("String is too long for DateTime64: " + s, ErrorCodes::TOO_LARGE_STRING_SIZE);
|
||||
|
||||
|
@ -30,7 +30,6 @@ toStartOfMinute({datetime})
|
||||
toStartOfFiveMinute({datetime})
|
||||
toStartOfTenMinutes({datetime})
|
||||
toStartOfFifteenMinutes({datetime})
|
||||
# Do not work with DateTime64
|
||||
toStartOfInterval({datetime}, INTERVAL 1 year)
|
||||
toStartOfInterval({datetime}, INTERVAL 1 month)
|
||||
toStartOfInterval({datetime}, INTERVAL 1 day)
|
||||
@ -52,7 +51,6 @@ timeSlot({datetime})
|
||||
toYYYYMM({datetime})
|
||||
toYYYYMMDD({datetime})
|
||||
toYYYYMMDDhhmmss({datetime})
|
||||
# -- Illegal type DateTime64 of argument of function addYears
|
||||
addYears({datetime}, 1)
|
||||
addMonths({datetime}, 1)
|
||||
addWeeks({datetime}, 1)
|
||||
@ -61,7 +59,6 @@ addHours({datetime}, 1)
|
||||
addMinutes({datetime}, 1)
|
||||
addSeconds({datetime}, 1)
|
||||
addQuarters({datetime}, 1)
|
||||
# -- Illegal type DateTime64 of argument of function subtractYears.
|
||||
subtractYears({datetime}, 1)
|
||||
subtractMonths({datetime}, 1)
|
||||
subtractWeeks({datetime}, 1)
|
||||
|
Loading…
Reference in New Issue
Block a user