#pragma once #include #include #include #include namespace DB { namespace ErrorCodes { extern const int CANNOT_CONVERT_TYPE; extern const int NOT_IMPLEMENTED; } /** Converts numeric value of any type to specified type. */ template class FieldVisitorConvertToNumber : public StaticVisitor { public: T operator() (const Null &) const { throw Exception("Cannot convert NULL to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const String &) const { throw Exception("Cannot convert String to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const Array &) const { throw Exception("Cannot convert Array to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const Tuple &) const { throw Exception("Cannot convert Tuple to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const Map &) const { throw Exception("Cannot convert Map to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const Object &) const { throw Exception("Cannot convert Object to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } T operator() (const UInt64 & x) const { return T(x); } T operator() (const Int64 & x) const { return T(x); } T operator() (const Int128 & x) const { return T(x); } T operator() (const UUID & x) const { return T(x.toUnderType()); } T operator() (const Float64 & x) const { if constexpr (!std::is_floating_point_v) { if (!isFinite(x)) { /// When converting to bool it's ok (non-zero converts to true, NaN including). if (std::is_same_v) return true; /// Conversion of infinite values to integer is undefined. throw Exception("Cannot convert infinite value to integer type", ErrorCodes::CANNOT_CONVERT_TYPE); } else if (x > Float64(std::numeric_limits::max()) || x < Float64(std::numeric_limits::lowest())) { throw Exception("Cannot convert out of range floating point value to integer type", ErrorCodes::CANNOT_CONVERT_TYPE); } } if constexpr (std::is_same_v) { return Int256(x); } else { return T(x); } } T operator() (const UInt128 &) const { throw Exception("Cannot convert UInt128 to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } template T operator() (const DecimalField & x) const { if constexpr (std::is_floating_point_v) return x.getValue().template convertTo() / x.getScaleMultiplier().template convertTo(); else return (x.getValue() / x.getScaleMultiplier()). template convertTo(); } T operator() (const AggregateFunctionStateData &) const { throw Exception("Cannot convert AggregateFunctionStateData to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); } template requires is_big_int_v T operator() (const U & x) const { if constexpr (is_decimal) return static_cast(static_cast(x)); else if constexpr (std::is_same_v) throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED); else return static_cast(x); } T operator() (const bool & x) const { return T(x); } }; }