mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-09-20 08:40:50 +00:00
Fix issue #42966
This commit is contained in:
parent
2346f30095
commit
f94c33586c
@ -1987,7 +1987,7 @@ Extracts time from [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) as
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
snowflakeToDateTime(value [, time_zone])
|
||||
snowflakeToDateTime(value[, time_zone])
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@ -2023,7 +2023,7 @@ Extracts time from [Snowflake ID](https://en.wikipedia.org/wiki/Snowflake_ID) as
|
||||
**Syntax**
|
||||
|
||||
``` sql
|
||||
snowflakeToDateTime64(value [, time_zone])
|
||||
snowflakeToDateTime64(value[, time_zone])
|
||||
```
|
||||
|
||||
**Parameters**
|
||||
@ -2033,7 +2033,7 @@ snowflakeToDateTime64(value [, time_zone])
|
||||
|
||||
**Returned value**
|
||||
|
||||
- Input value converted to the [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) data type.
|
||||
- Input value converted to the [DateTime64](/docs/en/sql-reference/data-types/datetime64.md) data type with millisecond precision (scale = 3).
|
||||
|
||||
**Example**
|
||||
|
||||
|
@ -452,10 +452,23 @@ inline bool isObject(const T & data_type) { return WhichDataType(data_type).isOb
|
||||
template <typename T>
|
||||
inline bool isUInt8(const T & data_type) { return WhichDataType(data_type).isUInt8(); }
|
||||
template <typename T>
|
||||
inline bool isUInt16(const T & data_type) { return WhichDataType(data_type).isUInt16(); }
|
||||
template <typename T>
|
||||
inline bool isUInt32(const T & data_type) { return WhichDataType(data_type).isUInt32(); }
|
||||
template <typename T>
|
||||
inline bool isUInt64(const T & data_type) { return WhichDataType(data_type).isUInt64(); }
|
||||
template <typename T>
|
||||
inline bool isUnsignedInteger(const T & data_type) { return WhichDataType(data_type).isUInt(); }
|
||||
|
||||
template <typename T>
|
||||
inline bool isInt8(const T & data_type) { return WhichDataType(data_type).isInt8(); }
|
||||
template <typename T>
|
||||
inline bool isInt16(const T & data_type) { return WhichDataType(data_type).isInt16(); }
|
||||
template <typename T>
|
||||
inline bool isInt32(const T & data_type) { return WhichDataType(data_type).isInt32(); }
|
||||
template <typename T>
|
||||
inline bool isInt64(const T & data_type) { return WhichDataType(data_type).isInt64(); }
|
||||
|
||||
template <typename T>
|
||||
inline bool isInteger(const T & data_type)
|
||||
{
|
||||
|
@ -4,10 +4,12 @@
|
||||
#include <Functions/IFunction.h>
|
||||
#include <Functions/FunctionHelpers.h>
|
||||
#include <DataTypes/DataTypeDateTime64.h>
|
||||
#include <DataTypes/DataTypesDecimal.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Columns/ColumnConst.h>
|
||||
#include <Columns/ColumnsDateTime.h>
|
||||
#include <Columns/ColumnsNumber.h>
|
||||
#include <Core/DecimalFunctions.h>
|
||||
#include <Interpreters/Context.h>
|
||||
|
||||
#include <base/arithmeticOverflow.h>
|
||||
@ -40,14 +42,15 @@ public:
|
||||
|
||||
String getName() const override { return name; }
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isVariadic() const override { return false; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (!isDateTime(arguments[0].type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The only argument for function {} must be DateTime", name);
|
||||
FunctionArgumentDescriptors args{
|
||||
{"value", &isDateTime<IDataType>, nullptr, "DateTime"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, args);
|
||||
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
@ -88,13 +91,15 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (arguments.empty() || arguments.size() > 2)
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} takes one or two arguments", name);
|
||||
FunctionArgumentDescriptors mandatory_args{
|
||||
{"value", &isInt64<IDataType>, nullptr, "Int64"}
|
||||
};
|
||||
FunctionArgumentDescriptors optional_args{
|
||||
{"time_zone", &isString<IDataType>, nullptr, "String"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args);
|
||||
|
||||
if (!typeid_cast<const DataTypeInt64 *>(arguments[0].type.get()))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The first argument for function {} must be Int64", name);
|
||||
|
||||
std::string timezone;
|
||||
String timezone;
|
||||
if (arguments.size() == 2)
|
||||
timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments);
|
||||
|
||||
@ -141,14 +146,15 @@ public:
|
||||
|
||||
String getName() const override { return name; }
|
||||
size_t getNumberOfArguments() const override { return 1; }
|
||||
bool isVariadic() const override { return false; }
|
||||
bool useDefaultImplementationForConstants() const override { return true; }
|
||||
bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; }
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (!isDateTime64(arguments[0].type))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The only argument for function {} must be DateTime64", name);
|
||||
FunctionArgumentDescriptors args{
|
||||
{"value", &isDateTime64<IDataType>, nullptr, "DateTime64"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, args);
|
||||
|
||||
return std::make_shared<DataTypeInt64>();
|
||||
}
|
||||
@ -156,14 +162,21 @@ public:
|
||||
ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
|
||||
{
|
||||
const auto & src = arguments[0];
|
||||
const auto & src_column = *src.column;
|
||||
|
||||
const auto & src_column = *src.column;
|
||||
auto res_column = ColumnInt64::create(input_rows_count);
|
||||
auto & res_data = res_column->getData();
|
||||
|
||||
const auto & src_data = typeid_cast<const ColumnDecimal<DateTime64> &>(src_column).getData();
|
||||
|
||||
/// timestamps in snowflake-ids are millisecond-based, convert input to milliseconds
|
||||
UInt32 src_scale = getDecimalScale(*arguments[0].type);
|
||||
Int64 multiplier_msec = DecimalUtils::scaleMultiplier<DateTime64>(3);
|
||||
Int64 multiplier_src = DecimalUtils::scaleMultiplier<DateTime64>(src_scale);
|
||||
auto factor = multiplier_msec / static_cast<double>(multiplier_src);
|
||||
|
||||
for (size_t i = 0; i < input_rows_count; ++i)
|
||||
res_data[i] = (src_data[i] - snowflake_epoch) << time_shift;
|
||||
res_data[i] = static_cast<Int64>(src_data[i] * factor - snowflake_epoch) << time_shift;
|
||||
|
||||
return res_column;
|
||||
}
|
||||
@ -190,13 +203,15 @@ public:
|
||||
|
||||
DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
|
||||
{
|
||||
if (arguments.empty() || arguments.size() > 2)
|
||||
throw Exception(ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH, "Function {} takes one or two arguments", name);
|
||||
FunctionArgumentDescriptors mandatory_args{
|
||||
{"value", &isInt64<IDataType>, nullptr, "Int64"}
|
||||
};
|
||||
FunctionArgumentDescriptors optional_args{
|
||||
{"time_zone", &isString<IDataType>, nullptr, "String"}
|
||||
};
|
||||
validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args);
|
||||
|
||||
if (!typeid_cast<const DataTypeInt64 *>(arguments[0].type.get()))
|
||||
throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "The first argument for function {} must be Int64", name);
|
||||
|
||||
std::string timezone;
|
||||
String timezone;
|
||||
if (arguments.size() == 2)
|
||||
timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
const column
|
||||
2021-08-15 18:57:56 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840
|
||||
non-const column
|
||||
2021-08-15 18:57:56 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840
|
||||
-- const / non-const inputs
|
||||
2021-08-15 18:57:56 1426860702823350272 1426860702823350272
|
||||
2021-08-15 18:57:56.492 1426860704886947840 1426860704886947840
|
||||
-- different DateTime64 scales
|
||||
1426981498778550272 1426981500456271872 1426981500833759232 1426981500842147840 1426981500842147840
|
||||
1 1 1 1 0
|
||||
|
@ -1,23 +1,43 @@
|
||||
-- Error cases
|
||||
SELECT dateTimeToSnowflake(); -- {serverError 42}
|
||||
SELECT dateTime64ToSnowflake(); -- {serverError 42}
|
||||
SELECT dateTimeToSnowflake(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT dateTime64ToSnowflake(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT dateTimeToSnowflake('abc'); -- {serverError 43}
|
||||
SELECT dateTime64ToSnowflake('abc'); -- {serverError 43}
|
||||
SELECT dateTimeToSnowflake('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT dateTime64ToSnowflake('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT dateTimeToSnowflake('abc', 123); -- {serverError 42}
|
||||
SELECT dateTime64ToSnowflake('abc', 123); -- {serverError 42}
|
||||
SELECT dateTimeToSnowflake('abc', 123); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT dateTime64ToSnowflake('abc', 123); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT '-- const / non-const inputs';
|
||||
|
||||
SELECT 'const column';
|
||||
WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS dt
|
||||
SELECT dt, dateTimeToSnowflake(dt);
|
||||
SELECT dt, dateTimeToSnowflake(dt), materialize(dateTimeToSnowflake(dt));
|
||||
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS dt64
|
||||
SELECT dt64, dateTime64ToSnowflake(dt64);
|
||||
SELECT dt64, dateTime64ToSnowflake(dt64), materialize(dateTime64ToSnowflake(dt64));
|
||||
|
||||
SELECT 'non-const column';
|
||||
WITH toDateTime('2021-08-15 18:57:56', 'Asia/Shanghai') AS x
|
||||
SELECT materialize(x) as dt, dateTimeToSnowflake(dt);;
|
||||
SELECT '-- different DateTime64 scales';
|
||||
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 3, 'Asia/Shanghai') AS x
|
||||
SELECT materialize(x) as dt64, dateTime64ToSnowflake(dt64);
|
||||
WITH toDateTime64('2021-08-15 18:57:56.492', 0, 'UTC') AS dt64_0,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 1, 'UTC') AS dt64_1,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 2, 'UTC') AS dt64_2,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 3, 'UTC') AS dt64_3,
|
||||
toDateTime64('2021-08-15 18:57:56.492', 4, 'UTC') AS dt64_4
|
||||
SELECT dateTime64ToSnowflake(dt64_0),
|
||||
dateTime64ToSnowflake(dt64_1),
|
||||
dateTime64ToSnowflake(dt64_2),
|
||||
dateTime64ToSnowflake(dt64_3),
|
||||
dateTime64ToSnowflake(dt64_4);
|
||||
|
||||
-- DateTime64-to-Snowflake-to-DateTime64 is idempotent *if* the scale is <=3 (millisecond
|
||||
-- precision)
|
||||
WITH now64(0) AS dt64_0,
|
||||
now64(1) AS dt64_1,
|
||||
now64(2) AS dt64_2,
|
||||
now64(3) AS dt64_3,
|
||||
now64(4) AS dt64_4
|
||||
SELECT snowflakeToDateTime64(dateTime64ToSnowflake(dt64_0)) == dt64_0,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_1)) == dt64_1,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_2)) == dt64_2,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_3)) == dt64_3,
|
||||
snowflakeToDateTime64(dateTime64ToSnowflake(dt64_4)) == dt64_4;
|
||||
|
@ -1,12 +1,12 @@
|
||||
-- -- Error cases
|
||||
SELECT snowflakeToDateTime(); -- {serverError 42}
|
||||
SELECT snowflakeToDateTime64(); -- {serverError 42}
|
||||
SELECT snowflakeToDateTime(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
SELECT snowflakeToDateTime64(); -- {serverError NUMBER_OF_ARGUMENTS_DOESNT_MATCH}
|
||||
|
||||
SELECT snowflakeToDateTime('abc'); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime64('abc'); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT snowflakeToDateTime64('abc'); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT snowflakeToDateTime('abc', 123); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime64('abc', 123); -- {serverError 43}
|
||||
SELECT snowflakeToDateTime('abc', 123); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
SELECT snowflakeToDateTime64('abc', 123); -- {serverError ILLEGAL_TYPE_OF_ARGUMENT}
|
||||
|
||||
SELECT 'const column';
|
||||
WITH
|
||||
|
Loading…
Reference in New Issue
Block a user