| 1 | #pragma once |
| 2 | |
| 3 | #include <Core/Field.h> |
| 4 | #include <Core/AccurateComparison.h> |
| 5 | #include <common/demangle.h> |
| 6 | |
| 7 | |
| 8 | class SipHash; |
| 9 | |
| 10 | |
| 11 | namespace DB |
| 12 | { |
| 13 | |
| 14 | namespace ErrorCodes |
| 15 | { |
| 16 | extern const int CANNOT_CONVERT_TYPE; |
| 17 | extern const int BAD_TYPE_OF_FIELD; |
| 18 | extern const int LOGICAL_ERROR; |
| 19 | } |
| 20 | |
| 21 | #pragma GCC diagnostic push |
| 22 | #pragma GCC diagnostic ignored "-Wredundant-decls" |
| 23 | // Just dont mess with it. If the redundant redeclaration is removed then ReaderHelpers.h should be included. |
| 24 | // This leads to Arena.h inclusion which has a problem with ASAN stuff included properly and messing macro definition |
| 25 | // which intefrers with... You dont want to know, really. |
| 26 | UInt128 stringToUUID(const String & str); |
| 27 | #pragma GCC diagnostic pop |
| 28 | |
| 29 | |
| 30 | /** StaticVisitor (and its descendants) - class with overloaded operator() for all types of fields. |
| 31 | * You could call visitor for field using function 'applyVisitor'. |
| 32 | * Also "binary visitor" is supported - its operator() takes two arguments. |
| 33 | */ |
| 34 | template <typename R = void> |
| 35 | struct StaticVisitor |
| 36 | { |
| 37 | using ResultType = R; |
| 38 | }; |
| 39 | |
| 40 | |
| 41 | /// F is template parameter, to allow universal reference for field, that is useful for const and non-const values. |
| 42 | template <typename Visitor, typename F> |
| 43 | auto applyVisitor(Visitor && visitor, F && field) |
| 44 | { |
| 45 | return Field::dispatch(visitor, field); |
| 46 | } |
| 47 | |
| 48 | template <typename Visitor, typename F1, typename F2> |
| 49 | auto applyVisitor(Visitor && visitor, F1 && field1, F2 && field2) |
| 50 | { |
| 51 | return Field::dispatch([&](auto & field1_value) |
| 52 | { |
| 53 | return Field::dispatch([&](auto & field2_value) |
| 54 | { |
| 55 | return visitor(field1_value, field2_value); |
| 56 | }, |
| 57 | field2); |
| 58 | }, |
| 59 | field1); |
| 60 | } |
| 61 | |
| 62 | |
| 63 | /** Prints Field as literal in SQL query */ |
| 64 | class FieldVisitorToString : public StaticVisitor<String> |
| 65 | { |
| 66 | public: |
| 67 | String operator() (const Null & x) const; |
| 68 | String operator() (const UInt64 & x) const; |
| 69 | String operator() (const UInt128 & x) const; |
| 70 | String operator() (const Int64 & x) const; |
| 71 | String operator() (const Float64 & x) const; |
| 72 | String operator() (const String & x) const; |
| 73 | String operator() (const Array & x) const; |
| 74 | String operator() (const Tuple & x) const; |
| 75 | String operator() (const DecimalField<Decimal32> & x) const; |
| 76 | String operator() (const DecimalField<Decimal64> & x) const; |
| 77 | String operator() (const DecimalField<Decimal128> & x) const; |
| 78 | String operator() (const AggregateFunctionStateData & x) const; |
| 79 | }; |
| 80 | |
| 81 | |
| 82 | /** Print readable and unique text dump of field type and value. */ |
| 83 | class FieldVisitorDump : public StaticVisitor<String> |
| 84 | { |
| 85 | public: |
| 86 | String operator() (const Null & x) const; |
| 87 | String operator() (const UInt64 & x) const; |
| 88 | String operator() (const UInt128 & x) const; |
| 89 | String operator() (const Int64 & x) const; |
| 90 | String operator() (const Float64 & x) const; |
| 91 | String operator() (const String & x) const; |
| 92 | String operator() (const Array & x) const; |
| 93 | String operator() (const Tuple & x) const; |
| 94 | String operator() (const DecimalField<Decimal32> & x) const; |
| 95 | String operator() (const DecimalField<Decimal64> & x) const; |
| 96 | String operator() (const DecimalField<Decimal128> & x) const; |
| 97 | String operator() (const AggregateFunctionStateData & x) const; |
| 98 | }; |
| 99 | |
| 100 | |
| 101 | /** Converts numberic value of any type to specified type. */ |
| 102 | template <typename T> |
| 103 | class FieldVisitorConvertToNumber : public StaticVisitor<T> |
| 104 | { |
| 105 | public: |
| 106 | T operator() (const Null &) const |
| 107 | { |
| 108 | throw Exception("Cannot convert NULL to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 109 | } |
| 110 | |
| 111 | T operator() (const String &) const |
| 112 | { |
| 113 | throw Exception("Cannot convert String to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 114 | } |
| 115 | |
| 116 | T operator() (const Array &) const |
| 117 | { |
| 118 | throw Exception("Cannot convert Array to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 119 | } |
| 120 | |
| 121 | T operator() (const Tuple &) const |
| 122 | { |
| 123 | throw Exception("Cannot convert Tuple to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 124 | } |
| 125 | |
| 126 | T operator() (const UInt64 & x) const { return x; } |
| 127 | T operator() (const Int64 & x) const { return x; } |
| 128 | T operator() (const Float64 & x) const { return x; } |
| 129 | |
| 130 | T operator() (const UInt128 &) const |
| 131 | { |
| 132 | throw Exception("Cannot convert UInt128 to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 133 | } |
| 134 | |
| 135 | template <typename U> |
| 136 | T operator() (const DecimalField<U> & x) const |
| 137 | { |
| 138 | if constexpr (std::is_floating_point_v<T>) |
| 139 | return static_cast<T>(x.getValue()) / x.getScaleMultiplier(); |
| 140 | else |
| 141 | return x.getValue() / x.getScaleMultiplier(); |
| 142 | } |
| 143 | |
| 144 | T operator() (const AggregateFunctionStateData &) const |
| 145 | { |
| 146 | throw Exception("Cannot convert AggregateFunctionStateData to " + demangle(typeid(T).name()), ErrorCodes::CANNOT_CONVERT_TYPE); |
| 147 | } |
| 148 | }; |
| 149 | |
| 150 | |
| 151 | /** Updates SipHash by type and value of Field */ |
| 152 | class FieldVisitorHash : public StaticVisitor<> |
| 153 | { |
| 154 | private: |
| 155 | SipHash & hash; |
| 156 | public: |
| 157 | FieldVisitorHash(SipHash & hash_); |
| 158 | |
| 159 | void operator() (const Null & x) const; |
| 160 | void operator() (const UInt64 & x) const; |
| 161 | void operator() (const UInt128 & x) const; |
| 162 | void operator() (const Int64 & x) const; |
| 163 | void operator() (const Float64 & x) const; |
| 164 | void operator() (const String & x) const; |
| 165 | void operator() (const Array & x) const; |
| 166 | void operator() (const Tuple & x) const; |
| 167 | void operator() (const DecimalField<Decimal32> & x) const; |
| 168 | void operator() (const DecimalField<Decimal64> & x) const; |
| 169 | void operator() (const DecimalField<Decimal128> & x) const; |
| 170 | void operator() (const AggregateFunctionStateData & x) const; |
| 171 | }; |
| 172 | |
| 173 | |
| 174 | template <typename T> constexpr bool isDecimalField() { return false; } |
| 175 | template <> constexpr bool isDecimalField<DecimalField<Decimal32>>() { return true; } |
| 176 | template <> constexpr bool isDecimalField<DecimalField<Decimal64>>() { return true; } |
| 177 | template <> constexpr bool isDecimalField<DecimalField<Decimal128>>() { return true; } |
| 178 | |
| 179 | |
| 180 | /** More precise comparison, used for index. |
| 181 | * Differs from Field::operator< and Field::operator== in that it also compares values of different types. |
| 182 | * Comparison rules are same as in FunctionsComparison (to be consistent with expression evaluation in query). |
| 183 | */ |
| 184 | class FieldVisitorAccurateEquals : public StaticVisitor<bool> |
| 185 | { |
| 186 | public: |
| 187 | bool operator() (const UInt64 & l, const Null & r) const { return cantCompare(l, r); } |
| 188 | bool operator() (const UInt64 & l, const UInt64 & r) const { return l == r; } |
| 189 | bool operator() (const UInt64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 190 | bool operator() (const UInt64 & l, const Int64 & r) const { return accurate::equalsOp(l, r); } |
| 191 | bool operator() (const UInt64 & l, const Float64 & r) const { return accurate::equalsOp(l, r); } |
| 192 | bool operator() (const UInt64 & l, const String & r) const { return cantCompare(l, r); } |
| 193 | bool operator() (const UInt64 & l, const Array & r) const { return cantCompare(l, r); } |
| 194 | bool operator() (const UInt64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 195 | bool operator() (const UInt64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 196 | |
| 197 | bool operator() (const Int64 & l, const Null & r) const { return cantCompare(l, r); } |
| 198 | bool operator() (const Int64 & l, const UInt64 & r) const { return accurate::equalsOp(l, r); } |
| 199 | bool operator() (const Int64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 200 | bool operator() (const Int64 & l, const Int64 & r) const { return l == r; } |
| 201 | bool operator() (const Int64 & l, const Float64 & r) const { return accurate::equalsOp(l, r); } |
| 202 | bool operator() (const Int64 & l, const String & r) const { return cantCompare(l, r); } |
| 203 | bool operator() (const Int64 & l, const Array & r) const { return cantCompare(l, r); } |
| 204 | bool operator() (const Int64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 205 | bool operator() (const Int64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 206 | |
| 207 | bool operator() (const Float64 & l, const Null & r) const { return cantCompare(l, r); } |
| 208 | bool operator() (const Float64 & l, const UInt64 & r) const { return accurate::equalsOp(l, r); } |
| 209 | bool operator() (const Float64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 210 | bool operator() (const Float64 & l, const Int64 & r) const { return accurate::equalsOp(l, r); } |
| 211 | bool operator() (const Float64 & l, const Float64 & r) const { return l == r; } |
| 212 | bool operator() (const Float64 & l, const String & r) const { return cantCompare(l, r); } |
| 213 | bool operator() (const Float64 & l, const Array & r) const { return cantCompare(l, r); } |
| 214 | bool operator() (const Float64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 215 | bool operator() (const Float64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 216 | |
| 217 | template <typename T> |
| 218 | bool operator() (const Null &, const T &) const |
| 219 | { |
| 220 | return std::is_same_v<T, Null>; |
| 221 | } |
| 222 | |
| 223 | template <typename T> |
| 224 | bool operator() (const String & l, const T & r) const |
| 225 | { |
| 226 | if constexpr (std::is_same_v<T, String>) |
| 227 | return l == r; |
| 228 | if constexpr (std::is_same_v<T, UInt128>) |
| 229 | return stringToUUID(l) == r; |
| 230 | return cantCompare(l, r); |
| 231 | } |
| 232 | |
| 233 | template <typename T> |
| 234 | bool operator() (const UInt128 & l, const T & r) const |
| 235 | { |
| 236 | if constexpr (std::is_same_v<T, UInt128>) |
| 237 | return l == r; |
| 238 | if constexpr (std::is_same_v<T, String>) |
| 239 | return l == stringToUUID(r); |
| 240 | return cantCompare(l, r); |
| 241 | } |
| 242 | |
| 243 | template <typename T> |
| 244 | bool operator() (const Array & l, const T & r) const |
| 245 | { |
| 246 | if constexpr (std::is_same_v<T, Array>) |
| 247 | return l == r; |
| 248 | return cantCompare(l, r); |
| 249 | } |
| 250 | |
| 251 | template <typename T> |
| 252 | bool operator() (const Tuple & l, const T & r) const |
| 253 | { |
| 254 | if constexpr (std::is_same_v<T, Tuple>) |
| 255 | return l == r; |
| 256 | return cantCompare(l, r); |
| 257 | } |
| 258 | |
| 259 | template <typename T, typename U> |
| 260 | bool operator() (const DecimalField<T> & l, const U & r) const |
| 261 | { |
| 262 | if constexpr (isDecimalField<U>()) |
| 263 | return l == r; |
| 264 | if constexpr (std::is_same_v<U, Int64> || std::is_same_v<U, UInt64>) |
| 265 | return l == DecimalField<Decimal128>(r, 0); |
| 266 | return cantCompare(l, r); |
| 267 | } |
| 268 | |
| 269 | template <typename T> bool operator() (const UInt64 & l, const DecimalField<T> & r) const { return DecimalField<Decimal128>(l, 0) == r; } |
| 270 | template <typename T> bool operator() (const Int64 & l, const DecimalField<T> & r) const { return DecimalField<Decimal128>(l, 0) == r; } |
| 271 | template <typename T> bool operator() (const Float64 & l, const DecimalField<T> & r) const { return cantCompare(l, r); } |
| 272 | |
| 273 | template <typename T> |
| 274 | bool operator() (const AggregateFunctionStateData & l, const T & r) const |
| 275 | { |
| 276 | if constexpr (std::is_same_v<T, AggregateFunctionStateData>) |
| 277 | return l == r; |
| 278 | return cantCompare(l, r); |
| 279 | } |
| 280 | |
| 281 | private: |
| 282 | template <typename T, typename U> |
| 283 | bool cantCompare(const T &, const U &) const |
| 284 | { |
| 285 | if constexpr (std::is_same_v<U, Null>) |
| 286 | return false; |
| 287 | throw Exception("Cannot compare " + demangle(typeid(T).name()) + " with " + demangle(typeid(U).name()), |
| 288 | ErrorCodes::BAD_TYPE_OF_FIELD); |
| 289 | } |
| 290 | }; |
| 291 | |
| 292 | |
| 293 | class FieldVisitorAccurateLess : public StaticVisitor<bool> |
| 294 | { |
| 295 | public: |
| 296 | bool operator() (const UInt64 & l, const Null & r) const { return cantCompare(l, r); } |
| 297 | bool operator() (const UInt64 & l, const UInt64 & r) const { return l < r; } |
| 298 | bool operator() (const UInt64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 299 | bool operator() (const UInt64 & l, const Int64 & r) const { return accurate::lessOp(l, r); } |
| 300 | bool operator() (const UInt64 & l, const Float64 & r) const { return accurate::lessOp(l, r); } |
| 301 | bool operator() (const UInt64 & l, const String & r) const { return cantCompare(l, r); } |
| 302 | bool operator() (const UInt64 & l, const Array & r) const { return cantCompare(l, r); } |
| 303 | bool operator() (const UInt64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 304 | bool operator() (const UInt64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 305 | |
| 306 | bool operator() (const Int64 & l, const Null & r) const { return cantCompare(l, r); } |
| 307 | bool operator() (const Int64 & l, const UInt64 & r) const { return accurate::lessOp(l, r); } |
| 308 | bool operator() (const Int64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 309 | bool operator() (const Int64 & l, const Int64 & r) const { return l < r; } |
| 310 | bool operator() (const Int64 & l, const Float64 & r) const { return accurate::lessOp(l, r); } |
| 311 | bool operator() (const Int64 & l, const String & r) const { return cantCompare(l, r); } |
| 312 | bool operator() (const Int64 & l, const Array & r) const { return cantCompare(l, r); } |
| 313 | bool operator() (const Int64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 314 | bool operator() (const Int64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 315 | |
| 316 | bool operator() (const Float64 & l, const Null & r) const { return cantCompare(l, r); } |
| 317 | bool operator() (const Float64 & l, const UInt64 & r) const { return accurate::lessOp(l, r); } |
| 318 | bool operator() (const Float64 & l, const UInt128 & r) const { return cantCompare(l, r); } |
| 319 | bool operator() (const Float64 & l, const Int64 & r) const { return accurate::lessOp(l, r); } |
| 320 | bool operator() (const Float64 & l, const Float64 & r) const { return l < r; } |
| 321 | bool operator() (const Float64 & l, const String & r) const { return cantCompare(l, r); } |
| 322 | bool operator() (const Float64 & l, const Array & r) const { return cantCompare(l, r); } |
| 323 | bool operator() (const Float64 & l, const Tuple & r) const { return cantCompare(l, r); } |
| 324 | bool operator() (const Float64 & l, const AggregateFunctionStateData & r) const { return cantCompare(l, r); } |
| 325 | |
| 326 | template <typename T> |
| 327 | bool operator() (const Null &, const T &) const |
| 328 | { |
| 329 | return !std::is_same_v<T, Null>; |
| 330 | } |
| 331 | |
| 332 | template <typename T> |
| 333 | bool operator() (const String & l, const T & r) const |
| 334 | { |
| 335 | if constexpr (std::is_same_v<T, String>) |
| 336 | return l < r; |
| 337 | if constexpr (std::is_same_v<T, UInt128>) |
| 338 | return stringToUUID(l) < r; |
| 339 | return cantCompare(l, r); |
| 340 | } |
| 341 | |
| 342 | template <typename T> |
| 343 | bool operator() (const UInt128 & l, const T & r) const |
| 344 | { |
| 345 | if constexpr (std::is_same_v<T, UInt128>) |
| 346 | return l < r; |
| 347 | if constexpr (std::is_same_v<T, String>) |
| 348 | return l < stringToUUID(r); |
| 349 | return cantCompare(l, r); |
| 350 | } |
| 351 | |
| 352 | template <typename T> |
| 353 | bool operator() (const Array & l, const T & r) const |
| 354 | { |
| 355 | if constexpr (std::is_same_v<T, Array>) |
| 356 | return l < r; |
| 357 | return cantCompare(l, r); |
| 358 | } |
| 359 | |
| 360 | template <typename T> |
| 361 | bool operator() (const Tuple & l, const T & r) const |
| 362 | { |
| 363 | if constexpr (std::is_same_v<T, Tuple>) |
| 364 | return l < r; |
| 365 | return cantCompare(l, r); |
| 366 | } |
| 367 | |
| 368 | template <typename T, typename U> |
| 369 | bool operator() (const DecimalField<T> & l, const U & r) const |
| 370 | { |
| 371 | if constexpr (isDecimalField<U>()) |
| 372 | return l < r; |
| 373 | else if constexpr (std::is_same_v<U, Int64> || std::is_same_v<U, UInt64>) |
| 374 | return l < DecimalField<Decimal128>(r, 0); |
| 375 | return cantCompare(l, r); |
| 376 | } |
| 377 | |
| 378 | template <typename T> bool operator() (const UInt64 & l, const DecimalField<T> & r) const { return DecimalField<Decimal128>(l, 0) < r; } |
| 379 | template <typename T> bool operator() (const Int64 & l, const DecimalField<T> & r) const { return DecimalField<Decimal128>(l, 0) < r; } |
| 380 | template <typename T> bool operator() (const Float64 &, const DecimalField<T> &) const { return false; } |
| 381 | |
| 382 | template <typename T> |
| 383 | bool operator() (const AggregateFunctionStateData & l, const T & r) const |
| 384 | { |
| 385 | return cantCompare(l, r); |
| 386 | } |
| 387 | |
| 388 | private: |
| 389 | template <typename T, typename U> |
| 390 | bool cantCompare(const T &, const U &) const |
| 391 | { |
| 392 | throw Exception("Cannot compare " + demangle(typeid(T).name()) + " with " + demangle(typeid(U).name()), |
| 393 | ErrorCodes::BAD_TYPE_OF_FIELD); |
| 394 | } |
| 395 | }; |
| 396 | |
| 397 | |
| 398 | /** Implements `+=` operation. |
| 399 | * Returns false if the result is zero. |
| 400 | */ |
| 401 | class FieldVisitorSum : public StaticVisitor<bool> |
| 402 | { |
| 403 | private: |
| 404 | const Field & rhs; |
| 405 | public: |
| 406 | explicit FieldVisitorSum(const Field & rhs_) : rhs(rhs_) {} |
| 407 | |
| 408 | // We can add all ints as unsigned regardless of their actual signedness. |
| 409 | bool operator() (Int64 & x) const { return this->operator()(reinterpret_cast<UInt64 &>(x)); } |
| 410 | bool operator() (UInt64 & x) const |
| 411 | { |
| 412 | x += rhs.reinterpret<UInt64>(); |
| 413 | return x != 0; |
| 414 | } |
| 415 | |
| 416 | bool operator() (Float64 & x) const { x += get<Float64>(rhs); return x != 0; } |
| 417 | |
| 418 | bool operator() (Null &) const { throw Exception("Cannot sum Nulls" , ErrorCodes::LOGICAL_ERROR); } |
| 419 | bool operator() (String &) const { throw Exception("Cannot sum Strings" , ErrorCodes::LOGICAL_ERROR); } |
| 420 | bool operator() (Array &) const { throw Exception("Cannot sum Arrays" , ErrorCodes::LOGICAL_ERROR); } |
| 421 | bool operator() (Tuple &) const { throw Exception("Cannot sum Tuples" , ErrorCodes::LOGICAL_ERROR); } |
| 422 | bool operator() (UInt128 &) const { throw Exception("Cannot sum UUIDs" , ErrorCodes::LOGICAL_ERROR); } |
| 423 | bool operator() (AggregateFunctionStateData &) const { throw Exception("Cannot sum AggregateFunctionStates" , ErrorCodes::LOGICAL_ERROR); } |
| 424 | |
| 425 | template <typename T> |
| 426 | bool operator() (DecimalField<T> & x) const |
| 427 | { |
| 428 | x += get<DecimalField<T>>(rhs); |
| 429 | return x.getValue() != 0; |
| 430 | } |
| 431 | }; |
| 432 | |
| 433 | } |
| 434 | |