diff --git a/src/Functions/FunctionJoinGet.cpp b/src/Functions/FunctionJoinGet.cpp index 00bc3d8142a..51eab38bee5 100644 --- a/src/Functions/FunctionJoinGet.cpp +++ b/src/Functions/FunctionJoinGet.cpp @@ -1,5 +1,3 @@ -#include - #include #include #include @@ -7,15 +5,117 @@ #include #include +#include +#include +#include +#include + namespace DB { + namespace ErrorCodes { extern const int ILLEGAL_TYPE_OF_ARGUMENT; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } +namespace +{ + +class HashJoin; +using StorageJoinPtr = std::shared_ptr; + +template +class ExecutableFunctionJoinGet final : public IExecutableFunction, WithContext +{ +public: + ExecutableFunctionJoinGet(ContextPtr context_, + TableLockHolder table_lock_, + StorageJoinPtr storage_join_, + const DB::Block & result_columns_) + : WithContext(context_) + , table_lock(std::move(table_lock_)) + , storage_join(std::move(storage_join_)) + , result_columns(result_columns_) + {} + + static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; + + bool useDefaultImplementationForNulls() const override { return false; } + bool useDefaultImplementationForLowCardinalityColumns() const override { return false; } + bool useDefaultImplementationForConstants() const override { return true; } + + ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override; + + String getName() const override { return name; } + +private: + TableLockHolder table_lock; + StorageJoinPtr storage_join; + DB::Block result_columns; +}; + +template +class FunctionJoinGet final : public IFunctionBase, WithContext +{ +public: + static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; + + FunctionJoinGet(ContextPtr context_, + TableLockHolder table_lock_, + StorageJoinPtr storage_join_, String attr_name_, + DataTypes argument_types_, DataTypePtr return_type_) + : WithContext(context_) + , table_lock(std::move(table_lock_)) + , storage_join(storage_join_) + , attr_name(std::move(attr_name_)) + , argument_types(std::move(argument_types_)) + , return_type(std::move(return_type_)) + { + } + + String getName() const override { return name; } + + bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } + + const DataTypes & getArgumentTypes() const override { return argument_types; } + const DataTypePtr & getResultType() const override { return return_type; } + + ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName &) const override; + +private: + TableLockHolder table_lock; + StorageJoinPtr storage_join; + const String attr_name; + DataTypes argument_types; + DataTypePtr return_type; +}; + +template +class JoinGetOverloadResolver final : public IFunctionOverloadResolver, WithContext +{ +public: + static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; + static FunctionOverloadResolverPtr create(ContextPtr context_) { return std::make_unique(context_); } + + explicit JoinGetOverloadResolver(ContextPtr context_) : WithContext(context_) {} + + bool isDeterministic() const override { return false; } + String getName() const override { return name; } + + FunctionBasePtr buildImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &) const override; + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName &) const override { return {}; } // Not used + + bool useDefaultImplementationForNulls() const override { return false; } + bool useDefaultImplementationForLowCardinalityColumns() const override { return false; } + + bool isVariadic() const override { return true; } + size_t getNumberOfArguments() const override { return 0; } + ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0, 1}; } +}; + + template ColumnPtr ExecutableFunctionJoinGet::executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t) const { @@ -96,6 +196,8 @@ FunctionBasePtr JoinGetOverloadResolver::buildImpl(const ColumnsWithTyp return std::make_unique>(getContext(), table_lock, storage_join, attr_name, argument_types, return_type); } +} + REGISTER_FUNCTION(JoinGet) { // joinGet @@ -104,10 +206,4 @@ REGISTER_FUNCTION(JoinGet) factory.registerFunction>(); } -template class ExecutableFunctionJoinGet; -template class ExecutableFunctionJoinGet; -template class FunctionJoinGet; -template class FunctionJoinGet; -template class JoinGetOverloadResolver; -template class JoinGetOverloadResolver; } diff --git a/src/Functions/FunctionJoinGet.h b/src/Functions/FunctionJoinGet.h deleted file mode 100644 index 998a892f3df..00000000000 --- a/src/Functions/FunctionJoinGet.h +++ /dev/null @@ -1,105 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace DB -{ - -class HashJoin; -class StorageJoin; -using StorageJoinPtr = std::shared_ptr; - -template -class ExecutableFunctionJoinGet final : public IExecutableFunction, WithContext -{ -public: - ExecutableFunctionJoinGet(ContextPtr context_, - TableLockHolder table_lock_, - StorageJoinPtr storage_join_, - const DB::Block & result_columns_) - : WithContext(context_) - , table_lock(std::move(table_lock_)) - , storage_join(std::move(storage_join_)) - , result_columns(result_columns_) - {} - - static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; - - bool useDefaultImplementationForNulls() const override { return false; } - bool useDefaultImplementationForLowCardinalityColumns() const override { return false; } - bool useDefaultImplementationForConstants() const override { return true; } - - ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override; - - String getName() const override { return name; } - -private: - TableLockHolder table_lock; - StorageJoinPtr storage_join; - DB::Block result_columns; -}; - -template -class FunctionJoinGet final : public IFunctionBase, WithContext -{ -public: - static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; - - FunctionJoinGet(ContextPtr context_, - TableLockHolder table_lock_, - StorageJoinPtr storage_join_, String attr_name_, - DataTypes argument_types_, DataTypePtr return_type_) - : WithContext(context_) - , table_lock(std::move(table_lock_)) - , storage_join(storage_join_) - , attr_name(std::move(attr_name_)) - , argument_types(std::move(argument_types_)) - , return_type(std::move(return_type_)) - { - } - - String getName() const override { return name; } - - bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } - - const DataTypes & getArgumentTypes() const override { return argument_types; } - const DataTypePtr & getResultType() const override { return return_type; } - - ExecutableFunctionPtr prepare(const ColumnsWithTypeAndName &) const override; - -private: - TableLockHolder table_lock; - StorageJoinPtr storage_join; - const String attr_name; - DataTypes argument_types; - DataTypePtr return_type; -}; - -template -class JoinGetOverloadResolver final : public IFunctionOverloadResolver, WithContext -{ -public: - static constexpr auto name = or_null ? "joinGetOrNull" : "joinGet"; - static FunctionOverloadResolverPtr create(ContextPtr context_) { return std::make_unique(context_); } - - explicit JoinGetOverloadResolver(ContextPtr context_) : WithContext(context_) {} - - bool isDeterministic() const override { return false; } - String getName() const override { return name; } - - FunctionBasePtr buildImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &) const override; - DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName &) const override { return {}; } // Not used - - bool useDefaultImplementationForNulls() const override { return false; } - bool useDefaultImplementationForLowCardinalityColumns() const override { return false; } - - bool isVariadic() const override { return true; } - size_t getNumberOfArguments() const override { return 0; } - ColumnNumbers getArgumentsThatAreAlwaysConstant() const override { return {0, 1}; } -}; - -} diff --git a/src/Functions/FunctionSnowflake.h b/src/Functions/FunctionSnowflake.h deleted file mode 100644 index 26c8138633b..00000000000 --- a/src/Functions/FunctionSnowflake.h +++ /dev/null @@ -1,247 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - - -namespace DB -{ -namespace ErrorCodes -{ - extern const int ILLEGAL_TYPE_OF_ARGUMENT; -} - -/** According to Twitter's post on Snowflake, we can extract the timestamp for a snowflake ID by right shifting - * the snowflake ID by 22 bits(10 bits machine ID and 12 bits sequence ID) and adding the Twitter epoch time of 1288834974657. - * https://en.wikipedia.org/wiki/Snowflake_ID - * https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake - * https://ws-dl.blogspot.com/2019/08/2019-08-03-tweetedat-finding-tweet.html -*/ -static constexpr size_t snowflake_epoch = 1288834974657L; -static constexpr int time_shift = 22; - -class FunctionDateTimeToSnowflake : public IFunction -{ -private: - const char * name; - -public: - explicit FunctionDateTimeToSnowflake(const char * name_) : name(name_) { } - - String getName() const override { return name; } - size_t getNumberOfArguments() const override { return 1; } - bool useDefaultImplementationForConstants() const override { return true; } - bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } - - DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override - { - FunctionArgumentDescriptors args{ - {"value", &isDateTime, nullptr, "DateTime"} - }; - validateFunctionArgumentTypes(*this, arguments, args); - - return std::make_shared(); - } - - 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; - - auto res_column = ColumnInt64::create(input_rows_count); - auto & res_data = res_column->getData(); - - const auto & src_data = typeid_cast(src_column).getData(); - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = (Int64(src_data[i]) * 1000 - snowflake_epoch) << time_shift; - - return res_column; - } -}; - -class FunctionSnowflakeToDateTime : public IFunction -{ -private: - const char * name; - const bool allow_nonconst_timezone_arguments; - -public: - explicit FunctionSnowflakeToDateTime(const char * name_, ContextPtr context) - : name(name_) - , allow_nonconst_timezone_arguments(context->getSettings().allow_nonconst_timezone_arguments) - {} - - String getName() const override { return name; } - size_t getNumberOfArguments() const override { return 0; } - bool isVariadic() const override { return true; } - bool useDefaultImplementationForConstants() const override { return true; } - bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } - - DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override - { - FunctionArgumentDescriptors mandatory_args{ - {"value", &isInt64, nullptr, "Int64"} - }; - FunctionArgumentDescriptors optional_args{ - {"time_zone", &isString, nullptr, "String"} - }; - validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args); - - String timezone; - if (arguments.size() == 2) - timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments); - - return std::make_shared(timezone); - } - - 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; - - auto res_column = ColumnUInt32::create(input_rows_count); - auto & res_data = res_column->getData(); - - if (const auto * src_column_non_const = typeid_cast(&src_column)) - { - const auto & src_data = src_column_non_const->getData(); - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = static_cast( - ((src_data[i] >> time_shift) + snowflake_epoch) / 1000); - } - else if (const auto * src_column_const = typeid_cast(&src_column)) - { - Int64 src_val = src_column_const->getValue(); - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = static_cast( - ((src_val >> time_shift) + snowflake_epoch) / 1000); - } - else - throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal argument for function {}", name); - - return res_column; - } -}; - - -class FunctionDateTime64ToSnowflake : public IFunction -{ -private: - const char * name; - -public: - explicit FunctionDateTime64ToSnowflake(const char * name_) : name(name_) { } - - String getName() const override { return name; } - size_t getNumberOfArguments() const override { return 1; } - bool useDefaultImplementationForConstants() const override { return true; } - bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } - - DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override - { - FunctionArgumentDescriptors args{ - {"value", &isDateTime64, nullptr, "DateTime64"} - }; - validateFunctionArgumentTypes(*this, arguments, args); - - return std::make_shared(); - } - - 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; - auto res_column = ColumnInt64::create(input_rows_count); - auto & res_data = res_column->getData(); - - const auto & src_data = typeid_cast &>(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(3); - Int64 multiplier_src = DecimalUtils::scaleMultiplier(src_scale); - auto factor = multiplier_msec / static_cast(multiplier_src); - - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = static_cast(src_data[i] * factor - snowflake_epoch) << time_shift; - - return res_column; - } -}; - - -class FunctionSnowflakeToDateTime64 : public IFunction -{ -private: - const char * name; - const bool allow_nonconst_timezone_arguments; - -public: - explicit FunctionSnowflakeToDateTime64(const char * name_, ContextPtr context) - : name(name_) - , allow_nonconst_timezone_arguments(context->getSettings().allow_nonconst_timezone_arguments) - {} - - String getName() const override { return name; } - size_t getNumberOfArguments() const override { return 0; } - bool isVariadic() const override { return true; } - bool useDefaultImplementationForConstants() const override { return true; } - bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } - - DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override - { - FunctionArgumentDescriptors mandatory_args{ - {"value", &isInt64, nullptr, "Int64"} - }; - FunctionArgumentDescriptors optional_args{ - {"time_zone", &isString, nullptr, "String"} - }; - validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args); - - String timezone; - if (arguments.size() == 2) - timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments); - - return std::make_shared(3, timezone); - } - - 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; - - auto res_column = ColumnDecimal::create(input_rows_count, 3); - auto & res_data = res_column->getData(); - - if (const auto * src_column_non_const = typeid_cast(&src_column)) - { - const auto & src_data = src_column_non_const->getData(); - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = (src_data[i] >> time_shift) + snowflake_epoch; - } - else if (const auto * src_column_const = typeid_cast(&src_column)) - { - Int64 src_val = src_column_const->getValue(); - for (size_t i = 0; i < input_rows_count; ++i) - res_data[i] = (src_val >> time_shift) + snowflake_epoch; - } - else - throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal argument for function {}", name); - - return res_column; - } -}; - -} diff --git a/src/Functions/FunctionToDecimalString.cpp b/src/Functions/FunctionToDecimalString.cpp deleted file mode 100644 index fe417b19137..00000000000 --- a/src/Functions/FunctionToDecimalString.cpp +++ /dev/null @@ -1,22 +0,0 @@ -#include -#include -#include - -namespace DB -{ - -REGISTER_FUNCTION(ToDecimalString) -{ - factory.registerFunction( - FunctionDocumentation{ - .description=R"( -Returns string representation of a number. First argument is the number of any numeric type, -second argument is the desired number of digits in fractional part. Returns String. - - )", - .examples{{"toDecimalString", "SELECT toDecimalString(2.1456,2)", ""}}, - .categories{"String"} - }, FunctionFactory::CaseInsensitive); -} - -} diff --git a/src/Functions/snowflake.cpp b/src/Functions/snowflake.cpp index c18f1c03332..989feecb9b4 100644 --- a/src/Functions/snowflake.cpp +++ b/src/Functions/snowflake.cpp @@ -1,9 +1,251 @@ -#include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + namespace DB { +namespace ErrorCodes +{ + extern const int ILLEGAL_TYPE_OF_ARGUMENT; +} + +namespace +{ + +/** According to Twitter's post on Snowflake, we can extract the timestamp for a snowflake ID by right shifting + * the snowflake ID by 22 bits(10 bits machine ID and 12 bits sequence ID) and adding the Twitter epoch time of 1288834974657. + * https://en.wikipedia.org/wiki/Snowflake_ID + * https://blog.twitter.com/engineering/en_us/a/2010/announcing-snowflake + * https://ws-dl.blogspot.com/2019/08/2019-08-03-tweetedat-finding-tweet.html +*/ +static constexpr size_t snowflake_epoch = 1288834974657L; +static constexpr int time_shift = 22; + +class FunctionDateTimeToSnowflake : public IFunction +{ +private: + const char * name; + +public: + explicit FunctionDateTimeToSnowflake(const char * name_) : name(name_) { } + + String getName() const override { return name; } + size_t getNumberOfArguments() const override { return 1; } + bool useDefaultImplementationForConstants() const override { return true; } + bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + FunctionArgumentDescriptors args{ + {"value", &isDateTime, nullptr, "DateTime"} + }; + validateFunctionArgumentTypes(*this, arguments, args); + + return std::make_shared(); + } + + 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; + + auto res_column = ColumnInt64::create(input_rows_count); + auto & res_data = res_column->getData(); + + const auto & src_data = typeid_cast(src_column).getData(); + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = (Int64(src_data[i]) * 1000 - snowflake_epoch) << time_shift; + + return res_column; + } +}; + +class FunctionSnowflakeToDateTime : public IFunction +{ +private: + const char * name; + const bool allow_nonconst_timezone_arguments; + +public: + explicit FunctionSnowflakeToDateTime(const char * name_, ContextPtr context) + : name(name_) + , allow_nonconst_timezone_arguments(context->getSettings().allow_nonconst_timezone_arguments) + {} + + String getName() const override { return name; } + size_t getNumberOfArguments() const override { return 0; } + bool isVariadic() const override { return true; } + bool useDefaultImplementationForConstants() const override { return true; } + bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + FunctionArgumentDescriptors mandatory_args{ + {"value", &isInt64, nullptr, "Int64"} + }; + FunctionArgumentDescriptors optional_args{ + {"time_zone", &isString, nullptr, "String"} + }; + validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args); + + String timezone; + if (arguments.size() == 2) + timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments); + + return std::make_shared(timezone); + } + + 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; + + auto res_column = ColumnUInt32::create(input_rows_count); + auto & res_data = res_column->getData(); + + if (const auto * src_column_non_const = typeid_cast(&src_column)) + { + const auto & src_data = src_column_non_const->getData(); + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = static_cast( + ((src_data[i] >> time_shift) + snowflake_epoch) / 1000); + } + else if (const auto * src_column_const = typeid_cast(&src_column)) + { + Int64 src_val = src_column_const->getValue(); + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = static_cast( + ((src_val >> time_shift) + snowflake_epoch) / 1000); + } + else + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal argument for function {}", name); + + return res_column; + } +}; + + +class FunctionDateTime64ToSnowflake : public IFunction +{ +private: + const char * name; + +public: + explicit FunctionDateTime64ToSnowflake(const char * name_) : name(name_) { } + + String getName() const override { return name; } + size_t getNumberOfArguments() const override { return 1; } + bool useDefaultImplementationForConstants() const override { return true; } + bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + FunctionArgumentDescriptors args{ + {"value", &isDateTime64, nullptr, "DateTime64"} + }; + validateFunctionArgumentTypes(*this, arguments, args); + + return std::make_shared(); + } + + 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; + auto res_column = ColumnInt64::create(input_rows_count); + auto & res_data = res_column->getData(); + + const auto & src_data = typeid_cast &>(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(3); + Int64 multiplier_src = DecimalUtils::scaleMultiplier(src_scale); + auto factor = multiplier_msec / static_cast(multiplier_src); + + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = static_cast(src_data[i] * factor - snowflake_epoch) << time_shift; + + return res_column; + } +}; + + +class FunctionSnowflakeToDateTime64 : public IFunction +{ +private: + const char * name; + const bool allow_nonconst_timezone_arguments; + +public: + explicit FunctionSnowflakeToDateTime64(const char * name_, ContextPtr context) + : name(name_) + , allow_nonconst_timezone_arguments(context->getSettings().allow_nonconst_timezone_arguments) + {} + + String getName() const override { return name; } + size_t getNumberOfArguments() const override { return 0; } + bool isVariadic() const override { return true; } + bool useDefaultImplementationForConstants() const override { return true; } + bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & /*arguments*/) const override { return true; } + + DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override + { + FunctionArgumentDescriptors mandatory_args{ + {"value", &isInt64, nullptr, "Int64"} + }; + FunctionArgumentDescriptors optional_args{ + {"time_zone", &isString, nullptr, "String"} + }; + validateFunctionArgumentTypes(*this, arguments, mandatory_args, optional_args); + + String timezone; + if (arguments.size() == 2) + timezone = extractTimeZoneNameFromFunctionArguments(arguments, 1, 0, allow_nonconst_timezone_arguments); + + return std::make_shared(3, timezone); + } + + 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; + + auto res_column = ColumnDecimal::create(input_rows_count, 3); + auto & res_data = res_column->getData(); + + if (const auto * src_column_non_const = typeid_cast(&src_column)) + { + const auto & src_data = src_column_non_const->getData(); + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = (src_data[i] >> time_shift) + snowflake_epoch; + } + else if (const auto * src_column_const = typeid_cast(&src_column)) + { + Int64 src_val = src_column_const->getValue(); + for (size_t i = 0; i < input_rows_count; ++i) + res_data[i] = (src_val >> time_shift) + snowflake_epoch; + } + else + throw Exception(ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT, "Illegal argument for function {}", name); + + return res_column; + } +}; + +} + REGISTER_FUNCTION(DateTimeToSnowflake) { factory.registerFunction("dateTimeToSnowflake", diff --git a/src/Functions/FunctionToDecimalString.h b/src/toDecimalString.cpp similarity index 95% rename from src/Functions/FunctionToDecimalString.h rename to src/toDecimalString.cpp index 3dd946203cc..75593901bb3 100644 --- a/src/Functions/FunctionToDecimalString.h +++ b/src/toDecimalString.cpp @@ -1,10 +1,7 @@ -#pragma once - -#include -#include +#include #include +#include #include -#include #include #include #include @@ -14,6 +11,7 @@ #include #include + namespace DB { @@ -23,6 +21,9 @@ namespace ErrorCodes extern const int CANNOT_PRINT_FLOAT_OR_DOUBLE_NUMBER; } +namespace +{ + class FunctionToDecimalString : public IFunction { public: @@ -260,3 +261,19 @@ private: }; } + +REGISTER_FUNCTION(ToDecimalString) +{ + factory.registerFunction( + FunctionDocumentation{ + .description=R"( +Returns string representation of a number. First argument is the number of any numeric type, +second argument is the desired number of digits in fractional part. Returns String. + + )", + .examples{{"toDecimalString", "SELECT toDecimalString(2.1456,2)", ""}}, + .categories{"String"} + }, FunctionFactory::CaseInsensitive); +} + +}