1#pragma once
2
3#include <Core/Field.h>
4#include <Core/AccurateComparison.h>
5#include <common/demangle.h>
6
7
8class SipHash;
9
10
11namespace DB
12{
13
14namespace 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.
26UInt128 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 */
34template <typename R = void>
35struct 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.
42template <typename Visitor, typename F>
43auto applyVisitor(Visitor && visitor, F && field)
44{
45 return Field::dispatch(visitor, field);
46}
47
48template <typename Visitor, typename F1, typename F2>
49auto 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 */
64class FieldVisitorToString : public StaticVisitor<String>
65{
66public:
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. */
83class FieldVisitorDump : public StaticVisitor<String>
84{
85public:
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. */
102template <typename T>
103class FieldVisitorConvertToNumber : public StaticVisitor<T>
104{
105public:
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 */
152class FieldVisitorHash : public StaticVisitor<>
153{
154private:
155 SipHash & hash;
156public:
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
174template <typename T> constexpr bool isDecimalField() { return false; }
175template <> constexpr bool isDecimalField<DecimalField<Decimal32>>() { return true; }
176template <> constexpr bool isDecimalField<DecimalField<Decimal64>>() { return true; }
177template <> 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 */
184class FieldVisitorAccurateEquals : public StaticVisitor<bool>
185{
186public:
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
281private:
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
293class FieldVisitorAccurateLess : public StaticVisitor<bool>
294{
295public:
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
388private:
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 */
401class FieldVisitorSum : public StaticVisitor<bool>
402{
403private:
404 const Field & rhs;
405public:
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