Merge pull request #20131 from azat/DateTime64-fix

DateTime64 fixes
This commit is contained in:
alexey-milovidov 2021-02-07 16:55:28 +03:00 committed by GitHub
commit 3b43b0a1be
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 98 additions and 3 deletions

View File

@ -704,7 +704,11 @@ struct DateTimeTransformImpl
{ {
using Op = Transformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform>; using Op = Transformer<typename FromDataType::FieldType, typename ToDataType::FieldType, Transform>;
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, 1, 0); size_t time_zone_argument_position = 1;
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
time_zone_argument_position = 2;
const DateLUTImpl & time_zone = extractTimeZoneFromFunctionArguments(arguments, time_zone_argument_position, 0);
const ColumnPtr source_col = arguments[0].column; const ColumnPtr source_col = arguments[0].column;
if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get())) if (const auto * sources = checkAndGetColumn<typename FromDataType::ColumnType>(source_col.get()))

View File

@ -477,6 +477,61 @@ template <typename Name> struct ConvertImpl<DataTypeDate, DataTypeDateTime64, Na
template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag> template <typename Name> struct ConvertImpl<DataTypeDateTime, DataTypeDateTime64, Name, ConvertDefaultBehaviorTag>
: DateTimeTransformImpl<DataTypeDateTime, DataTypeDateTime64, ToDateTime64Transform> {}; : DateTimeTransformImpl<DataTypeDateTime, DataTypeDateTime64, ToDateTime64Transform> {};
/** Conversion of numeric to DateTime64
*/
template <typename FromType>
struct ToDateTime64TransformUnsigned
{
static constexpr auto name = "toDateTime64";
const DateTime64::NativeType scale_multiplier = 1;
ToDateTime64TransformUnsigned(UInt32 scale = 0)
: scale_multiplier(DecimalUtils::scaleMultiplier<DateTime64::NativeType>(scale))
{}
inline NO_SANITIZE_UNDEFINED DateTime64::NativeType execute(FromType from, const DateLUTImpl &) const
{
from = std::min(time_t(from), time_t(0xFFFFFFFF));
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(from, 0, scale_multiplier);
}
};
template <typename FromType>
struct ToDateTime64TransformSigned
{
static constexpr auto name = "toDateTime64";
const DateTime64::NativeType scale_multiplier = 1;
ToDateTime64TransformSigned(UInt32 scale = 0)
: scale_multiplier(DecimalUtils::scaleMultiplier<DateTime64::NativeType>(scale))
{}
inline NO_SANITIZE_UNDEFINED DateTime64::NativeType execute(FromType from, const DateLUTImpl &) const
{
if (from < 0)
return 0;
from = std::min(time_t(from), time_t(0xFFFFFFFF));
return DecimalUtils::decimalFromComponentsWithMultiplier<DateTime64>(from, 0, scale_multiplier);
}
};
template <typename Name> struct ConvertImpl<DataTypeInt8, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeInt8, DataTypeDateTime64, ToDateTime64TransformSigned<Int8>> {};
template <typename Name> struct ConvertImpl<DataTypeInt16, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeInt16, DataTypeDateTime64, ToDateTime64TransformSigned<Int16>> {};
template <typename Name> struct ConvertImpl<DataTypeInt32, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeInt32, DataTypeDateTime64, ToDateTime64TransformSigned<Int32>> {};
template <typename Name> struct ConvertImpl<DataTypeInt64, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeInt64, DataTypeDateTime64, ToDateTime64TransformSigned<Int64>> {};
template <typename Name> struct ConvertImpl<DataTypeUInt64, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeUInt64, DataTypeDateTime64, ToDateTime64TransformUnsigned<UInt64>> {};
template <typename Name> struct ConvertImpl<DataTypeFloat32, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeFloat32, DataTypeDateTime64, ToDateTime64TransformSigned<Float32>> {};
template <typename Name> struct ConvertImpl<DataTypeFloat64, DataTypeDateTime64, Name>
: DateTimeTransformImpl<DataTypeFloat64, DataTypeDateTime64, ToDateTime64TransformSigned<Float64>> {};
/** Conversion of DateTime64 to Date or DateTime: discards fractional part. /** Conversion of DateTime64 to Date or DateTime: discards fractional part.
*/ */
template <typename Transform> template <typename Transform>
@ -1294,7 +1349,12 @@ public:
bool useDefaultImplementationForNulls() const override { return checked_return_type; } bool useDefaultImplementationForNulls() const override { return checked_return_type; }
bool useDefaultImplementationForConstants() const override { return true; } bool useDefaultImplementationForConstants() const override { return true; }
ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {1}; } ColumnNumbers getArgumentsThatAreAlwaysConstant() const override
{
if constexpr (std::is_same_v<ToDataType, DataTypeDateTime64>)
return {2};
return {1};
}
bool canBeExecutedOnDefaultArguments() const override { return false; } bool canBeExecutedOnDefaultArguments() const override { return false; }
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type, size_t input_rows_count) const override
@ -2313,7 +2373,7 @@ private:
using LeftDataType = typename Types::LeftType; using LeftDataType = typename Types::LeftType;
using RightDataType = typename Types::RightType; using RightDataType = typename Types::RightType;
if constexpr (IsDataTypeDecimalOrNumber<LeftDataType> && IsDataTypeDecimalOrNumber<RightDataType>) if constexpr (IsDataTypeDecimalOrNumber<LeftDataType> && IsDataTypeDecimalOrNumber<RightDataType> && !std::is_same_v<DataTypeDateTime64, RightDataType>)
{ {
if (wrapper_cast_type == CastType::accurate) if (wrapper_cast_type == CastType::accurate)
{ {

View File

@ -0,0 +1,11 @@
-- { echo }
SELECT toDateTime(-2, 2);
1970-01-01 03:00:00.00
SELECT toDateTime64(-2, 2);
1970-01-01 03:00:00.00
SELECT CAST(-1 AS DateTime64);
1970-01-01 03:00:00.000
SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64);
2020-01-01 00:00:00.300
SELECT toDateTime64(bitShiftLeft(toUInt64(1),33), 2);
2106-02-07 09:28:15.00

View File

@ -0,0 +1,6 @@
-- { echo }
SELECT toDateTime(-2, 2);
SELECT toDateTime64(-2, 2);
SELECT CAST(-1 AS DateTime64);
SELECT CAST('2020-01-01 00:00:00.3' AS DateTime64);
SELECT toDateTime64(bitShiftLeft(toUInt64(1),33), 2);

View File

@ -0,0 +1,9 @@
-- { echo }
select toDateTime64(toDateTime(1), 2);
1970-01-01 03:00:01.00
select toDateTime64(toDate(1), 2);
1970-01-02 00:00:00.00
select toDateTime64(toDateTime(1), 2, 'GMT');
1970-01-01 00:00:01.00
select toDateTime64(toDate(1), 2, 'GMT');
1970-01-02 00:00:00.00

View File

@ -0,0 +1,5 @@
-- { echo }
select toDateTime64(toDateTime(1), 2);
select toDateTime64(toDate(1), 2);
select toDateTime64(toDateTime(1), 2, 'GMT');
select toDateTime64(toDate(1), 2, 'GMT');