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 | |