#pragma once #include #include #include #include class SipHash; namespace DB { namespace ErrorCodes { extern const int CANNOT_CONVERT_TYPE; extern const int LOGICAL_ERROR; extern const int NOT_IMPLEMENTED; } /** StaticVisitor (and its descendants) - class with overloaded operator() for all types of fields. * You could call visitor for field using function 'applyVisitor'. * Also "binary visitor" is supported - its operator() takes two arguments. */ template struct StaticVisitor { using ResultType = R; }; /// F is template parameter, to allow universal reference for field, that is useful for const and non-const values. template auto applyVisitor(Visitor && visitor, F && field) { return Field::dispatch(std::forward(visitor), std::forward(field)); } template auto applyVisitor(Visitor && visitor, F1 && field1, F2 && field2) { return Field::dispatch( [&field2, &visitor](auto & field1_value) { return Field::dispatch( [&field1_value, &visitor](auto & field2_value) { return visitor(field1_value, field2_value); }, std::forward(field2)); }, std::forward(field1)); } /** Prints Field as literal in SQL query */ class FieldVisitorToString : public StaticVisitor { public: String operator() (const Null & x) const; String operator() (const UInt64 & x) const; String operator() (const UInt128 & x) const; String operator() (const UInt256 & x) const; String operator() (const Int64 & x) const; String operator() (const Int128 & x) const; String operator() (const Int256 & x) const; String operator() (const UUID & x) const; String operator() (const Float64 & x) const; String operator() (const String & x) const; String operator() (const Array & x) const; String operator() (const Tuple & x) const; String operator() (const Map & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const AggregateFunctionStateData & x) const; }; class FieldVisitorWriteBinary { public: void operator() (const Null & x, WriteBuffer & buf) const; void operator() (const UInt64 & x, WriteBuffer & buf) const; void operator() (const UInt128 & x, WriteBuffer & buf) const; void operator() (const UInt256 & x, WriteBuffer & buf) const; void operator() (const Int64 & x, WriteBuffer & buf) const; void operator() (const Int128 & x, WriteBuffer & buf) const; void operator() (const Int256 & x, WriteBuffer & buf) const; void operator() (const UUID & x, WriteBuffer & buf) const; void operator() (const Float64 & x, WriteBuffer & buf) const; void operator() (const String & x, WriteBuffer & buf) const; void operator() (const Array & x, WriteBuffer & buf) const; void operator() (const Tuple & x, WriteBuffer & buf) const; void operator() (const Map & x, WriteBuffer & buf) const; void operator() (const DecimalField & x, WriteBuffer & buf) const; void operator() (const DecimalField & x, WriteBuffer & buf) const; void operator() (const DecimalField & x, WriteBuffer & buf) const; void operator() (const DecimalField & x, WriteBuffer & buf) const; void operator() (const AggregateFunctionStateData & x, WriteBuffer & buf) const; }; /** Print readable and unique text dump of field type and value. */ class FieldVisitorDump : public StaticVisitor { public: String operator() (const Null & x) const; String operator() (const UInt64 & x) const; String operator() (const UInt128 & x) const; String operator() (const UInt256 & x) const; String operator() (const Int64 & x) const; String operator() (const Int128 & x) const; String operator() (const Int256 & x) const; String operator() (const UUID & x) const; String operator() (const Float64 & x) const; String operator() (const String & x) const; String operator() (const Array & x) const; String operator() (const Tuple & x) const; String operator() (const Map & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const DecimalField & x) const; String operator() (const AggregateFunctionStateData & x) const; }; /** 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 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 > std::numeric_limits::max() || x < 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 if constexpr (std::is_same_v) { /// TODO: remove with old UInt128 type if constexpr (sizeof(U) < 16) { return UInt128(0, (x.getValue() / x.getScaleMultiplier()).value); } else if constexpr (sizeof(U) == 16) { auto tmp = (x.getValue() / x.getScaleMultiplier()).value; return UInt128(tmp >> 64, UInt64(tmp)); } else throw Exception("No conversion to old UInt128 from " + demangle(typeid(U).name()), ErrorCodes::NOT_IMPLEMENTED); } 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 > > T operator() (const U & x) const { if constexpr (IsDecimalNumber) 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); } }; /** Updates SipHash by type and value of Field */ class FieldVisitorHash : public StaticVisitor<> { private: SipHash & hash; public: FieldVisitorHash(SipHash & hash_); void operator() (const Null & x) const; void operator() (const UInt64 & x) const; void operator() (const UInt128 & x) const; void operator() (const UInt256 & x) const; void operator() (const Int64 & x) const; void operator() (const Int128 & x) const; void operator() (const Int256 & x) const; void operator() (const UUID & x) const; void operator() (const Float64 & x) const; void operator() (const String & x) const; void operator() (const Array & x) const; void operator() (const Tuple & x) const; void operator() (const Map & x) const; void operator() (const DecimalField & x) const; void operator() (const DecimalField & x) const; void operator() (const DecimalField & x) const; void operator() (const DecimalField & x) const; void operator() (const AggregateFunctionStateData & x) const; }; template constexpr bool isDecimalField() { return false; } template <> constexpr bool isDecimalField>() { return true; } template <> constexpr bool isDecimalField>() { return true; } template <> constexpr bool isDecimalField>() { return true; } template <> constexpr bool isDecimalField>() { return true; } /** Implements `+=` operation. * Returns false if the result is zero. */ class FieldVisitorSum : public StaticVisitor { private: const Field & rhs; public: explicit FieldVisitorSum(const Field & rhs_) : rhs(rhs_) {} // We can add all ints as unsigned regardless of their actual signedness. bool operator() (Int64 & x) const { return this->operator()(reinterpret_cast(x)); } bool operator() (UInt64 & x) const { x += rhs.reinterpret(); return x != 0; } bool operator() (Float64 & x) const { x += get(rhs); return x != 0; } bool operator() (Null &) const { throw Exception("Cannot sum Nulls", ErrorCodes::LOGICAL_ERROR); } bool operator() (String &) const { throw Exception("Cannot sum Strings", ErrorCodes::LOGICAL_ERROR); } bool operator() (Array &) const { throw Exception("Cannot sum Arrays", ErrorCodes::LOGICAL_ERROR); } bool operator() (Tuple &) const { throw Exception("Cannot sum Tuples", ErrorCodes::LOGICAL_ERROR); } bool operator() (Map &) const { throw Exception("Cannot sum Maps", ErrorCodes::LOGICAL_ERROR); } bool operator() (UUID &) const { throw Exception("Cannot sum UUIDs", ErrorCodes::LOGICAL_ERROR); } bool operator() (AggregateFunctionStateData &) const { throw Exception("Cannot sum AggregateFunctionStates", ErrorCodes::LOGICAL_ERROR); } bool operator() (Int128 & x) const { x += get(rhs); return x != Int128(0); } template bool operator() (DecimalField & x) const { x += get>(rhs); return x.getValue() != T(0); } template > > bool operator() (T & x) const { x += rhs.reinterpret(); return x != T(0); } }; }