/src/tarantool/src/box/tuple_compare.cc
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright 2010-2016, Tarantool AUTHORS, please see AUTHORS file. |
3 | | * |
4 | | * Redistribution and use in source and binary forms, with or |
5 | | * without modification, are permitted provided that the following |
6 | | * conditions are met: |
7 | | * |
8 | | * 1. Redistributions of source code must retain the above |
9 | | * copyright notice, this list of conditions and the |
10 | | * following disclaimer. |
11 | | * |
12 | | * 2. Redistributions in binary form must reproduce the above |
13 | | * copyright notice, this list of conditions and the following |
14 | | * disclaimer in the documentation and/or other materials |
15 | | * provided with the distribution. |
16 | | * |
17 | | * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND |
18 | | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
19 | | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
20 | | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL |
21 | | * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
22 | | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
23 | | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
24 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
25 | | * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
26 | | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
27 | | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF |
28 | | * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
29 | | * SUCH DAMAGE. |
30 | | */ |
31 | | #include "core/decimal.h" |
32 | | #include "tuple_compare.h" |
33 | | #include "tuple.h" |
34 | | #include "coll/coll.h" |
35 | | #include "trivia/util.h" /* NOINLINE */ |
36 | | #include <math.h> |
37 | | #include "mp_decimal.h" |
38 | | #include "mp_extension_types.h" |
39 | | #include "mp_uuid.h" |
40 | | #include "mp_datetime.h" |
41 | | |
42 | | /* {{{ tuple_compare */ |
43 | | |
44 | | /* |
45 | | * Compare two tuple fields. |
46 | | * Separate version exists since compare is a very |
47 | | * often used operation, so any performance speed up |
48 | | * in it can have dramatic impact on the overall |
49 | | * performance. |
50 | | */ |
51 | | ALWAYS_INLINE int |
52 | | mp_compare_uint(const char **data_a, const char **data_b); |
53 | | |
54 | | enum mp_class { |
55 | | MP_CLASS_NIL = 0, |
56 | | MP_CLASS_BOOL, |
57 | | MP_CLASS_NUMBER, |
58 | | MP_CLASS_STR, |
59 | | MP_CLASS_BIN, |
60 | | MP_CLASS_UUID, |
61 | | MP_CLASS_DATETIME, |
62 | | MP_CLASS_INTERVAL, |
63 | | MP_CLASS_ARRAY, |
64 | | MP_CLASS_MAP, |
65 | | mp_class_max, |
66 | | }; |
67 | | |
68 | | static enum mp_class mp_classes[] = { |
69 | | /* .MP_NIL = */ MP_CLASS_NIL, |
70 | | /* .MP_UINT = */ MP_CLASS_NUMBER, |
71 | | /* .MP_INT = */ MP_CLASS_NUMBER, |
72 | | /* .MP_STR = */ MP_CLASS_STR, |
73 | | /* .MP_BIN = */ MP_CLASS_BIN, |
74 | | /* .MP_ARRAY = */ MP_CLASS_ARRAY, |
75 | | /* .MP_MAP = */ MP_CLASS_MAP, |
76 | | /* .MP_BOOL = */ MP_CLASS_BOOL, |
77 | | /* .MP_FLOAT = */ MP_CLASS_NUMBER, |
78 | | /* .MP_DOUBLE = */ MP_CLASS_NUMBER, |
79 | | /* .MP_EXT = */ mp_class_max, |
80 | | }; |
81 | | |
82 | | static enum mp_class mp_ext_classes[] = { |
83 | | /* .MP_UNKNOWN_EXTENSION = */ mp_class_max, /* unsupported */ |
84 | | /* .MP_DECIMAL = */ MP_CLASS_NUMBER, |
85 | | /* .MP_UUID = */ MP_CLASS_UUID, |
86 | | /* .MP_ERROR = */ mp_class_max, |
87 | | /* .MP_DATETIME = */ MP_CLASS_DATETIME, |
88 | | /* .MP_COMPRESSION = */ mp_class_max, |
89 | | /* .MP_INTERVAL = */ MP_CLASS_INTERVAL, |
90 | | }; |
91 | | |
92 | | static enum mp_class |
93 | | mp_classof(enum mp_type type) |
94 | 0 | { |
95 | 0 | return mp_classes[type]; |
96 | 0 | } |
97 | | |
98 | | static enum mp_class |
99 | | mp_extension_class(const char *data) |
100 | 0 | { |
101 | 0 | assert(mp_typeof(*data) == MP_EXT); |
102 | 0 | int8_t type; |
103 | 0 | mp_decode_extl(&data, &type); |
104 | 0 | assert(type >= 0 && type < mp_extension_type_MAX); |
105 | 0 | return mp_ext_classes[type]; |
106 | 0 | } |
107 | | |
108 | | static int |
109 | | mp_compare_bool(const char *field_a, const char *field_b) |
110 | 0 | { |
111 | 0 | int a_val = mp_decode_bool(&field_a); |
112 | 0 | int b_val = mp_decode_bool(&field_b); |
113 | 0 | return COMPARE_RESULT(a_val, b_val); |
114 | 0 | } |
115 | | |
116 | | static int |
117 | | mp_compare_float32(const char *field_a, const char *field_b) |
118 | 0 | { |
119 | 0 | float a_val = mp_decode_float(&field_a); |
120 | 0 | float b_val = mp_decode_float(&field_b); |
121 | 0 | return COMPARE_RESULT(a_val, b_val); |
122 | 0 | } |
123 | | |
124 | | static int |
125 | | mp_compare_float64(const char *field_a, const char *field_b) |
126 | 0 | { |
127 | 0 | double a_val = mp_decode_double(&field_a); |
128 | 0 | double b_val = mp_decode_double(&field_b); |
129 | 0 | return COMPARE_RESULT(a_val, b_val); |
130 | 0 | } |
131 | | |
132 | | static int |
133 | | mp_compare_integer_with_type(const char *field_a, enum mp_type a_type, |
134 | | const char *field_b, enum mp_type b_type) |
135 | 0 | { |
136 | 0 | assert(mp_classof(a_type) == MP_CLASS_NUMBER); |
137 | 0 | assert(mp_classof(b_type) == MP_CLASS_NUMBER); |
138 | 0 | if (a_type == MP_UINT) { |
139 | 0 | uint64_t a_val = mp_decode_uint(&field_a); |
140 | 0 | if (b_type == MP_UINT) { |
141 | 0 | uint64_t b_val = mp_decode_uint(&field_b); |
142 | 0 | return COMPARE_RESULT(a_val, b_val); |
143 | 0 | } else { |
144 | 0 | int64_t b_val = mp_decode_int(&field_b); |
145 | 0 | if (b_val < 0) |
146 | 0 | return 1; |
147 | 0 | return COMPARE_RESULT(a_val, (uint64_t)b_val); |
148 | 0 | } |
149 | 0 | } else { |
150 | 0 | int64_t a_val = mp_decode_int(&field_a); |
151 | 0 | if (b_type == MP_UINT) { |
152 | 0 | uint64_t b_val = mp_decode_uint(&field_b); |
153 | 0 | if (a_val < 0) |
154 | 0 | return -1; |
155 | 0 | return COMPARE_RESULT((uint64_t)a_val, b_val); |
156 | 0 | } else { |
157 | 0 | int64_t b_val = mp_decode_int(&field_b); |
158 | 0 | return COMPARE_RESULT(a_val, b_val); |
159 | 0 | } |
160 | 0 | } |
161 | 0 | } |
162 | | |
163 | | static int |
164 | | mp_compare_double_any_int(double lhs, const char *rhs, enum mp_type rhs_type, |
165 | | int k) |
166 | 0 | { |
167 | 0 | if (rhs_type == MP_INT) |
168 | 0 | return double_compare_int64(lhs, mp_decode_int(&rhs), k); |
169 | 0 | assert(rhs_type == MP_UINT); |
170 | 0 | return double_compare_uint64(lhs, mp_decode_uint(&rhs), k); |
171 | 0 | } |
172 | | |
173 | | static int |
174 | | mp_compare_double_any_number(double lhs, const char *rhs, |
175 | | enum mp_type rhs_type, int k) |
176 | 0 | { |
177 | 0 | double v; |
178 | 0 | if (rhs_type == MP_FLOAT) |
179 | 0 | v = mp_decode_float(&rhs); |
180 | 0 | else if (rhs_type == MP_DOUBLE) |
181 | 0 | v = mp_decode_double(&rhs); |
182 | 0 | else |
183 | 0 | return mp_compare_double_any_int(lhs, rhs, rhs_type, k); |
184 | 0 | int lhs_is_nan = isnan(lhs); |
185 | 0 | int rhs_is_nan = isnan(v); |
186 | 0 | assert(lhs_is_nan == 1 || lhs_is_nan == 0); |
187 | 0 | assert(rhs_is_nan == 1 || rhs_is_nan == 0); |
188 | 0 | if (lhs_is_nan == 0 && rhs_is_nan == 0) { |
189 | 0 | return k * COMPARE_RESULT(lhs, v); |
190 | 0 | } else if (lhs_is_nan != rhs_is_nan) { |
191 | | /* |
192 | | * lhs | lhs_isNaN | rhs | rhs_isNaN | ret |
193 | | * -------+-----------+--------+-----------+----- |
194 | | * NaN | 1 | number | 0 | -1 |
195 | | * number | 0 | NaN | 1 | 1 |
196 | | */ |
197 | 0 | return k * (rhs_is_nan - lhs_is_nan); |
198 | 0 | } |
199 | | /* |
200 | | * Both NaNs. Compare signaling and quiet NaNs by |
201 | | * 'quiet bit'. |
202 | | */ |
203 | 0 | uint64_t lqbit; |
204 | 0 | memcpy(&lqbit, &lhs, sizeof(lhs)); |
205 | 0 | lqbit &= UINT64_C(0x8000000000000); |
206 | 0 | uint64_t rqbit; |
207 | 0 | memcpy(&rqbit, &v, sizeof(v)); |
208 | 0 | rqbit &= UINT64_C(0x8000000000000); |
209 | | /* |
210 | | * Lets consider the quiet NaN (fraction first bit == 1) |
211 | | * to be bigger than signaling NaN (fraction first |
212 | | * bit == 0). |
213 | | */ |
214 | 0 | return k * COMPARE_RESULT(lqbit, rqbit); |
215 | 0 | } |
216 | | |
217 | | static int |
218 | | mp_compare_decimal(const char *lhs, const char *rhs) |
219 | 0 | { |
220 | 0 | decimal_t lhs_dec, rhs_dec; |
221 | 0 | decimal_t *ret; |
222 | 0 | ret = mp_decode_decimal(&lhs, &lhs_dec); |
223 | 0 | assert(ret != NULL); |
224 | 0 | ret = mp_decode_decimal(&rhs, &rhs_dec); |
225 | 0 | assert(ret != NULL); |
226 | 0 | (void)ret; |
227 | 0 | return decimal_compare(&lhs_dec, &rhs_dec); |
228 | |
|
229 | 0 | } |
230 | | |
231 | | /** |
232 | | * Compare a decimal to something not representable as decimal. Like NaN, Inf or |
233 | | * just a value outside the (-1e38, 1e38) range. In all these cases the decimal |
234 | | * value doesn't matter. |
235 | | */ |
236 | | static inline int |
237 | | decimal_compare_nan_or_huge(double rhs) |
238 | 0 | { |
239 | | /* We assume NaN is less than everything else. */ |
240 | 0 | if (isnan(rhs)) |
241 | 0 | return 1; |
242 | 0 | assert(fabs(rhs) >= 1e38); |
243 | 0 | return (rhs < 0) - (rhs > 0); |
244 | 0 | } |
245 | | |
246 | | static int |
247 | | mp_compare_decimal_any_number(decimal_t *lhs, const char *rhs, |
248 | | enum mp_type rhs_type, int k) |
249 | 0 | { |
250 | 0 | decimal_t rhs_dec; |
251 | 0 | decimal_t *rc; |
252 | 0 | switch (rhs_type) { |
253 | 0 | case MP_FLOAT: |
254 | 0 | { |
255 | 0 | double d = mp_decode_float(&rhs); |
256 | 0 | rc = decimal_from_double(&rhs_dec, d); |
257 | 0 | if (rc == NULL) |
258 | 0 | return decimal_compare_nan_or_huge(d) * k; |
259 | 0 | break; |
260 | 0 | } |
261 | 0 | case MP_DOUBLE: |
262 | 0 | { |
263 | 0 | double d = mp_decode_double(&rhs); |
264 | 0 | rc = decimal_from_double(&rhs_dec, d); |
265 | 0 | if (rc == NULL) |
266 | 0 | return decimal_compare_nan_or_huge(d) * k; |
267 | 0 | break; |
268 | 0 | } |
269 | 0 | case MP_INT: |
270 | 0 | { |
271 | 0 | int64_t num = mp_decode_int(&rhs); |
272 | 0 | rc = decimal_from_int64(&rhs_dec, num); |
273 | 0 | break; |
274 | 0 | } |
275 | 0 | case MP_UINT: |
276 | 0 | { |
277 | 0 | uint64_t num = mp_decode_uint(&rhs); |
278 | 0 | rc = decimal_from_uint64(&rhs_dec, num); |
279 | 0 | break; |
280 | 0 | } |
281 | 0 | case MP_EXT: |
282 | 0 | { |
283 | 0 | int8_t ext_type; |
284 | 0 | uint32_t len = mp_decode_extl(&rhs, &ext_type); |
285 | 0 | switch (ext_type) { |
286 | 0 | case MP_DECIMAL: |
287 | 0 | rc = decimal_unpack(&rhs, len, &rhs_dec); |
288 | 0 | break; |
289 | 0 | default: |
290 | 0 | unreachable(); |
291 | 0 | } |
292 | 0 | break; |
293 | 0 | } |
294 | 0 | default: |
295 | 0 | unreachable(); |
296 | 0 | } |
297 | 0 | assert(rc != NULL); |
298 | 0 | return k * decimal_compare(lhs, &rhs_dec); |
299 | 0 | } |
300 | | |
301 | | static int |
302 | | mp_compare_number_with_type(const char *lhs, enum mp_type lhs_type, |
303 | | const char *rhs, enum mp_type rhs_type) |
304 | 0 | { |
305 | 0 | assert(mp_classof(lhs_type) == MP_CLASS_NUMBER || |
306 | 0 | mp_extension_class(lhs) == MP_CLASS_NUMBER); |
307 | 0 | assert(mp_classof(rhs_type) == MP_CLASS_NUMBER || |
308 | 0 | mp_extension_class(rhs) == MP_CLASS_NUMBER); |
309 | | |
310 | | /* |
311 | | * Test decimals first, so that we don't have to |
312 | | * account for them in other comparators. |
313 | | */ |
314 | 0 | decimal_t dec; |
315 | 0 | if (rhs_type == MP_EXT) { |
316 | 0 | int8_t ext_type; |
317 | 0 | uint32_t len = mp_decode_extl(&rhs, &ext_type); |
318 | 0 | switch (ext_type) { |
319 | 0 | case MP_DECIMAL: |
320 | 0 | return mp_compare_decimal_any_number( |
321 | 0 | decimal_unpack(&rhs, len, &dec), lhs, lhs_type, -1 |
322 | 0 | ); |
323 | 0 | default: |
324 | 0 | unreachable(); |
325 | 0 | } |
326 | 0 | } |
327 | 0 | if (lhs_type == MP_EXT) { |
328 | 0 | int8_t ext_type; |
329 | 0 | uint32_t len = mp_decode_extl(&lhs, &ext_type); |
330 | 0 | switch (ext_type) { |
331 | 0 | case MP_DECIMAL: |
332 | 0 | return mp_compare_decimal_any_number( |
333 | 0 | decimal_unpack(&lhs, len, &dec), rhs, rhs_type, 1 |
334 | 0 | ); |
335 | 0 | default: |
336 | 0 | unreachable(); |
337 | 0 | } |
338 | 0 | } |
339 | 0 | if (rhs_type == MP_FLOAT) { |
340 | 0 | return mp_compare_double_any_number( |
341 | 0 | mp_decode_float(&rhs), lhs, lhs_type, -1 |
342 | 0 | ); |
343 | 0 | } |
344 | 0 | if (rhs_type == MP_DOUBLE) { |
345 | 0 | return mp_compare_double_any_number( |
346 | 0 | mp_decode_double(&rhs), lhs, lhs_type, -1 |
347 | 0 | ); |
348 | 0 | } |
349 | 0 | assert(rhs_type == MP_INT || rhs_type == MP_UINT); |
350 | 0 | if (lhs_type == MP_FLOAT) { |
351 | 0 | return mp_compare_double_any_int( |
352 | 0 | mp_decode_float(&lhs), rhs, rhs_type, 1 |
353 | 0 | ); |
354 | 0 | } |
355 | 0 | if (lhs_type == MP_DOUBLE) { |
356 | 0 | return mp_compare_double_any_int( |
357 | 0 | mp_decode_double(&lhs), rhs, rhs_type, 1 |
358 | 0 | ); |
359 | 0 | } |
360 | 0 | assert(lhs_type == MP_INT || lhs_type == MP_UINT); |
361 | 0 | return mp_compare_integer_with_type(lhs, lhs_type, rhs, rhs_type); |
362 | 0 | } |
363 | | |
364 | | static inline int |
365 | | mp_compare_number(const char *lhs, const char *rhs) |
366 | 0 | { |
367 | 0 | return mp_compare_number_with_type(lhs, mp_typeof(*lhs), |
368 | 0 | rhs, mp_typeof(*rhs)); |
369 | 0 | } |
370 | | |
371 | | static inline int |
372 | | mp_compare_str(const char *field_a, const char *field_b) |
373 | 0 | { |
374 | 0 | uint32_t size_a = mp_decode_strl(&field_a); |
375 | 0 | uint32_t size_b = mp_decode_strl(&field_b); |
376 | 0 | int r = memcmp(field_a, field_b, MIN(size_a, size_b)); |
377 | 0 | if (r != 0) |
378 | 0 | return r; |
379 | 0 | return COMPARE_RESULT(size_a, size_b); |
380 | 0 | } |
381 | | |
382 | | static inline int |
383 | | mp_compare_str_coll(const char *field_a, const char *field_b, struct coll *coll) |
384 | 0 | { |
385 | 0 | uint32_t size_a = mp_decode_strl(&field_a); |
386 | 0 | uint32_t size_b = mp_decode_strl(&field_b); |
387 | 0 | return coll->cmp(field_a, size_a, field_b, size_b, coll); |
388 | 0 | } |
389 | | |
390 | | static inline int |
391 | | mp_compare_bin(const char *field_a, const char *field_b) |
392 | 0 | { |
393 | 0 | uint32_t size_a = mp_decode_binl(&field_a); |
394 | 0 | uint32_t size_b = mp_decode_binl(&field_b); |
395 | 0 | int r = memcmp(field_a, field_b, MIN(size_a, size_b)); |
396 | 0 | if (r != 0) |
397 | 0 | return r; |
398 | 0 | return COMPARE_RESULT(size_a, size_b); |
399 | 0 | } |
400 | | |
401 | | static inline int |
402 | | mp_compare_uuid(const char *field_a, const char *field_b) |
403 | 0 | { |
404 | | /* |
405 | | * Packed uuid fields are in the right order for |
406 | | * comparison and are big-endian, so memcmp is |
407 | | * the same as tt_uuid_compare() and lets us |
408 | | * spare 2 mp_uuid_unpack() calls. |
409 | | * "field_a + 2" to skip the uuid header. |
410 | | */ |
411 | 0 | return memcmp(field_a + 2, field_b + 2, UUID_PACKED_LEN); |
412 | 0 | } |
413 | | |
414 | | static int |
415 | | mp_compare_datetime(const char *lhs, const char *rhs) |
416 | 0 | { |
417 | 0 | struct datetime lhs_dt, rhs_dt; |
418 | 0 | struct datetime *ret; |
419 | 0 | ret = mp_decode_datetime(&lhs, &lhs_dt); |
420 | 0 | assert(ret != NULL); |
421 | 0 | ret = mp_decode_datetime(&rhs, &rhs_dt); |
422 | 0 | assert(ret != NULL); |
423 | 0 | (void)ret; |
424 | 0 | return datetime_compare(&lhs_dt, &rhs_dt); |
425 | 0 | } |
426 | | |
427 | | typedef int (*mp_compare_f)(const char *, const char *); |
428 | | static mp_compare_f mp_class_comparators[] = { |
429 | | /* .MP_CLASS_NIL = */ NULL, |
430 | | /* .MP_CLASS_BOOL = */ mp_compare_bool, |
431 | | /* .MP_CLASS_NUMBER = */ mp_compare_number, |
432 | | /* .MP_CLASS_STR = */ mp_compare_str, |
433 | | /* .MP_CLASS_BIN = */ mp_compare_bin, |
434 | | /* .MP_CLASS_UUID = */ mp_compare_uuid, |
435 | | /* .MP_CLASS_DATETIME=*/ mp_compare_datetime, |
436 | | /* .MP_CLASS_INTERVAL=*/ NULL, |
437 | | /* .MP_CLASS_ARRAY = */ NULL, |
438 | | /* .MP_CLASS_MAP = */ NULL, |
439 | | }; |
440 | | |
441 | | static int |
442 | | mp_compare_scalar_with_type(const char *field_a, enum mp_type a_type, |
443 | | const char *field_b, enum mp_type b_type) |
444 | 0 | { |
445 | 0 | enum mp_class a_class = mp_classof(a_type) < mp_class_max ? |
446 | 0 | mp_classof(a_type) : |
447 | 0 | mp_extension_class(field_a); |
448 | 0 | enum mp_class b_class = mp_classof(b_type) < mp_class_max ? |
449 | 0 | mp_classof(b_type) : |
450 | 0 | mp_extension_class(field_b); |
451 | 0 | if (a_class != b_class) |
452 | 0 | return COMPARE_RESULT(a_class, b_class); |
453 | 0 | mp_compare_f cmp = mp_class_comparators[a_class]; |
454 | 0 | assert(cmp != NULL); |
455 | 0 | return cmp(field_a, field_b); |
456 | 0 | } |
457 | | |
458 | | static inline int |
459 | | mp_compare_scalar(const char *field_a, const char *field_b) |
460 | 0 | { |
461 | 0 | return mp_compare_scalar_with_type(field_a, mp_typeof(*field_a), |
462 | 0 | field_b, mp_typeof(*field_b)); |
463 | 0 | } |
464 | | |
465 | | static inline int |
466 | | mp_compare_scalar_coll(const char *field_a, const char *field_b, |
467 | | struct coll *coll) |
468 | 0 | { |
469 | 0 | enum mp_type type_a = mp_typeof(*field_a); |
470 | 0 | enum mp_type type_b = mp_typeof(*field_b); |
471 | 0 | if (type_a == MP_STR && type_b == MP_STR) |
472 | 0 | return mp_compare_str_coll(field_a, field_b, coll); |
473 | 0 | return mp_compare_scalar_with_type(field_a, type_a, field_b, type_b); |
474 | 0 | } |
475 | | |
476 | | /** |
477 | | * @brief Compare two fields parts using a type definition |
478 | | * @param field_a field |
479 | | * @param field_b field |
480 | | * @param field_type field type definition |
481 | | * @retval 0 if field_a == field_b |
482 | | * @retval <0 if field_a < field_b |
483 | | * @retval >0 if field_a > field_b |
484 | | */ |
485 | | int |
486 | | tuple_compare_field(const char *field_a, const char *field_b, |
487 | | int8_t type, struct coll *coll) |
488 | 0 | { |
489 | 0 | switch (type) { |
490 | 0 | case FIELD_TYPE_UNSIGNED: |
491 | 0 | case FIELD_TYPE_UINT8: |
492 | 0 | case FIELD_TYPE_UINT16: |
493 | 0 | case FIELD_TYPE_UINT32: |
494 | 0 | case FIELD_TYPE_UINT64: |
495 | 0 | return mp_compare_uint(field_a, field_b); |
496 | 0 | case FIELD_TYPE_STRING: |
497 | 0 | return coll != NULL ? |
498 | 0 | mp_compare_str_coll(field_a, field_b, coll) : |
499 | 0 | mp_compare_str(field_a, field_b); |
500 | 0 | case FIELD_TYPE_INTEGER: |
501 | 0 | case FIELD_TYPE_INT8: |
502 | 0 | case FIELD_TYPE_INT16: |
503 | 0 | case FIELD_TYPE_INT32: |
504 | 0 | case FIELD_TYPE_INT64: |
505 | 0 | return mp_compare_integer_with_type(field_a, |
506 | 0 | mp_typeof(*field_a), |
507 | 0 | field_b, |
508 | 0 | mp_typeof(*field_b)); |
509 | 0 | case FIELD_TYPE_NUMBER: |
510 | 0 | case FIELD_TYPE_DOUBLE: |
511 | 0 | return mp_compare_number(field_a, field_b); |
512 | 0 | case FIELD_TYPE_FLOAT32: |
513 | 0 | return mp_compare_float32(field_a, field_b); |
514 | 0 | case FIELD_TYPE_FLOAT64: |
515 | 0 | return mp_compare_float64(field_a, field_b); |
516 | 0 | case FIELD_TYPE_BOOLEAN: |
517 | 0 | return mp_compare_bool(field_a, field_b); |
518 | 0 | case FIELD_TYPE_VARBINARY: |
519 | 0 | return mp_compare_bin(field_a, field_b); |
520 | 0 | case FIELD_TYPE_SCALAR: |
521 | 0 | return coll != NULL ? |
522 | 0 | mp_compare_scalar_coll(field_a, field_b, coll) : |
523 | 0 | mp_compare_scalar(field_a, field_b); |
524 | 0 | case FIELD_TYPE_DECIMAL: |
525 | 0 | case FIELD_TYPE_DECIMAL32: |
526 | 0 | case FIELD_TYPE_DECIMAL64: |
527 | 0 | case FIELD_TYPE_DECIMAL128: |
528 | 0 | case FIELD_TYPE_DECIMAL256: |
529 | 0 | return mp_compare_decimal(field_a, field_b); |
530 | 0 | case FIELD_TYPE_UUID: |
531 | 0 | return mp_compare_uuid(field_a, field_b); |
532 | 0 | case FIELD_TYPE_DATETIME: |
533 | 0 | return mp_compare_datetime(field_a, field_b); |
534 | 0 | default: |
535 | 0 | unreachable(); |
536 | 0 | return 0; |
537 | 0 | } |
538 | 0 | } |
539 | | |
540 | | static int |
541 | | tuple_compare_field_with_type(const char *field_a, enum mp_type a_type, |
542 | | const char *field_b, enum mp_type b_type, |
543 | | int8_t type, struct coll *coll) |
544 | 0 | { |
545 | 0 | switch (type) { |
546 | 0 | case FIELD_TYPE_UNSIGNED: |
547 | 0 | case FIELD_TYPE_UINT8: |
548 | 0 | case FIELD_TYPE_UINT16: |
549 | 0 | case FIELD_TYPE_UINT32: |
550 | 0 | case FIELD_TYPE_UINT64: |
551 | 0 | return mp_compare_uint(field_a, field_b); |
552 | 0 | case FIELD_TYPE_STRING: |
553 | 0 | return coll != NULL ? |
554 | 0 | mp_compare_str_coll(field_a, field_b, coll) : |
555 | 0 | mp_compare_str(field_a, field_b); |
556 | 0 | case FIELD_TYPE_INTEGER: |
557 | 0 | case FIELD_TYPE_INT8: |
558 | 0 | case FIELD_TYPE_INT16: |
559 | 0 | case FIELD_TYPE_INT32: |
560 | 0 | case FIELD_TYPE_INT64: |
561 | 0 | return mp_compare_integer_with_type(field_a, a_type, |
562 | 0 | field_b, b_type); |
563 | 0 | case FIELD_TYPE_NUMBER: |
564 | 0 | case FIELD_TYPE_DOUBLE: |
565 | 0 | return mp_compare_number_with_type(field_a, a_type, |
566 | 0 | field_b, b_type); |
567 | 0 | case FIELD_TYPE_FLOAT32: |
568 | 0 | return mp_compare_float32(field_a, field_b); |
569 | 0 | case FIELD_TYPE_FLOAT64: |
570 | 0 | return mp_compare_float64(field_a, field_b); |
571 | 0 | case FIELD_TYPE_BOOLEAN: |
572 | 0 | return mp_compare_bool(field_a, field_b); |
573 | 0 | case FIELD_TYPE_VARBINARY: |
574 | 0 | return mp_compare_bin(field_a, field_b); |
575 | 0 | case FIELD_TYPE_SCALAR: |
576 | 0 | return coll != NULL ? |
577 | 0 | mp_compare_scalar_coll(field_a, field_b, coll) : |
578 | 0 | mp_compare_scalar_with_type(field_a, a_type, |
579 | 0 | field_b, b_type); |
580 | 0 | case FIELD_TYPE_DECIMAL: |
581 | 0 | case FIELD_TYPE_DECIMAL32: |
582 | 0 | case FIELD_TYPE_DECIMAL64: |
583 | 0 | case FIELD_TYPE_DECIMAL128: |
584 | 0 | case FIELD_TYPE_DECIMAL256: |
585 | 0 | return mp_compare_number_with_type(field_a, a_type, |
586 | 0 | field_b, b_type); |
587 | 0 | case FIELD_TYPE_UUID: |
588 | 0 | return mp_compare_uuid(field_a, field_b); |
589 | 0 | case FIELD_TYPE_DATETIME: |
590 | 0 | return mp_compare_datetime(field_a, field_b); |
591 | 0 | default: |
592 | 0 | unreachable(); |
593 | 0 | return 0; |
594 | 0 | } |
595 | 0 | } |
596 | | |
597 | | /* |
598 | | * Reverse the compare result if the key part sort order is descending. |
599 | | */ |
600 | | template<bool has_desc_parts> |
601 | | static inline int |
602 | | key_part_compare_result(struct key_part *part, int result) |
603 | 0 | { |
604 | 0 | bool is_asc = !has_desc_parts || part->sort_order != SORT_ORDER_DESC; |
605 | 0 | return result * (is_asc ? 1 : -1); |
606 | 0 | } Unexecuted instantiation: tuple_compare.cc:int key_part_compare_result<false>(key_part*, int) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_result<true>(key_part*, int) |
607 | | |
608 | | /* |
609 | | * Reverse the hint if the key part sort order is descending. |
610 | | */ |
611 | | template<bool has_desc_parts> |
612 | | static inline hint_t |
613 | | key_part_hint(struct key_part *part, hint_t hint) |
614 | 0 | { |
615 | 0 | bool is_asc = !has_desc_parts || part->sort_order != SORT_ORDER_DESC; |
616 | | /* HINT_MAX - HINT_NONE underflows to HINT_NONE. */ |
617 | 0 | return is_asc ? hint : HINT_MAX - hint; |
618 | 0 | } Unexecuted instantiation: tuple_compare.cc:unsigned long key_part_hint<true>(key_part*, unsigned long) Unexecuted instantiation: tuple_compare.cc:unsigned long key_part_hint<false>(key_part*, unsigned long) |
619 | | |
620 | | /* |
621 | | * Implements the field comparison logic. If the key we use is not nullable |
622 | | * then a simple call to tuple_compare_field is used. |
623 | | * |
624 | | * Otherwise one of \p field_a and \p field_b can be NIL: either it's encoded |
625 | | * as MP_NIL or if the field is absent (corresponding field pointer equals to |
626 | | * NULL). In this case we perform comparison so that NIL is lesser than any |
627 | | * value but two NILs are equal. |
628 | | * |
629 | | * The template parameters a_is_optional and b_is_optional specify if the |
630 | | * corresponding field arguments can be absent (equal to NULL). |
631 | | * |
632 | | * If \p was_null_met is not NULL, sets the boolean pointed by it to true if |
633 | | * any of \p field_a and \p field_b is absent or NIL. Othervice the pointed |
634 | | * value is not modified. |
635 | | * |
636 | | * This code had been deduplicated, so made the function always_inline in |
637 | | * order to make sure it's still inlined after refactoring. |
638 | | * |
639 | | * @param part the key part we compare |
640 | | * @param field_a the field to compare |
641 | | * @param field_b the field to compare against |
642 | | * @param was_null_met pointer to the value to set to true if a NIL is met, |
643 | | * can be set to NULL if the information isn't required |
644 | | * @retval 0 if field_a == field_b |
645 | | * @retval <0 if field_a < field_b |
646 | | * @retval >0 if field_a > field_b |
647 | | */ |
648 | | template<bool is_nullable, bool a_is_optional, bool b_is_optional, |
649 | | bool has_desc_parts> |
650 | | static ALWAYS_INLINE int |
651 | | key_part_compare_fields(struct key_part *part, const char *field_a, |
652 | | const char *field_b, bool *was_null_met = NULL) |
653 | 0 | { |
654 | 0 | int rc; |
655 | 0 | if (!is_nullable) { |
656 | 0 | rc = tuple_compare_field(field_a, field_b, |
657 | 0 | part->type, part->coll); |
658 | 0 | return key_part_compare_result<has_desc_parts>(part, rc); |
659 | 0 | } |
660 | 0 | enum mp_type a_type = (a_is_optional && field_a == NULL) ? |
661 | 0 | MP_NIL : mp_typeof(*field_a); |
662 | 0 | enum mp_type b_type = (b_is_optional && field_b == NULL) ? |
663 | 0 | MP_NIL : mp_typeof(*field_b); |
664 | 0 | bool a_is_value = a_type != MP_NIL; |
665 | 0 | bool b_is_value = b_type != MP_NIL; |
666 | 0 | if (!a_is_value || !b_is_value) { |
667 | 0 | if (was_null_met != NULL) |
668 | 0 | *was_null_met = true; |
669 | 0 | rc = a_is_value - b_is_value; |
670 | 0 | } else { |
671 | 0 | rc = tuple_compare_field_with_type(field_a, a_type, |
672 | 0 | field_b, b_type, |
673 | 0 | part->type, part->coll); |
674 | 0 | } |
675 | 0 | return key_part_compare_result<has_desc_parts>(part, rc); |
676 | 0 | } Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<false, false, false, false>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<false, false, false, true>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, false, false, true>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, false, false, false>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, true, true, true>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, true, false, true>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, true, true, false>(key_part*, char const*, char const*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_part_compare_fields<true, true, false, false>(key_part*, char const*, char const*, bool*) |
677 | | |
678 | | template<bool is_nullable, bool has_optional_parts, bool has_json_paths, |
679 | | bool is_multikey, bool has_desc_parts> |
680 | | static inline int |
681 | | tuple_compare_slowpath(struct tuple *tuple_a, hint_t tuple_a_hint, |
682 | | struct tuple *tuple_b, hint_t tuple_b_hint, |
683 | | struct key_def *key_def) |
684 | 0 | { |
685 | 0 | assert(has_json_paths == key_def->has_json_paths); |
686 | 0 | assert(!has_optional_parts || is_nullable); |
687 | 0 | assert(is_nullable == key_def->is_nullable); |
688 | 0 | assert(has_optional_parts == key_def->has_optional_parts); |
689 | 0 | assert(key_def->is_multikey == is_multikey); |
690 | 0 | assert(!is_multikey || (tuple_a_hint != HINT_NONE && |
691 | 0 | tuple_b_hint != HINT_NONE)); |
692 | 0 | int rc = 0; |
693 | 0 | if (!is_multikey && (rc = hint_cmp(tuple_a_hint, tuple_b_hint)) != 0) |
694 | 0 | return rc; |
695 | 0 | bool was_null_met = false; |
696 | 0 | struct key_part *part = key_def->parts; |
697 | 0 | const char *tuple_a_raw = tuple_data(tuple_a); |
698 | 0 | const char *tuple_b_raw = tuple_data(tuple_b); |
699 | 0 | struct tuple_format *format_a = tuple_format(tuple_a); |
700 | 0 | struct tuple_format *format_b = tuple_format(tuple_b); |
701 | 0 | const uint32_t *field_map_a = tuple_field_map(tuple_a); |
702 | 0 | const uint32_t *field_map_b = tuple_field_map(tuple_b); |
703 | 0 | struct key_part *end; |
704 | 0 | const char *field_a, *field_b; |
705 | 0 | if (is_nullable) |
706 | 0 | end = part + key_def->unique_part_count; |
707 | 0 | else |
708 | 0 | end = part + key_def->part_count; |
709 | |
|
710 | 0 | for (; part < end; part++) { |
711 | 0 | if (is_multikey) { |
712 | 0 | field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, |
713 | 0 | field_map_a, part, |
714 | 0 | (int)tuple_a_hint); |
715 | 0 | field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, |
716 | 0 | field_map_b, part, |
717 | 0 | (int)tuple_b_hint); |
718 | 0 | } else if (has_json_paths) { |
719 | 0 | field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, |
720 | 0 | field_map_a, part, |
721 | 0 | MULTIKEY_NONE); |
722 | 0 | field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, |
723 | 0 | field_map_b, part, |
724 | 0 | MULTIKEY_NONE); |
725 | 0 | } else { |
726 | 0 | field_a = tuple_field_raw(format_a, tuple_a_raw, |
727 | 0 | field_map_a, part->fieldno); |
728 | 0 | field_b = tuple_field_raw(format_b, tuple_b_raw, |
729 | 0 | field_map_b, part->fieldno); |
730 | 0 | } |
731 | 0 | assert(has_optional_parts || |
732 | 0 | (field_a != NULL && field_b != NULL)); |
733 | 0 | rc = key_part_compare_fields<is_nullable, has_optional_parts, |
734 | 0 | has_optional_parts, |
735 | 0 | has_desc_parts>( |
736 | 0 | part, field_a, field_b, &was_null_met); |
737 | 0 | if (rc != 0) |
738 | 0 | return rc; |
739 | 0 | } |
740 | | /* |
741 | | * Do not use full parts set when no NULLs. It allows to |
742 | | * simulate a NULL != NULL logic in secondary keys, |
743 | | * because in them full parts set contains unique primary |
744 | | * key. |
745 | | */ |
746 | 0 | if (!is_nullable || !was_null_met) |
747 | 0 | return 0; |
748 | | /* |
749 | | * Index parts are equal and contain NULLs. So use |
750 | | * extended parts only. |
751 | | */ |
752 | 0 | end = key_def->parts + key_def->part_count; |
753 | 0 | for (; part < end; ++part) { |
754 | 0 | if (is_multikey) { |
755 | 0 | field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, |
756 | 0 | field_map_a, part, |
757 | 0 | (int)tuple_a_hint); |
758 | 0 | field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, |
759 | 0 | field_map_b, part, |
760 | 0 | (int)tuple_b_hint); |
761 | 0 | } else if (has_json_paths) { |
762 | 0 | field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, |
763 | 0 | field_map_a, part, |
764 | 0 | MULTIKEY_NONE); |
765 | 0 | field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, |
766 | 0 | field_map_b, part, |
767 | 0 | MULTIKEY_NONE); |
768 | 0 | } else { |
769 | 0 | field_a = tuple_field_raw(format_a, tuple_a_raw, |
770 | 0 | field_map_a, part->fieldno); |
771 | 0 | field_b = tuple_field_raw(format_b, tuple_b_raw, |
772 | 0 | field_map_b, part->fieldno); |
773 | 0 | } |
774 | | /* |
775 | | * Extended parts are primary, and they can not |
776 | | * be absent or be NULLs. |
777 | | */ |
778 | 0 | assert(field_a != NULL && field_b != NULL); |
779 | 0 | rc = key_part_compare_fields<false, false, false, |
780 | 0 | has_desc_parts>( |
781 | 0 | part, field_a, field_b); |
782 | 0 | if (rc != 0) |
783 | 0 | return rc; |
784 | 0 | } |
785 | 0 | return 0; |
786 | 0 | } Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, false, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, false, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, false, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, false, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, false, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, false, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, true, true, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, true, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, true, true, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, true, true, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, true, true, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, true, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, true, true, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<true, false, true, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, true, true, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, true, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, true, true, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_slowpath<false, false, true, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) |
787 | | |
788 | | template<bool is_nullable, bool has_optional_parts, bool has_json_paths, |
789 | | bool is_multikey, bool has_desc_parts> |
790 | | static inline int |
791 | | tuple_compare_with_key_slowpath(struct tuple *tuple, hint_t tuple_hint, |
792 | | const char *key, uint32_t part_count, |
793 | | hint_t key_hint, struct key_def *key_def) |
794 | 0 | { |
795 | 0 | assert(has_json_paths == key_def->has_json_paths); |
796 | 0 | assert(!has_optional_parts || is_nullable); |
797 | 0 | assert(is_nullable == key_def->is_nullable); |
798 | 0 | assert(has_optional_parts == key_def->has_optional_parts); |
799 | 0 | assert(key != NULL || part_count == 0); |
800 | 0 | assert(part_count <= key_def->part_count); |
801 | 0 | assert(key_def->is_multikey == is_multikey); |
802 | 0 | assert(!is_multikey || (tuple_hint != HINT_NONE && |
803 | 0 | key_hint == HINT_NONE)); |
804 | 0 | int rc = 0; |
805 | 0 | if (!is_multikey && (rc = hint_cmp(tuple_hint, key_hint)) != 0) |
806 | 0 | return rc; |
807 | 0 | struct key_part *part = key_def->parts; |
808 | 0 | struct tuple_format *format = tuple_format(tuple); |
809 | 0 | const char *tuple_raw = tuple_data(tuple); |
810 | 0 | const uint32_t *field_map = tuple_field_map(tuple); |
811 | 0 | if (likely(part_count == 1)) { |
812 | 0 | const char *field; |
813 | 0 | if (is_multikey) { |
814 | 0 | field = tuple_field_raw_by_part(format, tuple_raw, |
815 | 0 | field_map, part, |
816 | 0 | (int)tuple_hint); |
817 | 0 | } else if (has_json_paths) { |
818 | 0 | field = tuple_field_raw_by_part(format, tuple_raw, |
819 | 0 | field_map, part, |
820 | 0 | MULTIKEY_NONE); |
821 | 0 | } else { |
822 | 0 | field = tuple_field_raw(format, tuple_raw, field_map, |
823 | 0 | part->fieldno); |
824 | 0 | } |
825 | 0 | return key_part_compare_fields<is_nullable, has_optional_parts, |
826 | 0 | false, has_desc_parts>( |
827 | 0 | part, field, key); |
828 | 0 | } |
829 | | |
830 | 0 | struct key_part *end = part + part_count; |
831 | 0 | for (; part < end; ++part, mp_next(&key)) { |
832 | 0 | const char *field; |
833 | 0 | if (is_multikey) { |
834 | 0 | field = tuple_field_raw_by_part(format, tuple_raw, |
835 | 0 | field_map, part, |
836 | 0 | (int)tuple_hint); |
837 | 0 | } else if (has_json_paths) { |
838 | 0 | field = tuple_field_raw_by_part(format, tuple_raw, |
839 | 0 | field_map, part, |
840 | 0 | MULTIKEY_NONE); |
841 | 0 | } else { |
842 | 0 | field = tuple_field_raw(format, tuple_raw, field_map, |
843 | 0 | part->fieldno); |
844 | 0 | } |
845 | 0 | rc = key_part_compare_fields<is_nullable, has_optional_parts, |
846 | 0 | false, has_desc_parts>( |
847 | 0 | part, field, key); |
848 | 0 | if (rc != 0) |
849 | 0 | return rc; |
850 | 0 | } |
851 | 0 | return 0; |
852 | 0 | } Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, false, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, false, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, false, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, false, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, false, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, false, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, true, true, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, true, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, true, true, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, true, true, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, true, true, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, true, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, true, true, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<true, false, true, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, true, true, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, true, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, true, true, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_slowpath<false, false, true, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) |
853 | | |
854 | | /** |
855 | | * Compare key parts and skip compared equally. After function call, keys |
856 | | * will point to the first field that differ or to the end of key or |
857 | | * part_count + 1 field in order. |
858 | | * Key arguments must not be NULL, allowed to be NULL if dereferenced. |
859 | | * Set was_null_met to true if at least one part is NULL, to false otherwise. |
860 | | */ |
861 | | template<bool is_nullable, bool has_desc_parts> |
862 | | static inline int |
863 | | key_compare_and_skip_parts(const char **key_a, const char **key_b, |
864 | | uint32_t part_count, struct key_def *key_def, |
865 | | bool *was_null_met) |
866 | 0 | { |
867 | 0 | assert(is_nullable == key_def->is_nullable); |
868 | 0 | assert(key_a != NULL && key_b != NULL); |
869 | 0 | assert((*key_a != NULL && *key_b != NULL) || part_count == 0); |
870 | 0 | struct key_part *part = key_def->parts; |
871 | 0 | int rc; |
872 | 0 | *was_null_met = false; |
873 | |
|
874 | 0 | if (likely(part_count == 1)) { |
875 | 0 | rc = key_part_compare_fields<is_nullable, false, false, |
876 | 0 | has_desc_parts>( |
877 | 0 | part, *key_a, *key_b, was_null_met); |
878 | | /* If key parts are equals, we must skip them. */ |
879 | 0 | if (rc == 0) { |
880 | 0 | mp_next(key_a); |
881 | 0 | mp_next(key_b); |
882 | 0 | } |
883 | 0 | return rc; |
884 | 0 | } |
885 | | |
886 | 0 | struct key_part *end = part + part_count; |
887 | 0 | for (; part < end; ++part, mp_next(key_a), mp_next(key_b)) { |
888 | 0 | rc = key_part_compare_fields<is_nullable, false, false, |
889 | 0 | has_desc_parts>( |
890 | 0 | part, *key_a, *key_b, was_null_met); |
891 | 0 | if (rc != 0) |
892 | 0 | return rc; |
893 | 0 | } |
894 | 0 | return 0; |
895 | 0 | } Unexecuted instantiation: tuple_compare.cc:int key_compare_and_skip_parts<false, false>(char const**, char const**, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_and_skip_parts<false, true>(char const**, char const**, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_and_skip_parts<true, true>(char const**, char const**, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_and_skip_parts<true, false>(char const**, char const**, unsigned int, key_def*, bool*) |
896 | | |
897 | | template<bool is_nullable, bool has_desc_parts> |
898 | | static inline int |
899 | | key_compare_parts(const char *key_a, const char *key_b, uint32_t part_count, |
900 | | struct key_def *key_def, bool *was_null_met) |
901 | 0 | { |
902 | 0 | return key_compare_and_skip_parts<is_nullable, has_desc_parts>( |
903 | 0 | &key_a, &key_b, part_count, key_def, was_null_met); |
904 | 0 | } Unexecuted instantiation: tuple_compare.cc:int key_compare_parts<false, true>(char const*, char const*, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_parts<false, false>(char const*, char const*, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_parts<true, true>(char const*, char const*, unsigned int, key_def*, bool*) Unexecuted instantiation: tuple_compare.cc:int key_compare_parts<true, false>(char const*, char const*, unsigned int, key_def*, bool*) |
905 | | |
906 | | template<bool is_nullable, bool has_optional_parts, bool has_desc_parts> |
907 | | static inline int |
908 | | tuple_compare_with_key_sequential(struct tuple *tuple, hint_t tuple_hint, |
909 | | const char *key, uint32_t part_count, |
910 | | hint_t key_hint, struct key_def *key_def) |
911 | 0 | { |
912 | 0 | assert(!has_optional_parts || is_nullable); |
913 | 0 | assert(key_def_is_sequential(key_def)); |
914 | 0 | assert(is_nullable == key_def->is_nullable); |
915 | 0 | assert(has_optional_parts == key_def->has_optional_parts); |
916 | 0 | int rc = hint_cmp(tuple_hint, key_hint); |
917 | 0 | if (rc != 0) |
918 | 0 | return rc; |
919 | 0 | const char *tuple_key = tuple_data(tuple); |
920 | 0 | uint32_t field_count = mp_decode_array(&tuple_key); |
921 | 0 | uint32_t cmp_part_count; |
922 | 0 | if (has_optional_parts && field_count < part_count) { |
923 | 0 | cmp_part_count = field_count; |
924 | 0 | } else { |
925 | 0 | assert(field_count >= part_count); |
926 | 0 | cmp_part_count = part_count; |
927 | 0 | } |
928 | 0 | bool unused; |
929 | 0 | rc = key_compare_and_skip_parts<is_nullable, has_desc_parts>( |
930 | 0 | &tuple_key, &key, cmp_part_count, key_def, &unused); |
931 | 0 | if (!has_optional_parts || rc != 0) |
932 | 0 | return rc; |
933 | | /* |
934 | | * If some tuple indexed fields are absent, then check |
935 | | * corresponding key fields to be equal to NULL. |
936 | | */ |
937 | 0 | if (field_count < part_count) { |
938 | 0 | for (uint32_t i = field_count; i < part_count; |
939 | 0 | ++i, mp_next(&key)) { |
940 | 0 | rc = key_part_compare_fields<true, true, false, |
941 | 0 | has_desc_parts>( |
942 | 0 | &key_def->parts[i], NULL, key); |
943 | 0 | if (rc != 0) |
944 | 0 | return rc; |
945 | 0 | } |
946 | 0 | } |
947 | 0 | return 0; |
948 | 0 | } Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<false, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<true, true, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<true, true, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<true, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<true, false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_with_key_sequential<false, false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) |
949 | | |
950 | | int |
951 | | key_compare(const char *key_a, uint32_t part_count_a, hint_t key_a_hint, |
952 | | const char *key_b, uint32_t part_count_b, hint_t key_b_hint, |
953 | | struct key_def *key_def) |
954 | 0 | { |
955 | 0 | int rc = hint_cmp(key_a_hint, key_b_hint); |
956 | 0 | if (rc != 0) |
957 | 0 | return rc; |
958 | 0 | assert(part_count_a <= key_def->part_count); |
959 | 0 | assert(part_count_b <= key_def->part_count); |
960 | 0 | uint32_t part_count = MIN(part_count_a, part_count_b); |
961 | 0 | assert(part_count <= key_def->part_count); |
962 | 0 | bool unused; |
963 | 0 | if (! key_def->is_nullable) { |
964 | 0 | if (key_def_has_desc_parts(key_def)) { |
965 | 0 | return key_compare_parts<false, true>( |
966 | 0 | key_a, key_b, part_count, key_def, &unused); |
967 | 0 | } else { |
968 | 0 | return key_compare_parts<false, false>( |
969 | 0 | key_a, key_b, part_count, key_def, &unused); |
970 | 0 | } |
971 | 0 | } else { |
972 | 0 | if (key_def_has_desc_parts(key_def)) { |
973 | 0 | return key_compare_parts<true, true>( |
974 | 0 | key_a, key_b, part_count, key_def, &unused); |
975 | 0 | } else { |
976 | 0 | return key_compare_parts<true, false>( |
977 | 0 | key_a, key_b, part_count, key_def, &unused); |
978 | 0 | } |
979 | 0 | } |
980 | 0 | } |
981 | | |
982 | | template<bool is_nullable, bool has_optional_parts, bool has_desc_parts> |
983 | | static int |
984 | | tuple_compare_sequential(struct tuple *tuple_a, hint_t tuple_a_hint, |
985 | | struct tuple *tuple_b, hint_t tuple_b_hint, |
986 | | struct key_def *key_def) |
987 | 0 | { |
988 | 0 | assert(!has_optional_parts || is_nullable); |
989 | 0 | assert(has_optional_parts == key_def->has_optional_parts); |
990 | 0 | assert(key_def_is_sequential(key_def)); |
991 | 0 | assert(is_nullable == key_def->is_nullable); |
992 | 0 | int rc = hint_cmp(tuple_a_hint, tuple_b_hint); |
993 | 0 | if (rc != 0) |
994 | 0 | return rc; |
995 | 0 | const char *key_a = tuple_data(tuple_a); |
996 | 0 | uint32_t fc_a = mp_decode_array(&key_a); |
997 | 0 | const char *key_b = tuple_data(tuple_b); |
998 | 0 | uint32_t fc_b = mp_decode_array(&key_b); |
999 | 0 | if (!has_optional_parts && !is_nullable) { |
1000 | 0 | assert(fc_a >= key_def->part_count); |
1001 | 0 | assert(fc_b >= key_def->part_count); |
1002 | 0 | bool unused; |
1003 | 0 | return key_compare_parts<false, has_desc_parts>( |
1004 | 0 | key_a, key_b, key_def->part_count, key_def, &unused); |
1005 | 0 | } |
1006 | 0 | bool was_null_met = false; |
1007 | 0 | struct key_part *part = key_def->parts; |
1008 | 0 | struct key_part *end = part + key_def->unique_part_count; |
1009 | 0 | uint32_t i = 0; |
1010 | 0 | for (const char *field_a, *field_b; part < end; ++part, ++i) { |
1011 | 0 | field_a = (has_optional_parts && i >= fc_a) ? NULL : key_a; |
1012 | 0 | field_b = (has_optional_parts && i >= fc_b) ? NULL : key_b; |
1013 | 0 | rc = key_part_compare_fields<true, has_optional_parts, |
1014 | 0 | has_optional_parts, |
1015 | 0 | has_desc_parts>( |
1016 | 0 | part, field_a, field_b, &was_null_met); |
1017 | 0 | if (rc != 0) |
1018 | 0 | return rc; |
1019 | 0 | if (!has_optional_parts || i < fc_a) |
1020 | 0 | mp_next(&key_a); |
1021 | 0 | if (!has_optional_parts || i < fc_b) |
1022 | 0 | mp_next(&key_b); |
1023 | 0 | } |
1024 | 0 | if (! was_null_met) |
1025 | 0 | return 0; |
1026 | 0 | end = key_def->parts + key_def->part_count; |
1027 | 0 | for (; part < end; ++part, ++i, mp_next(&key_a), mp_next(&key_b)) { |
1028 | | /* |
1029 | | * If tuples are equal by unique_part_count, then |
1030 | | * the rest of parts are a primary key, which can |
1031 | | * not be absent or be null. |
1032 | | */ |
1033 | 0 | assert(i < fc_a && i < fc_b); |
1034 | 0 | rc = key_part_compare_fields<false, false, false, |
1035 | 0 | has_desc_parts>( |
1036 | 0 | part, key_a, key_b); |
1037 | 0 | if (rc != 0) |
1038 | 0 | return rc; |
1039 | 0 | } |
1040 | 0 | return 0; |
1041 | 0 | } Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<false, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<true, true, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<true, true, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<true, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<true, false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int tuple_compare_sequential<false, false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) |
1042 | | |
1043 | | template <int TYPE> |
1044 | | static inline int |
1045 | | field_compare(const char **field_a, const char **field_b); |
1046 | | |
1047 | | template <> |
1048 | | inline int |
1049 | | field_compare<FIELD_TYPE_UNSIGNED>(const char **field_a, const char **field_b) |
1050 | 0 | { |
1051 | 0 | return mp_compare_uint(*field_a, *field_b); |
1052 | 0 | } |
1053 | | |
1054 | | template <> |
1055 | | inline int |
1056 | | field_compare<FIELD_TYPE_STRING>(const char **field_a, const char **field_b) |
1057 | 0 | { |
1058 | 0 | uint32_t size_a, size_b; |
1059 | 0 | size_a = mp_decode_strl(field_a); |
1060 | 0 | size_b = mp_decode_strl(field_b); |
1061 | 0 | int r = memcmp(*field_a, *field_b, MIN(size_a, size_b)); |
1062 | 0 | if (r == 0) |
1063 | 0 | r = size_a < size_b ? -1 : size_a > size_b; |
1064 | 0 | return r; |
1065 | 0 | } |
1066 | | |
1067 | | template <int TYPE> |
1068 | | static inline int |
1069 | | field_compare_and_next(const char **field_a, const char **field_b); |
1070 | | |
1071 | | template <> |
1072 | | inline int |
1073 | | field_compare_and_next<FIELD_TYPE_UNSIGNED>(const char **field_a, |
1074 | | const char **field_b) |
1075 | 0 | { |
1076 | 0 | int r = mp_compare_uint(*field_a, *field_b); |
1077 | 0 | mp_next(field_a); |
1078 | 0 | mp_next(field_b); |
1079 | 0 | return r; |
1080 | 0 | } |
1081 | | |
1082 | | template <> |
1083 | | inline int |
1084 | | field_compare_and_next<FIELD_TYPE_STRING>(const char **field_a, |
1085 | | const char **field_b) |
1086 | 0 | { |
1087 | 0 | uint32_t size_a, size_b; |
1088 | 0 | size_a = mp_decode_strl(field_a); |
1089 | 0 | size_b = mp_decode_strl(field_b); |
1090 | 0 | int r = memcmp(*field_a, *field_b, MIN(size_a, size_b)); |
1091 | 0 | if (r == 0) |
1092 | 0 | r = size_a < size_b ? -1 : size_a > size_b; |
1093 | 0 | *field_a += size_a; |
1094 | 0 | *field_b += size_b; |
1095 | 0 | return r; |
1096 | 0 | } |
1097 | | |
1098 | | /* Tuple comparator */ |
1099 | | namespace /* local symbols */ { |
1100 | | |
1101 | | template <int IDX, int TYPE, int ...MORE_TYPES> struct FieldCompare { }; |
1102 | | |
1103 | | /** |
1104 | | * Common case. |
1105 | | */ |
1106 | | template <int IDX, int TYPE, int IDX2, int TYPE2, int ...MORE_TYPES> |
1107 | | struct FieldCompare<IDX, TYPE, IDX2, TYPE2, MORE_TYPES...> |
1108 | | { |
1109 | | inline static int compare(struct tuple *tuple_a, |
1110 | | struct tuple *tuple_b, |
1111 | | struct tuple_format *format_a, |
1112 | | struct tuple_format *format_b, |
1113 | | const char *field_a, |
1114 | | const char *field_b) |
1115 | 0 | { |
1116 | 0 | int r; |
1117 | | /* static if */ |
1118 | 0 | if (IDX + 1 == IDX2) { |
1119 | 0 | if ((r = field_compare_and_next<TYPE>(&field_a, |
1120 | 0 | &field_b)) != 0) |
1121 | 0 | return r; |
1122 | 0 | } else { |
1123 | 0 | if ((r = field_compare<TYPE>(&field_a, &field_b)) != 0) |
1124 | 0 | return r; |
1125 | 0 | field_a = tuple_field_raw(format_a, tuple_data(tuple_a), |
1126 | 0 | tuple_field_map(tuple_a), |
1127 | 0 | IDX2); |
1128 | 0 | field_b = tuple_field_raw(format_b, tuple_data(tuple_b), |
1129 | 0 | tuple_field_map(tuple_b), |
1130 | 0 | IDX2); |
1131 | 0 | } |
1132 | 0 | return FieldCompare<IDX2, TYPE2, MORE_TYPES...>:: |
1133 | 0 | compare(tuple_a, tuple_b, format_a, |
1134 | 0 | format_b, field_a, field_b); |
1135 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 1, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 1, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 1, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 2, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 2, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 2, 2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 1, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 1, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 1, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1, 1, 2, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 2, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2, 1, 2, 2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) |
1136 | | }; |
1137 | | |
1138 | | template <int IDX, int TYPE> |
1139 | | struct FieldCompare<IDX, TYPE> |
1140 | | { |
1141 | | inline static int compare(struct tuple *, |
1142 | | struct tuple *, |
1143 | | struct tuple_format *, |
1144 | | struct tuple_format *, |
1145 | | const char *field_a, |
1146 | | const char *field_b) |
1147 | 0 | { |
1148 | 0 | return field_compare<TYPE>(&field_a, &field_b); |
1149 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<0, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<1, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<2, 1>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompare<2, 2>::compare(tuple*, tuple*, tuple_format*, tuple_format*, char const*, char const*) |
1150 | | }; |
1151 | | |
1152 | | /** |
1153 | | * header |
1154 | | */ |
1155 | | template <int IDX, int TYPE, int ...MORE_TYPES> |
1156 | | struct TupleCompare |
1157 | | { |
1158 | | static int compare(struct tuple *tuple_a, hint_t tuple_a_hint, |
1159 | | struct tuple *tuple_b, hint_t tuple_b_hint, |
1160 | | struct key_def *) |
1161 | | { |
1162 | | int rc = hint_cmp(tuple_a_hint, tuple_b_hint); |
1163 | | if (rc != 0) |
1164 | | return rc; |
1165 | | struct tuple_format *format_a = tuple_format(tuple_a); |
1166 | | struct tuple_format *format_b = tuple_format(tuple_b); |
1167 | | const char *field_a, *field_b; |
1168 | | field_a = tuple_field_raw(format_a, tuple_data(tuple_a), |
1169 | | tuple_field_map(tuple_a), IDX); |
1170 | | field_b = tuple_field_raw(format_b, tuple_data(tuple_b), |
1171 | | tuple_field_map(tuple_b), IDX); |
1172 | | return FieldCompare<IDX, TYPE, MORE_TYPES...>:: |
1173 | | compare(tuple_a, tuple_b, format_a, |
1174 | | format_b, field_a, field_b); |
1175 | | } |
1176 | | }; |
1177 | | |
1178 | | template <int TYPE, int ...MORE_TYPES> |
1179 | | struct TupleCompare<0, TYPE, MORE_TYPES...> { |
1180 | | static int compare(struct tuple *tuple_a, hint_t tuple_a_hint, |
1181 | | struct tuple *tuple_b, hint_t tuple_b_hint, |
1182 | | struct key_def *) |
1183 | 0 | { |
1184 | 0 | int rc = hint_cmp(tuple_a_hint, tuple_b_hint); |
1185 | 0 | if (rc != 0) |
1186 | 0 | return rc; |
1187 | 0 | struct tuple_format *format_a = tuple_format(tuple_a); |
1188 | 0 | struct tuple_format *format_b = tuple_format(tuple_b); |
1189 | 0 | const char *field_a = tuple_data(tuple_a); |
1190 | 0 | const char *field_b = tuple_data(tuple_b); |
1191 | 0 | mp_decode_array(&field_a); |
1192 | 0 | mp_decode_array(&field_b); |
1193 | 0 | return FieldCompare<0, TYPE, MORE_TYPES...>::compare(tuple_a, tuple_b, |
1194 | 0 | format_a, format_b, field_a, field_b); |
1195 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 1, 2, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 1, 2, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 2, 2, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 2, 2, 1>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 1, 2, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 1, 2, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 1, 1, 2, 2, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompare<0, 2, 1, 2, 2, 2>::compare(tuple*, unsigned long, tuple*, unsigned long, key_def*) |
1196 | | }; |
1197 | | } /* end of anonymous namespace */ |
1198 | | |
1199 | | struct comparator_signature { |
1200 | | tuple_compare_t f; |
1201 | | uint32_t p[64]; |
1202 | | }; |
1203 | | #define COMPARATOR(...) \ |
1204 | | { TupleCompare<__VA_ARGS__>::compare, { __VA_ARGS__, UINT32_MAX } }, |
1205 | | |
1206 | | /** |
1207 | | * field1 no, field1 type, field2 no, field2 type, ... |
1208 | | */ |
1209 | | static const comparator_signature cmp_arr[] = { |
1210 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED) |
1211 | | COMPARATOR(0, FIELD_TYPE_STRING) |
1212 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED) |
1213 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED) |
1214 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING) |
1215 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_STRING) |
1216 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) |
1217 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) |
1218 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) |
1219 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) |
1220 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_STRING) |
1221 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_STRING) |
1222 | | COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) |
1223 | | COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) |
1224 | | }; |
1225 | | |
1226 | | #undef COMPARATOR |
1227 | | |
1228 | | /* }}} tuple_compare */ |
1229 | | |
1230 | | /* {{{ tuple_compare_with_key */ |
1231 | | |
1232 | | template <int TYPE> |
1233 | | static inline int field_compare_with_key(const char **field, const char **key); |
1234 | | |
1235 | | template <> |
1236 | | inline int |
1237 | | field_compare_with_key<FIELD_TYPE_UNSIGNED>(const char **field, const char **key) |
1238 | 0 | { |
1239 | 0 | return mp_compare_uint(*field, *key); |
1240 | 0 | } |
1241 | | |
1242 | | template <> |
1243 | | inline int |
1244 | | field_compare_with_key<FIELD_TYPE_STRING>(const char **field, const char **key) |
1245 | 0 | { |
1246 | 0 | uint32_t size_a, size_b; |
1247 | 0 | size_a = mp_decode_strl(field); |
1248 | 0 | size_b = mp_decode_strl(key); |
1249 | 0 | int r = memcmp(*field, *key, MIN(size_a, size_b)); |
1250 | 0 | if (r == 0) |
1251 | 0 | r = size_a < size_b ? -1 : size_a > size_b; |
1252 | 0 | return r; |
1253 | 0 | } |
1254 | | |
1255 | | template <int TYPE> |
1256 | | static inline int |
1257 | | field_compare_with_key_and_next(const char **field_a, const char **field_b); |
1258 | | |
1259 | | template <> |
1260 | | inline int |
1261 | | field_compare_with_key_and_next<FIELD_TYPE_UNSIGNED>(const char **field_a, |
1262 | | const char **field_b) |
1263 | 0 | { |
1264 | 0 | int r = mp_compare_uint(*field_a, *field_b); |
1265 | 0 | mp_next(field_a); |
1266 | 0 | mp_next(field_b); |
1267 | 0 | return r; |
1268 | 0 | } |
1269 | | |
1270 | | template <> |
1271 | | inline int |
1272 | | field_compare_with_key_and_next<FIELD_TYPE_STRING>(const char **field_a, |
1273 | | const char **field_b) |
1274 | 0 | { |
1275 | 0 | uint32_t size_a, size_b; |
1276 | 0 | size_a = mp_decode_strl(field_a); |
1277 | 0 | size_b = mp_decode_strl(field_b); |
1278 | 0 | int r = memcmp(*field_a, *field_b, MIN(size_a, size_b)); |
1279 | 0 | if (r == 0) |
1280 | 0 | r = size_a < size_b ? -1 : size_a > size_b; |
1281 | 0 | *field_a += size_a; |
1282 | 0 | *field_b += size_b; |
1283 | 0 | return r; |
1284 | 0 | } |
1285 | | |
1286 | | /* Tuple with key comparator */ |
1287 | | namespace /* local symbols */ { |
1288 | | |
1289 | | template <int FLD_ID, int IDX, int TYPE, int ...MORE_TYPES> |
1290 | | struct FieldCompareWithKey {}; |
1291 | | /** |
1292 | | * common |
1293 | | */ |
1294 | | template <int FLD_ID, int IDX, int TYPE, int IDX2, int TYPE2, int ...MORE_TYPES> |
1295 | | struct FieldCompareWithKey<FLD_ID, IDX, TYPE, IDX2, TYPE2, MORE_TYPES...> |
1296 | | { |
1297 | | inline static int |
1298 | | compare(struct tuple *tuple, const char *key, uint32_t part_count, |
1299 | | struct key_def *key_def, struct tuple_format *format, |
1300 | | const char *field) |
1301 | 0 | { |
1302 | 0 | int r; |
1303 | | /* static if */ |
1304 | 0 | if (IDX + 1 == IDX2) { |
1305 | 0 | r = field_compare_with_key_and_next<TYPE>(&field, &key); |
1306 | 0 | if (r || part_count == FLD_ID + 1) |
1307 | 0 | return r; |
1308 | 0 | } else { |
1309 | 0 | r = field_compare_with_key<TYPE>(&field, &key); |
1310 | 0 | if (r || part_count == FLD_ID + 1) |
1311 | 0 | return r; |
1312 | 0 | field = tuple_field_raw(format, tuple_data(tuple), |
1313 | 0 | tuple_field_map(tuple), IDX2); |
1314 | 0 | mp_next(&key); |
1315 | 0 | } |
1316 | 0 | return FieldCompareWithKey<FLD_ID + 1, IDX2, TYPE2, MORE_TYPES...>:: |
1317 | 0 | compare(tuple, key, part_count, |
1318 | 0 | key_def, format, field); |
1319 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 1, 1, 1, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 1, 1, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 2, 1, 1, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 1, 1, 2, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 1, 2, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 2, 1, 2, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 1, 1, 1, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 1, 1, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 2, 1, 1, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 1, 1, 2, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 1, 2, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 0, 2, 1, 2, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 1, 1, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 1, 2, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 1, 1, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<0, 1, 2, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) |
1320 | | }; |
1321 | | |
1322 | | template <int FLD_ID, int IDX, int TYPE> |
1323 | | struct FieldCompareWithKey<FLD_ID, IDX, TYPE> { |
1324 | | inline static int compare(struct tuple *, |
1325 | | const char *key, |
1326 | | uint32_t, |
1327 | | struct key_def *, |
1328 | | struct tuple_format *, |
1329 | | const char *field) |
1330 | 0 | { |
1331 | 0 | return field_compare_with_key<TYPE>(&field, &key); |
1332 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<2, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<2, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 2, 1>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::FieldCompareWithKey<1, 2, 2>::compare(tuple*, char const*, unsigned int, key_def*, tuple_format*, char const*) |
1333 | | }; |
1334 | | |
1335 | | /** |
1336 | | * header |
1337 | | */ |
1338 | | template <int FLD_ID, int IDX, int TYPE, int ...MORE_TYPES> |
1339 | | struct TupleCompareWithKey |
1340 | | { |
1341 | | static int |
1342 | | compare(struct tuple *tuple, hint_t tuple_hint, |
1343 | | const char *key, uint32_t part_count, |
1344 | | hint_t key_hint, struct key_def *key_def) |
1345 | 0 | { |
1346 | | /* Part count can be 0 in wildcard searches. */ |
1347 | 0 | if (part_count == 0) |
1348 | 0 | return 0; |
1349 | 0 | int rc = hint_cmp(tuple_hint, key_hint); |
1350 | 0 | if (rc != 0) |
1351 | 0 | return rc; |
1352 | 0 | struct tuple_format *format = tuple_format(tuple); |
1353 | 0 | const char *field = tuple_field_raw(format, tuple_data(tuple), |
1354 | 0 | tuple_field_map(tuple), |
1355 | 0 | IDX); |
1356 | 0 | return FieldCompareWithKey<FLD_ID, IDX, TYPE, MORE_TYPES...>:: |
1357 | 0 | compare(tuple, key, part_count, |
1358 | 0 | key_def, format, field); |
1359 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 1, 1, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 1, 2, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 1, 1, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 1, 2, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) |
1360 | | }; |
1361 | | |
1362 | | template <int TYPE, int ...MORE_TYPES> |
1363 | | struct TupleCompareWithKey<0, 0, TYPE, MORE_TYPES...> |
1364 | | { |
1365 | | static int compare(struct tuple *tuple, hint_t tuple_hint, |
1366 | | const char *key, uint32_t part_count, |
1367 | | hint_t key_hint, struct key_def *key_def) |
1368 | 0 | { |
1369 | | /* Part count can be 0 in wildcard searches. */ |
1370 | 0 | if (part_count == 0) |
1371 | 0 | return 0; |
1372 | 0 | int rc = hint_cmp(tuple_hint, key_hint); |
1373 | 0 | if (rc != 0) |
1374 | 0 | return rc; |
1375 | 0 | struct tuple_format *format = tuple_format(tuple); |
1376 | 0 | const char *field = tuple_data(tuple); |
1377 | 0 | mp_decode_array(&field); |
1378 | 0 | return FieldCompareWithKey<0, 0, TYPE, MORE_TYPES...>:: |
1379 | 0 | compare(tuple, key, part_count, |
1380 | 0 | key_def, format, field); |
1381 | 0 | } Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 1, 1, 1, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 2, 1, 1, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 1, 1, 2, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 2, 1, 2, 2, 1>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 1, 1, 1, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 2, 1, 1, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 1, 1, 2, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:(anonymous namespace)::TupleCompareWithKey<0, 0, 2, 1, 2, 2, 2>::compare(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) |
1382 | | }; |
1383 | | |
1384 | | } /* end of anonymous namespace */ |
1385 | | |
1386 | | struct comparator_with_key_signature |
1387 | | { |
1388 | | tuple_compare_with_key_t f; |
1389 | | uint32_t p[64]; |
1390 | | }; |
1391 | | |
1392 | | #define KEY_COMPARATOR(...) \ |
1393 | | { TupleCompareWithKey<0, __VA_ARGS__>::compare, { __VA_ARGS__ } }, |
1394 | | |
1395 | | static const comparator_with_key_signature cmp_wk_arr[] = { |
1396 | | KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) |
1397 | | KEY_COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) |
1398 | | KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) |
1399 | | KEY_COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) |
1400 | | KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_STRING) |
1401 | | KEY_COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_STRING) |
1402 | | KEY_COMPARATOR(0, FIELD_TYPE_UNSIGNED, 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) |
1403 | | KEY_COMPARATOR(0, FIELD_TYPE_STRING , 1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) |
1404 | | |
1405 | | KEY_COMPARATOR(1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_UNSIGNED) |
1406 | | KEY_COMPARATOR(1, FIELD_TYPE_STRING , 2, FIELD_TYPE_UNSIGNED) |
1407 | | KEY_COMPARATOR(1, FIELD_TYPE_UNSIGNED, 2, FIELD_TYPE_STRING) |
1408 | | KEY_COMPARATOR(1, FIELD_TYPE_STRING , 2, FIELD_TYPE_STRING) |
1409 | | }; |
1410 | | |
1411 | | #undef KEY_COMPARATOR |
1412 | | |
1413 | | /** |
1414 | | * A functional index tuple compare. |
1415 | | * tuple_a_hint and tuple_b_hint are expected to be valid pointers to functional |
1416 | | * key memory. These keys are represented as a MsgPack array with the number of |
1417 | | * elements equal to the functional index definition part_count (let's denote |
1418 | | * it as func_index_part_count). The keys have been already validated by |
1419 | | * key_list_iterator_next(). |
1420 | | * |
1421 | | * In case of unique non-nullable index, the non-extended key_def is used as a |
1422 | | * cmp_def (see memtx_tree_index_new_tpl()). Otherwise, the extended cmp_def has |
1423 | | * part_count > func_index_part_count, since it was produced by key_def_merge() |
1424 | | * of the functional key part and the primary key. So its tail parts are taken |
1425 | | * from primary index key definition. |
1426 | | */ |
1427 | | template<bool is_nullable, bool has_desc_parts> |
1428 | | static inline int |
1429 | | func_index_compare(struct tuple *tuple_a, hint_t tuple_a_hint, |
1430 | | struct tuple *tuple_b, hint_t tuple_b_hint, |
1431 | | struct key_def *cmp_def) |
1432 | 0 | { |
1433 | 0 | assert(cmp_def->for_func_index); |
1434 | 0 | assert(is_nullable == cmp_def->is_nullable); |
1435 | | |
1436 | 0 | const char *key_a = tuple_data((struct tuple *)tuple_a_hint); |
1437 | 0 | const char *key_b = tuple_data((struct tuple *)tuple_b_hint); |
1438 | 0 | assert(mp_typeof(*key_a) == MP_ARRAY); |
1439 | 0 | uint32_t part_count_a = mp_decode_array(&key_a); |
1440 | 0 | assert(mp_typeof(*key_b) == MP_ARRAY); |
1441 | 0 | uint32_t part_count_b = mp_decode_array(&key_b); |
1442 | 0 | assert(part_count_a == part_count_b); |
1443 | 0 | uint32_t key_part_count = part_count_a; |
1444 | 0 | (void)part_count_b; |
1445 | |
|
1446 | 0 | bool was_null_met; |
1447 | 0 | int rc = key_compare_parts<is_nullable, has_desc_parts>( |
1448 | 0 | key_a, key_b, key_part_count, cmp_def, &was_null_met); |
1449 | 0 | if (rc != 0) |
1450 | 0 | return rc; |
1451 | | /* |
1452 | | * Tuples with nullified fields may violate the uniqueness constraint |
1453 | | * so if we encountered a nullified field while comparing the secondary |
1454 | | * key parts we must proceed with comparing the primary key parts even |
1455 | | * if the secondary index is unique. |
1456 | | */ |
1457 | 0 | if (key_part_count == cmp_def->unique_part_count && |
1458 | 0 | (!is_nullable || !was_null_met)) |
1459 | 0 | return 0; |
1460 | | /* |
1461 | | * Primary index definition key compare. |
1462 | | * It cannot contain nullable parts so the code is |
1463 | | * simplified correspondingly. |
1464 | | */ |
1465 | 0 | const char *tuple_a_raw = tuple_data(tuple_a); |
1466 | 0 | const char *tuple_b_raw = tuple_data(tuple_b); |
1467 | 0 | struct tuple_format *format_a = tuple_format(tuple_a); |
1468 | 0 | struct tuple_format *format_b = tuple_format(tuple_b); |
1469 | 0 | const uint32_t *field_map_a = tuple_field_map(tuple_a); |
1470 | 0 | const uint32_t *field_map_b = tuple_field_map(tuple_b); |
1471 | 0 | const char *field_a, *field_b; |
1472 | 0 | for (uint32_t i = key_part_count; i < cmp_def->part_count; i++) { |
1473 | 0 | struct key_part *part = &cmp_def->parts[i]; |
1474 | 0 | field_a = tuple_field_raw_by_part(format_a, tuple_a_raw, |
1475 | 0 | field_map_a, part, |
1476 | 0 | MULTIKEY_NONE); |
1477 | 0 | field_b = tuple_field_raw_by_part(format_b, tuple_b_raw, |
1478 | 0 | field_map_b, part, |
1479 | 0 | MULTIKEY_NONE); |
1480 | 0 | assert(field_a != NULL && field_b != NULL); |
1481 | 0 | rc = key_part_compare_fields<false, false, false, |
1482 | 0 | has_desc_parts>( |
1483 | 0 | part, field_a, field_b); |
1484 | 0 | if (rc != 0) |
1485 | 0 | return rc; |
1486 | 0 | } |
1487 | 0 | return 0; |
1488 | 0 | } Unexecuted instantiation: tuple_compare.cc:int func_index_compare<true, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare<true, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare<false, true>(tuple*, unsigned long, tuple*, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare<false, false>(tuple*, unsigned long, tuple*, unsigned long, key_def*) |
1489 | | |
1490 | | /** |
1491 | | * A functional index key compare. |
1492 | | * tuple_hint is expected to be a valid pointer to |
1493 | | * functional key memory and is compared with the given key by |
1494 | | * using the functional index key definition. |
1495 | | */ |
1496 | | template<bool is_nullable, bool has_desc_parts> |
1497 | | static inline int |
1498 | | func_index_compare_with_key(struct tuple *tuple, hint_t tuple_hint, |
1499 | | const char *key, uint32_t part_count, |
1500 | | hint_t key_hint, struct key_def *key_def) |
1501 | 0 | { |
1502 | 0 | (void)key_hint; |
1503 | 0 | assert(key_def->for_func_index); |
1504 | 0 | assert(is_nullable == key_def->is_nullable); |
1505 | 0 | const char *tuple_key = tuple_data((struct tuple *)tuple_hint); |
1506 | 0 | assert(mp_typeof(*tuple_key) == MP_ARRAY); |
1507 | | |
1508 | 0 | uint32_t tuple_key_count = mp_decode_array(&tuple_key); |
1509 | 0 | uint32_t cmp_part_count = MIN(part_count, tuple_key_count); |
1510 | 0 | cmp_part_count = MIN(cmp_part_count, key_def->part_count); |
1511 | 0 | bool unused; |
1512 | 0 | int rc = key_compare_and_skip_parts<is_nullable, has_desc_parts>( |
1513 | 0 | &tuple_key, &key, cmp_part_count, key_def, &unused); |
1514 | 0 | if (rc != 0) |
1515 | 0 | return rc; |
1516 | | /* Equals if nothing to compare. */ |
1517 | 0 | if (part_count == cmp_part_count || |
1518 | 0 | key_def->part_count == cmp_part_count) |
1519 | 0 | return 0; |
1520 | | /* |
1521 | | * Now we know that tuple_key count is less than key part_count |
1522 | | * and key_def part_count, so let's keep comparing, but with |
1523 | | * original tuple fields. We will compare parts of primary key, |
1524 | | * it cannot contain nullable parts so the code is simplified |
1525 | | * correspondingly. Also, all the key parts, corresponding to |
1526 | | * func key, were already skipped. |
1527 | | */ |
1528 | 0 | const char *tuple_raw = tuple_data(tuple); |
1529 | 0 | struct tuple_format *format = tuple_format(tuple); |
1530 | 0 | const uint32_t *field_map = tuple_field_map(tuple); |
1531 | 0 | const char *field; |
1532 | 0 | part_count = MIN(part_count, key_def->part_count); |
1533 | 0 | for (uint32_t i = cmp_part_count; i < part_count; i++) { |
1534 | 0 | struct key_part *part = &key_def->parts[i]; |
1535 | 0 | field = tuple_field_raw_by_part(format, tuple_raw, field_map, |
1536 | 0 | part, MULTIKEY_NONE); |
1537 | 0 | assert(field != NULL); |
1538 | 0 | rc = key_part_compare_fields<false, false, false, |
1539 | 0 | has_desc_parts>( |
1540 | 0 | part, field, key); |
1541 | 0 | mp_next(&key); |
1542 | 0 | if (rc != 0) |
1543 | 0 | return rc; |
1544 | 0 | } |
1545 | 0 | return 0; |
1546 | 0 | } Unexecuted instantiation: tuple_compare.cc:int func_index_compare_with_key<true, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare_with_key<true, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare_with_key<false, true>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) Unexecuted instantiation: tuple_compare.cc:int func_index_compare_with_key<false, false>(tuple*, unsigned long, char const*, unsigned int, unsigned long, key_def*) |
1547 | | |
1548 | | /* }}} tuple_compare_with_key */ |
1549 | | |
1550 | | /* {{{ tuple_hint */ |
1551 | | |
1552 | | /** |
1553 | | * A comparison hint is an unsigned integer number that has |
1554 | | * the following layout: |
1555 | | * |
1556 | | * [ class | value ] |
1557 | | * <-- HINT_CLASS_BITS --> <-- HINT_VALUE_BITS --> |
1558 | | * <----------------- HINT_BITS -----------------> |
1559 | | * |
1560 | | * For simplicity we construct it using the first key part only; |
1561 | | * other key parts don't participate in hint construction. As a |
1562 | | * consequence, tuple hints are useless if the first key part |
1563 | | * doesn't differ among indexed tuples. |
1564 | | * |
1565 | | * Hint class stores one of mp_class enum values corresponding |
1566 | | * to the field type. We store it in upper bits of a hint so |
1567 | | * as to guarantee that tuple fields that have different types |
1568 | | * are compared correctly in a scalar index. We use the same |
1569 | | * layout for indexes of base types too so that we don't need |
1570 | | * to recalculate hints when altering an index from scalar to |
1571 | | * one of base types or vice versa without index rebuild. |
1572 | | * |
1573 | | * Hint value is stored in lower bits of a hint and chosen so |
1574 | | * as to satisfy the hint property (see the comment to hint_t). |
1575 | | * Also, hint values must be compatible among all kinds of numbers |
1576 | | * (integer, unsigned, floating point) so that we can alter an |
1577 | | * index between any two of them without touching the hints. |
1578 | | * |
1579 | | * The value depends on the field type: |
1580 | | * |
1581 | | * - For an integer field, the hint value equals the number |
1582 | | * stored in the field minus the minimal (negative) integer |
1583 | | * number that fits in a hint. If the number is too large |
1584 | | * or too small to fit in a hint, we use the max or the min |
1585 | | * number that fits. This guarantees correct order for all |
1586 | | * positive and negative integers. |
1587 | | * |
1588 | | * - For a field storing a floating point number, we use |
1589 | | * the hint computed for the integral part. This ensures |
1590 | | * compatibility between floating point and integer field |
1591 | | * hints. |
1592 | | * |
1593 | | * - For a boolean field, the hint value is simply 0 or 1. |
1594 | | * |
1595 | | * - For a string field, we take the first few characters that |
1596 | | * fit in a hint and shift them in such a way that comparing |
1597 | | * them is equivalent to strcmp(). If there's a collation, |
1598 | | * we use the sort key instead of the string (see coll->hint). |
1599 | | * |
1600 | | * - For a field containing NULL, the value is 0, and we rely on |
1601 | | * mp_class comparison rules for arranging nullable fields. |
1602 | | * |
1603 | | * Note: comparison hint only makes sense for non-multikey |
1604 | | * indexes. |
1605 | | */ |
1606 | 0 | #define HINT_BITS (sizeof(hint_t) * CHAR_BIT) |
1607 | 0 | #define HINT_CLASS_BITS 4 |
1608 | 0 | #define HINT_VALUE_BITS (HINT_BITS - HINT_CLASS_BITS) |
1609 | | |
1610 | | /** Number of bytes that fit in a hint value. */ |
1611 | 0 | #define HINT_VALUE_BYTES (HINT_VALUE_BITS / CHAR_BIT) |
1612 | | |
1613 | | /** Max unsigned integer that can be stored in a hint value. */ |
1614 | 0 | #define HINT_VALUE_MAX ((1ULL << HINT_VALUE_BITS) - 1) |
1615 | | |
1616 | | /** |
1617 | | * Max and min signed integer numbers that fit in a hint value. |
1618 | | * For numbers > MAX and < MIN we store MAX and MIN, respectively. |
1619 | | */ |
1620 | 0 | #define HINT_VALUE_INT_MAX ((1LL << (HINT_VALUE_BITS - 1)) - 1) |
1621 | 0 | #define HINT_VALUE_INT_MIN (-(1LL << (HINT_VALUE_BITS - 1))) |
1622 | | |
1623 | | /** |
1624 | | * Max and min floating point numbers whose integral parts fit |
1625 | | * in a hint value. Note, we can't compare a floating point number |
1626 | | * with HINT_VALUE_INT_{MIN,MAX} because of rounding errors. |
1627 | | */ |
1628 | 0 | #define HINT_VALUE_DOUBLE_MAX (exp2(HINT_VALUE_BITS - 1) - 1) |
1629 | 0 | #define HINT_VALUE_DOUBLE_MIN (-exp2(HINT_VALUE_BITS - 1)) |
1630 | | |
1631 | | /** |
1632 | | * We need to squeeze 64 bits of seconds and 32 bits of nanoseconds |
1633 | | * into 60 bits of hint value. The idea is to represent wide enough |
1634 | | * years range, and leave the rest of bits occupied from nanoseconds part: |
1635 | | * - 36 bits is enough for time range of [-208-05-13..6325-04-08] |
1636 | | * - for nanoseconds there is left 24 bits, which are MSB part of |
1637 | | * 32-bit value |
1638 | | */ |
1639 | 0 | #define HINT_VALUE_SECS_BITS 36 |
1640 | 0 | #define HINT_VALUE_NSEC_BITS (HINT_VALUE_BITS - HINT_VALUE_SECS_BITS) |
1641 | 0 | #define HINT_VALUE_SECS_MAX ((1LL << (HINT_VALUE_SECS_BITS - 1)) - 1) |
1642 | 0 | #define HINT_VALUE_SECS_MIN (-(1LL << (HINT_VALUE_SECS_BITS - 1))) |
1643 | 0 | #define HINT_VALUE_NSEC_SHIFT (sizeof(int32_t) * CHAR_BIT - HINT_VALUE_NSEC_BITS) |
1644 | 0 | #define HINT_VALUE_NSEC_MAX ((1ULL << HINT_VALUE_NSEC_BITS) - 1) |
1645 | | |
1646 | | /* |
1647 | | * HINT_CLASS_BITS should be big enough to store any mp_class value. |
1648 | | * Note, ((1 << HINT_CLASS_BITS) - 1) is reserved for HINT_NONE. |
1649 | | */ |
1650 | | static_assert(mp_class_max < (1 << HINT_CLASS_BITS) - 1, |
1651 | | "mp_class must fit in tuple hint"); |
1652 | | |
1653 | | static inline hint_t |
1654 | | hint_create(enum mp_class c, uint64_t val) |
1655 | 0 | { |
1656 | 0 | assert((val >> HINT_VALUE_BITS) == 0); |
1657 | 0 | return (hint_t)(((uint64_t)c << HINT_VALUE_BITS) | val); |
1658 | 0 | } |
1659 | | |
1660 | | static inline hint_t |
1661 | | hint_nil(void) |
1662 | 0 | { |
1663 | 0 | return hint_create(MP_CLASS_NIL, 0); |
1664 | 0 | } |
1665 | | |
1666 | | static inline hint_t |
1667 | | hint_bool(bool b) |
1668 | 0 | { |
1669 | 0 | return hint_create(MP_CLASS_BOOL, b ? 1 : 0); |
1670 | 0 | } |
1671 | | |
1672 | | static inline hint_t |
1673 | | hint_uint(uint64_t u) |
1674 | 0 | { |
1675 | 0 | uint64_t val = (u >= (uint64_t)HINT_VALUE_INT_MAX ? |
1676 | 0 | HINT_VALUE_MAX : u - HINT_VALUE_INT_MIN); |
1677 | 0 | return hint_create(MP_CLASS_NUMBER, val); |
1678 | 0 | } |
1679 | | |
1680 | | static inline hint_t |
1681 | | hint_int(int64_t i) |
1682 | 0 | { |
1683 | 0 | if (i >= 0) |
1684 | 0 | return hint_uint((uint64_t)i); |
1685 | 0 | uint64_t val = (i <= HINT_VALUE_INT_MIN ? 0 : i - HINT_VALUE_INT_MIN); |
1686 | 0 | return hint_create(MP_CLASS_NUMBER, val); |
1687 | 0 | } |
1688 | | |
1689 | | static inline hint_t |
1690 | | hint_double(double d) |
1691 | 0 | { |
1692 | 0 | if (!isfinite(d)) |
1693 | 0 | return HINT_NONE; |
1694 | | |
1695 | 0 | uint64_t val; |
1696 | 0 | if (d >= HINT_VALUE_DOUBLE_MAX) |
1697 | 0 | val = HINT_VALUE_MAX; |
1698 | 0 | else if (d <= HINT_VALUE_DOUBLE_MIN) |
1699 | 0 | val = 0; |
1700 | 0 | else |
1701 | 0 | val = (int64_t)d - HINT_VALUE_INT_MIN; |
1702 | |
|
1703 | 0 | return hint_create(MP_CLASS_NUMBER, val); |
1704 | 0 | } |
1705 | | |
1706 | | static inline hint_t |
1707 | | hint_decimal(decimal_t *dec) |
1708 | 0 | { |
1709 | 0 | uint64_t val = 0; |
1710 | 0 | int64_t num; |
1711 | 0 | if (decimal_to_int64(dec, &num) && |
1712 | 0 | num >= HINT_VALUE_INT_MIN && num <= HINT_VALUE_INT_MAX) { |
1713 | 0 | val = num - HINT_VALUE_INT_MIN; |
1714 | 0 | } else if (!(dec->bits & DECNEG)) { |
1715 | 0 | val = HINT_VALUE_MAX; |
1716 | 0 | } |
1717 | | /* |
1718 | | * In case the number is negative and out of bounds, val |
1719 | | * remains zero. |
1720 | | */ |
1721 | 0 | return hint_create(MP_CLASS_NUMBER, val); |
1722 | 0 | } |
1723 | | |
1724 | | static inline hint_t |
1725 | | hint_uuid_raw(const char *data) |
1726 | 0 | { |
1727 | | /* |
1728 | | * Packed UUID fields are big-endian and are stored in the |
1729 | | * order allowing lexicographical comparison, so the first |
1730 | | * 8 bytes of the packed representation constitute a big |
1731 | | * endian unsigned integer. Use it as a hint. |
1732 | | */ |
1733 | 0 | uint64_t val = mp_load_u64(&data); |
1734 | | /* Make space for class representation. */ |
1735 | 0 | val >>= HINT_CLASS_BITS; |
1736 | 0 | return hint_create(MP_CLASS_UUID, val); |
1737 | 0 | } |
1738 | | |
1739 | | static inline hint_t |
1740 | | hint_datetime(struct datetime *date) |
1741 | 0 | { |
1742 | | /* |
1743 | | * Use at most HINT_VALUE_SECS_BITS from datetime |
1744 | | * seconds field as a hint value, and at MSB part |
1745 | | * of HINT_VALUE_NSEC_BITS from nanoseconds. |
1746 | | */ |
1747 | 0 | int64_t secs = date->epoch; |
1748 | | /* |
1749 | | * Both overflow and underflow |
1750 | | */ |
1751 | 0 | bool is_overflow = false; |
1752 | 0 | uint64_t val; |
1753 | 0 | if (secs < HINT_VALUE_SECS_MIN) { |
1754 | 0 | is_overflow = true; |
1755 | 0 | val = 0; |
1756 | 0 | } else { |
1757 | 0 | val = secs - HINT_VALUE_SECS_MIN; |
1758 | 0 | } |
1759 | 0 | if (val > HINT_VALUE_SECS_MAX) { |
1760 | 0 | is_overflow = true; |
1761 | 0 | val = HINT_VALUE_SECS_MAX; |
1762 | 0 | } |
1763 | 0 | val <<= HINT_VALUE_NSEC_BITS; |
1764 | 0 | if (is_overflow == false) { |
1765 | 0 | val |= (date->nsec >> HINT_VALUE_NSEC_SHIFT) & |
1766 | 0 | HINT_VALUE_NSEC_MAX; |
1767 | 0 | } |
1768 | 0 | return hint_create(MP_CLASS_DATETIME, val); |
1769 | 0 | } |
1770 | | |
1771 | | static inline uint64_t |
1772 | | hint_str_raw(const char *s, uint32_t len) |
1773 | 0 | { |
1774 | 0 | len = MIN(len, HINT_VALUE_BYTES); |
1775 | 0 | uint64_t val = 0; |
1776 | 0 | for (uint32_t i = 0; i < len; i++) { |
1777 | 0 | val <<= CHAR_BIT; |
1778 | 0 | val |= (unsigned char)s[i]; |
1779 | 0 | } |
1780 | 0 | val <<= CHAR_BIT * (HINT_VALUE_BYTES - len); |
1781 | 0 | return val; |
1782 | 0 | } |
1783 | | |
1784 | | static inline hint_t |
1785 | | hint_str(const char *s, uint32_t len) |
1786 | 0 | { |
1787 | 0 | uint64_t val = hint_str_raw(s, len); |
1788 | 0 | return hint_create(MP_CLASS_STR, val); |
1789 | 0 | } |
1790 | | |
1791 | | static inline hint_t |
1792 | | hint_str_coll(const char *s, uint32_t len, struct coll *coll) |
1793 | 0 | { |
1794 | 0 | char buf[HINT_VALUE_BYTES]; |
1795 | 0 | uint32_t buf_len = coll->hint(s, len, buf, sizeof(buf), coll); |
1796 | 0 | uint64_t val = hint_str_raw(buf, buf_len); |
1797 | 0 | return hint_create(MP_CLASS_STR, val); |
1798 | 0 | } |
1799 | | |
1800 | | static inline hint_t |
1801 | | hint_bin(const char *s, uint32_t len) |
1802 | 0 | { |
1803 | 0 | uint64_t val = hint_str_raw(s, len); |
1804 | 0 | return hint_create(MP_CLASS_BIN, val); |
1805 | 0 | } |
1806 | | |
1807 | | static inline hint_t |
1808 | | field_hint_boolean(const char *field) |
1809 | 0 | { |
1810 | 0 | assert(mp_typeof(*field) == MP_BOOL); |
1811 | 0 | return hint_bool(mp_decode_bool(&field)); |
1812 | 0 | } |
1813 | | |
1814 | | static inline hint_t |
1815 | | field_hint_unsigned(const char *field) |
1816 | 0 | { |
1817 | 0 | assert(mp_typeof(*field) == MP_UINT); |
1818 | 0 | return hint_uint(mp_decode_uint(&field)); |
1819 | 0 | } |
1820 | | |
1821 | | static inline hint_t |
1822 | | field_hint_integer(const char *field) |
1823 | 0 | { |
1824 | 0 | switch (mp_typeof(*field)) { |
1825 | 0 | case MP_UINT: |
1826 | 0 | return hint_uint(mp_decode_uint(&field)); |
1827 | 0 | case MP_INT: |
1828 | 0 | return hint_int(mp_decode_int(&field)); |
1829 | 0 | default: |
1830 | 0 | unreachable(); |
1831 | 0 | } |
1832 | 0 | return HINT_NONE; |
1833 | 0 | } |
1834 | | |
1835 | | static inline hint_t |
1836 | | field_hint_float32(const char *field) |
1837 | 0 | { |
1838 | 0 | assert(mp_typeof(*field) == MP_FLOAT); |
1839 | 0 | return hint_double(mp_decode_float(&field)); |
1840 | 0 | } |
1841 | | |
1842 | | static inline hint_t |
1843 | | field_hint_float64(const char *field) |
1844 | 0 | { |
1845 | 0 | assert(mp_typeof(*field) == MP_DOUBLE); |
1846 | 0 | return hint_double(mp_decode_double(&field)); |
1847 | 0 | } |
1848 | | |
1849 | | static inline hint_t |
1850 | | field_hint_number(const char *field) |
1851 | 0 | { |
1852 | 0 | switch (mp_typeof(*field)) { |
1853 | 0 | case MP_UINT: |
1854 | 0 | return hint_uint(mp_decode_uint(&field)); |
1855 | 0 | case MP_INT: |
1856 | 0 | return hint_int(mp_decode_int(&field)); |
1857 | 0 | case MP_FLOAT: |
1858 | 0 | return hint_double(mp_decode_float(&field)); |
1859 | 0 | case MP_DOUBLE: |
1860 | 0 | return hint_double(mp_decode_double(&field)); |
1861 | 0 | case MP_EXT: |
1862 | 0 | { |
1863 | 0 | int8_t ext_type; |
1864 | 0 | uint32_t len = mp_decode_extl(&field, &ext_type); |
1865 | 0 | switch (ext_type) { |
1866 | 0 | case MP_DECIMAL: |
1867 | 0 | { |
1868 | 0 | decimal_t dec; |
1869 | 0 | return hint_decimal(decimal_unpack(&field, len, &dec)); |
1870 | 0 | } |
1871 | 0 | default: |
1872 | 0 | unreachable(); |
1873 | 0 | } |
1874 | 0 | } |
1875 | 0 | default: |
1876 | 0 | unreachable(); |
1877 | 0 | } |
1878 | 0 | return HINT_NONE; |
1879 | 0 | } |
1880 | | |
1881 | | static inline hint_t |
1882 | | field_hint_decimal(const char *field) |
1883 | 0 | { |
1884 | 0 | assert(mp_typeof(*field) == MP_EXT); |
1885 | 0 | int8_t ext_type; |
1886 | 0 | uint32_t len = mp_decode_extl(&field, &ext_type); |
1887 | 0 | switch (ext_type) { |
1888 | 0 | case MP_DECIMAL: |
1889 | 0 | { |
1890 | 0 | decimal_t dec; |
1891 | 0 | return hint_decimal(decimal_unpack(&field, len, &dec)); |
1892 | 0 | } |
1893 | 0 | default: |
1894 | 0 | unreachable(); |
1895 | 0 | } |
1896 | 0 | } |
1897 | | |
1898 | | static inline hint_t |
1899 | | field_hint_uuid(const char *field) |
1900 | 0 | { |
1901 | 0 | assert(mp_typeof(*field) == MP_EXT); |
1902 | 0 | int8_t type; |
1903 | 0 | uint32_t len; |
1904 | 0 | const char *data = mp_decode_ext(&field, &type, &len); |
1905 | 0 | assert(type == MP_UUID && len == UUID_PACKED_LEN); |
1906 | 0 | return hint_uuid_raw(data); |
1907 | 0 | } |
1908 | | |
1909 | | static inline hint_t |
1910 | | field_hint_datetime(const char *field) |
1911 | 0 | { |
1912 | 0 | assert(mp_typeof(*field) == MP_EXT); |
1913 | 0 | int8_t ext_type; |
1914 | 0 | uint32_t len = mp_decode_extl(&field, &ext_type); |
1915 | 0 | assert(ext_type == MP_DATETIME); |
1916 | 0 | struct datetime date; |
1917 | 0 | return hint_datetime(datetime_unpack(&field, len, &date)); |
1918 | 0 | } |
1919 | | |
1920 | | static inline hint_t |
1921 | | field_hint_string(const char *field, struct coll *coll) |
1922 | 0 | { |
1923 | 0 | assert(mp_typeof(*field) == MP_STR); |
1924 | 0 | uint32_t len = mp_decode_strl(&field); |
1925 | 0 | return coll == NULL ? hint_str(field, len) : |
1926 | 0 | hint_str_coll(field, len, coll); |
1927 | 0 | } |
1928 | | |
1929 | | static inline hint_t |
1930 | | field_hint_varbinary(const char *field) |
1931 | 0 | { |
1932 | 0 | assert(mp_typeof(*field) == MP_BIN); |
1933 | 0 | uint32_t len = mp_decode_binl(&field); |
1934 | 0 | return hint_bin(field, len); |
1935 | 0 | } |
1936 | | |
1937 | | static inline hint_t |
1938 | | field_hint_scalar(const char *field, struct coll *coll) |
1939 | 0 | { |
1940 | 0 | uint32_t len; |
1941 | 0 | switch(mp_typeof(*field)) { |
1942 | 0 | case MP_BOOL: |
1943 | 0 | return hint_bool(mp_decode_bool(&field)); |
1944 | 0 | case MP_UINT: |
1945 | 0 | return hint_uint(mp_decode_uint(&field)); |
1946 | 0 | case MP_INT: |
1947 | 0 | return hint_int(mp_decode_int(&field)); |
1948 | 0 | case MP_FLOAT: |
1949 | 0 | return hint_double(mp_decode_float(&field)); |
1950 | 0 | case MP_DOUBLE: |
1951 | 0 | return hint_double(mp_decode_double(&field)); |
1952 | 0 | case MP_STR: |
1953 | 0 | len = mp_decode_strl(&field); |
1954 | 0 | return coll == NULL ? hint_str(field, len) : |
1955 | 0 | hint_str_coll(field, len, coll); |
1956 | 0 | case MP_BIN: |
1957 | 0 | len = mp_decode_binl(&field); |
1958 | 0 | return hint_bin(field, len); |
1959 | 0 | case MP_EXT: |
1960 | 0 | { |
1961 | 0 | int8_t ext_type; |
1962 | 0 | uint32_t len = mp_decode_extl(&field, &ext_type); |
1963 | 0 | switch (ext_type) { |
1964 | 0 | case MP_DECIMAL: |
1965 | 0 | { |
1966 | 0 | decimal_t dec; |
1967 | 0 | return hint_decimal(decimal_unpack(&field, len, &dec)); |
1968 | 0 | } |
1969 | 0 | case MP_UUID: |
1970 | 0 | return hint_uuid_raw(field); |
1971 | 0 | case MP_DATETIME: |
1972 | 0 | { |
1973 | 0 | struct datetime date; |
1974 | 0 | return hint_datetime(datetime_unpack(&field, len, &date)); |
1975 | 0 | } |
1976 | 0 | default: |
1977 | 0 | unreachable(); |
1978 | 0 | } |
1979 | 0 | } |
1980 | 0 | default: |
1981 | 0 | unreachable(); |
1982 | 0 | } |
1983 | 0 | return HINT_NONE; |
1984 | 0 | } |
1985 | | |
1986 | | template <enum field_type type, bool is_nullable> |
1987 | | static inline hint_t |
1988 | | field_hint(const char *field, struct coll *coll) |
1989 | 0 | { |
1990 | 0 | if (is_nullable && mp_typeof(*field) == MP_NIL) |
1991 | 0 | return hint_nil(); |
1992 | 0 | switch (type) { |
1993 | 0 | case FIELD_TYPE_BOOLEAN: |
1994 | 0 | return field_hint_boolean(field); |
1995 | 0 | case FIELD_TYPE_UNSIGNED: |
1996 | 0 | case FIELD_TYPE_UINT8: |
1997 | 0 | case FIELD_TYPE_UINT16: |
1998 | 0 | case FIELD_TYPE_UINT32: |
1999 | 0 | case FIELD_TYPE_UINT64: |
2000 | 0 | return field_hint_unsigned(field); |
2001 | 0 | case FIELD_TYPE_INTEGER: |
2002 | 0 | case FIELD_TYPE_INT8: |
2003 | 0 | case FIELD_TYPE_INT16: |
2004 | 0 | case FIELD_TYPE_INT32: |
2005 | 0 | case FIELD_TYPE_INT64: |
2006 | 0 | return field_hint_integer(field); |
2007 | 0 | case FIELD_TYPE_NUMBER: |
2008 | 0 | case FIELD_TYPE_DOUBLE: |
2009 | 0 | return field_hint_number(field); |
2010 | 0 | case FIELD_TYPE_FLOAT32: |
2011 | 0 | return field_hint_float32(field); |
2012 | 0 | case FIELD_TYPE_FLOAT64: |
2013 | 0 | return field_hint_float64(field); |
2014 | 0 | case FIELD_TYPE_STRING: |
2015 | 0 | return field_hint_string(field, coll); |
2016 | 0 | case FIELD_TYPE_VARBINARY: |
2017 | 0 | return field_hint_varbinary(field); |
2018 | 0 | case FIELD_TYPE_SCALAR: |
2019 | 0 | return field_hint_scalar(field, coll); |
2020 | 0 | case FIELD_TYPE_DECIMAL: |
2021 | 0 | case FIELD_TYPE_DECIMAL32: |
2022 | 0 | case FIELD_TYPE_DECIMAL64: |
2023 | 0 | case FIELD_TYPE_DECIMAL128: |
2024 | 0 | case FIELD_TYPE_DECIMAL256: |
2025 | 0 | return field_hint_decimal(field); |
2026 | 0 | case FIELD_TYPE_UUID: |
2027 | 0 | return field_hint_uuid(field); |
2028 | 0 | case FIELD_TYPE_DATETIME: |
2029 | 0 | return field_hint_datetime(field); |
2030 | 0 | default: |
2031 | 0 | unreachable(); |
2032 | 0 | } |
2033 | 0 | return HINT_NONE; |
2034 | 0 | } Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)6, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)6, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)1, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)1, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)5, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)5, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)3, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)3, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)4, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)4, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)2, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)2, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)7, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)7, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)8, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)8, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)9, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)9, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)10, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)10, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)11, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)11, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)15, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)15, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)16, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)16, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)17, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)17, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)18, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)18, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)19, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)19, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)20, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)20, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)21, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)21, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)22, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)22, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)23, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)23, false>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)24, true>(char const*, coll*) Unexecuted instantiation: tuple_compare.cc:unsigned long field_hint<(field_type)24, false>(char const*, coll*) |
2035 | | |
2036 | | template<enum field_type type, bool is_nullable, bool has_desc_parts> |
2037 | | static hint_t |
2038 | | key_hint(const char *key, uint32_t part_count, struct key_def *key_def) |
2039 | 0 | { |
2040 | 0 | assert(!key_def->is_multikey); |
2041 | 0 | if (part_count == 0) |
2042 | 0 | return HINT_NONE; |
2043 | 0 | hint_t h = field_hint<type, is_nullable>(key, key_def->parts->coll); |
2044 | 0 | return key_part_hint<has_desc_parts>(key_def->parts, h); |
2045 | 0 | } Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)6, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)6, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)6, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)6, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)1, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)1, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)1, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)1, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)5, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)5, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)5, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)5, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)3, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)3, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)3, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)3, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)4, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)4, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)4, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)4, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)2, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)2, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)2, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)2, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)7, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)7, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)7, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)7, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)8, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)8, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)8, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)8, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)9, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)9, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)9, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)9, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)10, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)10, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)10, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)10, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)11, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)11, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)11, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)11, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)15, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)15, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)15, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)15, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)16, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)16, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)16, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)16, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)17, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)17, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)17, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)17, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)18, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)18, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)18, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)18, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)19, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)19, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)19, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)19, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)20, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)20, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)20, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)20, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)21, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)21, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)21, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)21, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)22, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)22, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)22, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)22, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)23, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)23, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)23, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)23, false, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)24, true, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)24, true, false>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)24, false, true>(char const*, unsigned int, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long key_hint<(field_type)24, false, false>(char const*, unsigned int, key_def*) |
2046 | | |
2047 | | template<enum field_type type, bool is_nullable, bool has_desc_parts> |
2048 | | static hint_t |
2049 | | tuple_hint(struct tuple *tuple, struct key_def *key_def) |
2050 | 0 | { |
2051 | 0 | assert(!key_def->is_multikey); |
2052 | 0 | const char *field = tuple_field_by_part(tuple, key_def->parts, |
2053 | 0 | MULTIKEY_NONE); |
2054 | 0 | hint_t h = is_nullable && field == NULL ? hint_nil() : |
2055 | 0 | field_hint<type, is_nullable>(field, key_def->parts->coll); |
2056 | 0 | return key_part_hint<has_desc_parts>(key_def->parts, h); |
2057 | 0 | } Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)6, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)6, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)6, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)6, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)1, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)1, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)1, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)1, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)5, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)5, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)5, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)5, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)3, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)3, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)3, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)3, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)4, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)4, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)4, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)4, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)2, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)2, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)2, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)2, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)7, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)7, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)7, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)7, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)8, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)8, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)8, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)8, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)9, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)9, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)9, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)9, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)10, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)10, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)10, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)10, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)11, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)11, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)11, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)11, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)15, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)15, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)15, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)15, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)16, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)16, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)16, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)16, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)17, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)17, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)17, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)17, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)18, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)18, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)18, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)18, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)19, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)19, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)19, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)19, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)20, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)20, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)20, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)20, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)21, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)21, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)21, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)21, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)22, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)22, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)22, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)22, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)23, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)23, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)23, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)23, false, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)24, true, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)24, true, false>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)24, false, true>(tuple*, key_def*) Unexecuted instantiation: tuple_compare.cc:unsigned long tuple_hint<(field_type)24, false, false>(tuple*, key_def*) |
2058 | | |
2059 | | static hint_t |
2060 | | key_hint_stub(const char *key, uint32_t part_count, struct key_def *key_def) |
2061 | 0 | { |
2062 | 0 | (void) key; |
2063 | 0 | (void) part_count; |
2064 | 0 | (void) key_def; |
2065 | | /* |
2066 | | * Multikey hint for tuple is an index of the key in |
2067 | | * array, it always must be defined. While |
2068 | | * key_hint_stub assumes that it must be |
2069 | | * initialized manually (so it mustn't be called), |
2070 | | * the virtual method for a key makes sense. Overriding |
2071 | | * this method such way, we extend existend code to |
2072 | | * do nothing on key hint calculation an it is valid |
2073 | | * because it is never used(unlike tuple hint). |
2074 | | */ |
2075 | 0 | assert(key_def->is_multikey || key_def->for_func_index); |
2076 | 0 | return HINT_NONE; |
2077 | 0 | } |
2078 | | |
2079 | | static hint_t |
2080 | | tuple_hint_stub(struct tuple *tuple, struct key_def *key_def) |
2081 | 0 | { |
2082 | 0 | (void) tuple; |
2083 | 0 | (void) key_def; |
2084 | 0 | unreachable(); |
2085 | 0 | return HINT_NONE; |
2086 | 0 | } |
2087 | | |
2088 | | template<enum field_type type, bool is_nullable, bool has_desc_parts> |
2089 | | static void |
2090 | | key_def_set_hint_func(struct key_def *def) |
2091 | 8.46k | { |
2092 | 8.46k | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; |
2093 | 8.46k | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; |
2094 | 8.46k | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)6, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)6, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)6, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)6, false, false>(key_def*) Line | Count | Source | 2091 | 1.09k | { | 2092 | 1.09k | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1.09k | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1.09k | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)1, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)1, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)1, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)1, false, false>(key_def*) Line | Count | Source | 2091 | 39 | { | 2092 | 39 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 39 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 39 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)5, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)5, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)5, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)5, false, false>(key_def*) Line | Count | Source | 2091 | 5.19k | { | 2092 | 5.19k | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 5.19k | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 5.19k | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)3, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)3, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)3, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)3, false, false>(key_def*) Line | Count | Source | 2091 | 49 | { | 2092 | 49 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 49 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 49 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)4, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)4, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)4, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)4, false, false>(key_def*) Line | Count | Source | 2091 | 46 | { | 2092 | 46 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 46 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 46 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)2, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)2, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)2, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)2, false, false>(key_def*) Line | Count | Source | 2091 | 78 | { | 2092 | 78 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 78 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 78 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)7, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)7, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)7, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)7, false, false>(key_def*) Line | Count | Source | 2091 | 42 | { | 2092 | 42 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 42 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 42 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)8, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)8, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)8, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)8, false, false>(key_def*) Line | Count | Source | 2091 | 45 | { | 2092 | 45 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 45 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 45 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)9, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)9, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)9, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)9, false, false>(key_def*) Line | Count | Source | 2091 | 187 | { | 2092 | 187 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 187 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 187 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)10, true, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)10, true, false>(key_def*) Line | Count | Source | 2091 | 1 | { | 2092 | 1 | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1 | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)10, false, true>(key_def*) tuple_compare.cc:void key_def_set_hint_func<(field_type)10, false, false>(key_def*) Line | Count | Source | 2091 | 1.67k | { | 2092 | 1.67k | def->key_hint = key_hint<type, is_nullable, has_desc_parts>; | 2093 | 1.67k | def->tuple_hint = tuple_hint<type, is_nullable, has_desc_parts>; | 2094 | 1.67k | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, false, false>(key_def*) |
2095 | | |
2096 | | template<enum field_type type, bool is_nullable> |
2097 | | static void |
2098 | | key_def_set_hint_func(struct key_def *def) |
2099 | 8.46k | { |
2100 | 8.46k | if (key_def_has_desc_parts(def)) |
2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); |
2102 | 8.46k | else |
2103 | 8.46k | key_def_set_hint_func<type, is_nullable, false>(def); |
2104 | 8.46k | } tuple_compare.cc:void key_def_set_hint_func<(field_type)6, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)6, false>(key_def*) Line | Count | Source | 2099 | 1.09k | { | 2100 | 1.09k | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1.09k | else | 2103 | 1.09k | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1.09k | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)1, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)1, false>(key_def*) Line | Count | Source | 2099 | 39 | { | 2100 | 39 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 39 | else | 2103 | 39 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 39 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)5, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)5, false>(key_def*) Line | Count | Source | 2099 | 5.19k | { | 2100 | 5.19k | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 5.19k | else | 2103 | 5.19k | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 5.19k | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)3, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)3, false>(key_def*) Line | Count | Source | 2099 | 49 | { | 2100 | 49 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 49 | else | 2103 | 49 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 49 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)4, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)4, false>(key_def*) Line | Count | Source | 2099 | 46 | { | 2100 | 46 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 46 | else | 2103 | 46 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 46 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)2, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)2, false>(key_def*) Line | Count | Source | 2099 | 78 | { | 2100 | 78 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 78 | else | 2103 | 78 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 78 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)7, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)7, false>(key_def*) Line | Count | Source | 2099 | 42 | { | 2100 | 42 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 42 | else | 2103 | 42 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 42 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)8, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)8, false>(key_def*) Line | Count | Source | 2099 | 45 | { | 2100 | 45 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 45 | else | 2103 | 45 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 45 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)9, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)9, false>(key_def*) Line | Count | Source | 2099 | 187 | { | 2100 | 187 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 187 | else | 2103 | 187 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 187 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)10, true>(key_def*) Line | Count | Source | 2099 | 1 | { | 2100 | 1 | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1 | else | 2103 | 1 | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)10, false>(key_def*) Line | Count | Source | 2099 | 1.67k | { | 2100 | 1.67k | if (key_def_has_desc_parts(def)) | 2101 | 0 | key_def_set_hint_func<type, is_nullable, true>(def); | 2102 | 1.67k | else | 2103 | 1.67k | key_def_set_hint_func<type, is_nullable, false>(def); | 2104 | 1.67k | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24, false>(key_def*) |
2105 | | |
2106 | | template<enum field_type type> |
2107 | | static void |
2108 | | key_def_set_hint_func(struct key_def *def) |
2109 | 8.46k | { |
2110 | 8.46k | if (key_part_is_nullable(def->parts)) |
2111 | 10 | key_def_set_hint_func<type, true>(def); |
2112 | 8.45k | else |
2113 | 8.45k | key_def_set_hint_func<type, false>(def); |
2114 | 8.46k | } tuple_compare.cc:void key_def_set_hint_func<(field_type)6>(key_def*) Line | Count | Source | 2109 | 1.09k | { | 2110 | 1.09k | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 1.09k | else | 2113 | 1.09k | key_def_set_hint_func<type, false>(def); | 2114 | 1.09k | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)1>(key_def*) Line | Count | Source | 2109 | 40 | { | 2110 | 40 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 39 | else | 2113 | 39 | key_def_set_hint_func<type, false>(def); | 2114 | 40 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)5>(key_def*) Line | Count | Source | 2109 | 5.19k | { | 2110 | 5.19k | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 5.19k | else | 2113 | 5.19k | key_def_set_hint_func<type, false>(def); | 2114 | 5.19k | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)3>(key_def*) Line | Count | Source | 2109 | 50 | { | 2110 | 50 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 49 | else | 2113 | 49 | key_def_set_hint_func<type, false>(def); | 2114 | 50 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)4>(key_def*) Line | Count | Source | 2109 | 47 | { | 2110 | 47 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 46 | else | 2113 | 46 | key_def_set_hint_func<type, false>(def); | 2114 | 47 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)2>(key_def*) Line | Count | Source | 2109 | 79 | { | 2110 | 79 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 78 | else | 2113 | 78 | key_def_set_hint_func<type, false>(def); | 2114 | 79 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)7>(key_def*) Line | Count | Source | 2109 | 43 | { | 2110 | 43 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 42 | else | 2113 | 42 | key_def_set_hint_func<type, false>(def); | 2114 | 43 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)8>(key_def*) Line | Count | Source | 2109 | 46 | { | 2110 | 46 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 45 | else | 2113 | 45 | key_def_set_hint_func<type, false>(def); | 2114 | 46 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)9>(key_def*) Line | Count | Source | 2109 | 188 | { | 2110 | 188 | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 187 | else | 2113 | 187 | key_def_set_hint_func<type, false>(def); | 2114 | 188 | } |
tuple_compare.cc:void key_def_set_hint_func<(field_type)10>(key_def*) Line | Count | Source | 2109 | 1.67k | { | 2110 | 1.67k | if (key_part_is_nullable(def->parts)) | 2111 | 1 | key_def_set_hint_func<type, true>(def); | 2112 | 1.67k | else | 2113 | 1.67k | key_def_set_hint_func<type, false>(def); | 2114 | 1.67k | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)11>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)15>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)16>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)17>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)18>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)19>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)20>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)21>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)22>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)23>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_hint_func<(field_type)24>(key_def*) |
2115 | | |
2116 | | static void |
2117 | | key_def_set_hint_func(struct key_def *def) |
2118 | 8.52k | { |
2119 | 8.52k | if (def->is_multikey || def->for_func_index) { |
2120 | 0 | def->key_hint = key_hint_stub; |
2121 | 0 | def->tuple_hint = tuple_hint_stub; |
2122 | 0 | return; |
2123 | 0 | } |
2124 | 8.52k | switch (def->parts->type) { |
2125 | 1.09k | case FIELD_TYPE_BOOLEAN: |
2126 | 1.09k | key_def_set_hint_func<FIELD_TYPE_BOOLEAN>(def); |
2127 | 1.09k | break; |
2128 | 40 | case FIELD_TYPE_UNSIGNED: |
2129 | 40 | key_def_set_hint_func<FIELD_TYPE_UNSIGNED>(def); |
2130 | 40 | break; |
2131 | 5.19k | case FIELD_TYPE_INTEGER: |
2132 | 5.19k | key_def_set_hint_func<FIELD_TYPE_INTEGER>(def); |
2133 | 5.19k | break; |
2134 | 50 | case FIELD_TYPE_NUMBER: |
2135 | 50 | key_def_set_hint_func<FIELD_TYPE_NUMBER>(def); |
2136 | 50 | break; |
2137 | 47 | case FIELD_TYPE_DOUBLE: |
2138 | 47 | key_def_set_hint_func<FIELD_TYPE_DOUBLE>(def); |
2139 | 47 | break; |
2140 | 79 | case FIELD_TYPE_STRING: |
2141 | 79 | key_def_set_hint_func<FIELD_TYPE_STRING>(def); |
2142 | 79 | break; |
2143 | 43 | case FIELD_TYPE_VARBINARY: |
2144 | 43 | key_def_set_hint_func<FIELD_TYPE_VARBINARY>(def); |
2145 | 43 | break; |
2146 | 46 | case FIELD_TYPE_SCALAR: |
2147 | 46 | key_def_set_hint_func<FIELD_TYPE_SCALAR>(def); |
2148 | 46 | break; |
2149 | 188 | case FIELD_TYPE_DECIMAL: |
2150 | 188 | case FIELD_TYPE_DECIMAL32: |
2151 | 188 | case FIELD_TYPE_DECIMAL64: |
2152 | 188 | case FIELD_TYPE_DECIMAL128: |
2153 | 188 | case FIELD_TYPE_DECIMAL256: |
2154 | 188 | key_def_set_hint_func<FIELD_TYPE_DECIMAL>(def); |
2155 | 188 | break; |
2156 | 1.67k | case FIELD_TYPE_UUID: |
2157 | 1.67k | key_def_set_hint_func<FIELD_TYPE_UUID>(def); |
2158 | 1.67k | break; |
2159 | 0 | case FIELD_TYPE_DATETIME: |
2160 | 0 | key_def_set_hint_func<FIELD_TYPE_DATETIME>(def); |
2161 | 0 | break; |
2162 | 0 | case FIELD_TYPE_INT8: |
2163 | 0 | key_def_set_hint_func<FIELD_TYPE_INT8>(def); |
2164 | 0 | break; |
2165 | 0 | case FIELD_TYPE_UINT8: |
2166 | 0 | key_def_set_hint_func<FIELD_TYPE_UINT8>(def); |
2167 | 0 | break; |
2168 | 0 | case FIELD_TYPE_INT16: |
2169 | 0 | key_def_set_hint_func<FIELD_TYPE_INT16>(def); |
2170 | 0 | break; |
2171 | 0 | case FIELD_TYPE_UINT16: |
2172 | 0 | key_def_set_hint_func<FIELD_TYPE_UINT16>(def); |
2173 | 0 | break; |
2174 | 0 | case FIELD_TYPE_INT32: |
2175 | 0 | key_def_set_hint_func<FIELD_TYPE_INT32>(def); |
2176 | 0 | break; |
2177 | 0 | case FIELD_TYPE_UINT32: |
2178 | 0 | key_def_set_hint_func<FIELD_TYPE_UINT32>(def); |
2179 | 0 | break; |
2180 | 0 | case FIELD_TYPE_INT64: |
2181 | 0 | key_def_set_hint_func<FIELD_TYPE_INT64>(def); |
2182 | 0 | break; |
2183 | 0 | case FIELD_TYPE_UINT64: |
2184 | 0 | key_def_set_hint_func<FIELD_TYPE_UINT64>(def); |
2185 | 0 | break; |
2186 | 0 | case FIELD_TYPE_FLOAT32: |
2187 | 0 | key_def_set_hint_func<FIELD_TYPE_FLOAT32>(def); |
2188 | 0 | break; |
2189 | 0 | case FIELD_TYPE_FLOAT64: |
2190 | 0 | key_def_set_hint_func<FIELD_TYPE_FLOAT64>(def); |
2191 | 0 | break; |
2192 | 64 | default: |
2193 | | /* Invalid key definition. */ |
2194 | 64 | def->key_hint = NULL; |
2195 | 64 | def->tuple_hint = NULL; |
2196 | 64 | break; |
2197 | 8.52k | } |
2198 | 8.52k | } |
2199 | | |
2200 | | /* }}} tuple_hint */ |
2201 | | |
2202 | | static void |
2203 | | key_def_set_compare_func_fast(struct key_def *def) |
2204 | 8.51k | { |
2205 | 8.51k | assert(!def->is_nullable); |
2206 | 8.51k | assert(!def->has_optional_parts); |
2207 | 8.51k | assert(!def->has_json_paths); |
2208 | 8.51k | assert(!key_def_has_collation(def)); |
2209 | 8.51k | assert(!key_def_has_desc_parts(def)); |
2210 | | |
2211 | 8.51k | tuple_compare_t cmp = NULL; |
2212 | 8.51k | tuple_compare_with_key_t cmp_wk = NULL; |
2213 | 8.51k | bool is_sequential = key_def_is_sequential(def); |
2214 | | |
2215 | | /* |
2216 | | * Use pre-compiled comparators if available, otherwise |
2217 | | * fall back on generic comparators. |
2218 | | */ |
2219 | 126k | for (uint32_t k = 0; k < lengthof(cmp_arr); k++) { |
2220 | 118k | uint32_t i = 0; |
2221 | 118k | for (; i < def->part_count; i++) |
2222 | 118k | if (def->parts[i].fieldno != cmp_arr[k].p[i * 2] || |
2223 | 118k | def->parts[i].type != cmp_arr[k].p[i * 2 + 1]) |
2224 | 117k | break; |
2225 | 118k | if (i == def->part_count && cmp_arr[k].p[i * 2] == UINT32_MAX) { |
2226 | 97 | cmp = cmp_arr[k].f; |
2227 | 97 | break; |
2228 | 97 | } |
2229 | 118k | } |
2230 | 109k | for (uint32_t k = 0; k < lengthof(cmp_wk_arr); k++) { |
2231 | 101k | uint32_t i = 0; |
2232 | 101k | for (; i < def->part_count; i++) { |
2233 | 101k | if (def->parts[i].fieldno != cmp_wk_arr[k].p[i * 2] || |
2234 | 101k | def->parts[i].type != cmp_wk_arr[k].p[i * 2 + 1]) |
2235 | 101k | break; |
2236 | 101k | } |
2237 | 101k | if (i == def->part_count) { |
2238 | 104 | cmp_wk = cmp_wk_arr[k].f; |
2239 | 104 | break; |
2240 | 104 | } |
2241 | 101k | } |
2242 | 8.51k | if (cmp == NULL) { |
2243 | 8.42k | cmp = is_sequential ? |
2244 | 7.96k | tuple_compare_sequential<false, false, false> : |
2245 | 8.42k | tuple_compare_slowpath<false, false, false, |
2246 | 455 | false, false>; |
2247 | 8.42k | } |
2248 | 8.51k | if (cmp_wk == NULL) { |
2249 | 8.41k | cmp_wk = is_sequential ? |
2250 | 7.96k | tuple_compare_with_key_sequential<false, false, false> : |
2251 | 8.41k | tuple_compare_with_key_slowpath<false, false, false, |
2252 | 448 | false, false>; |
2253 | 8.41k | } |
2254 | | |
2255 | 8.51k | def->tuple_compare = cmp; |
2256 | 8.51k | def->tuple_compare_with_key = cmp_wk; |
2257 | 8.51k | } |
2258 | | |
2259 | | template<bool is_nullable, bool has_optional_parts, bool has_desc_parts> |
2260 | | static void |
2261 | | key_def_set_compare_func_plain(struct key_def *def) |
2262 | 10 | { |
2263 | 10 | assert(!def->has_json_paths); |
2264 | 10 | if (key_def_is_sequential(def)) { |
2265 | 0 | def->tuple_compare = tuple_compare_sequential |
2266 | 0 | <is_nullable, has_optional_parts, has_desc_parts>; |
2267 | 0 | def->tuple_compare_with_key = tuple_compare_with_key_sequential |
2268 | 0 | <is_nullable, has_optional_parts, has_desc_parts>; |
2269 | 10 | } else { |
2270 | 10 | def->tuple_compare = tuple_compare_slowpath |
2271 | 10 | <is_nullable, has_optional_parts, |
2272 | 10 | false, false, has_desc_parts>; |
2273 | 10 | def->tuple_compare_with_key = tuple_compare_with_key_slowpath |
2274 | 10 | <is_nullable, has_optional_parts, |
2275 | 10 | false, false, has_desc_parts>; |
2276 | 10 | } |
2277 | 10 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<true, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<true, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<true, false, true>(key_def*) tuple_compare.cc:void key_def_set_compare_func_plain<true, false, false>(key_def*) Line | Count | Source | 2262 | 10 | { | 2263 | 10 | assert(!def->has_json_paths); | 2264 | 10 | if (key_def_is_sequential(def)) { | 2265 | 0 | def->tuple_compare = tuple_compare_sequential | 2266 | 0 | <is_nullable, has_optional_parts, has_desc_parts>; | 2267 | 0 | def->tuple_compare_with_key = tuple_compare_with_key_sequential | 2268 | 0 | <is_nullable, has_optional_parts, has_desc_parts>; | 2269 | 10 | } else { | 2270 | 10 | def->tuple_compare = tuple_compare_slowpath | 2271 | 10 | <is_nullable, has_optional_parts, | 2272 | 10 | false, false, has_desc_parts>; | 2273 | 10 | def->tuple_compare_with_key = tuple_compare_with_key_slowpath | 2274 | 10 | <is_nullable, has_optional_parts, | 2275 | 10 | false, false, has_desc_parts>; | 2276 | 10 | } | 2277 | 10 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<false, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<false, false, false>(key_def*) |
2278 | | |
2279 | | /* Proxy-template. */ |
2280 | | template<bool is_nullable, bool has_optional_parts> |
2281 | | static void |
2282 | | key_def_set_compare_func_plain(struct key_def *def) |
2283 | 10 | { |
2284 | 10 | assert(!def->has_json_paths); |
2285 | 10 | if (key_def_has_desc_parts(def)) |
2286 | 0 | key_def_set_compare_func_plain |
2287 | 0 | <is_nullable, has_optional_parts, true>(def); |
2288 | 10 | else |
2289 | 10 | key_def_set_compare_func_plain |
2290 | 10 | <is_nullable, has_optional_parts, false>(def); |
2291 | 10 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<true, true>(key_def*) tuple_compare.cc:void key_def_set_compare_func_plain<true, false>(key_def*) Line | Count | Source | 2283 | 10 | { | 2284 | 10 | assert(!def->has_json_paths); | 2285 | 10 | if (key_def_has_desc_parts(def)) | 2286 | 0 | key_def_set_compare_func_plain | 2287 | 0 | <is_nullable, has_optional_parts, true>(def); | 2288 | 10 | else | 2289 | 10 | key_def_set_compare_func_plain | 2290 | 10 | <is_nullable, has_optional_parts, false>(def); | 2291 | 10 | } |
Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_plain<false, false>(key_def*) |
2292 | | |
2293 | | template<bool is_nullable, bool has_optional_parts, bool has_desc_parts> |
2294 | | static void |
2295 | | key_def_set_compare_func_json(struct key_def *def) |
2296 | 0 | { |
2297 | 0 | if (def->is_multikey) { |
2298 | 0 | def->tuple_compare = tuple_compare_slowpath |
2299 | 0 | <is_nullable, has_optional_parts, |
2300 | 0 | true, true, has_desc_parts>; |
2301 | 0 | def->tuple_compare_with_key = tuple_compare_with_key_slowpath |
2302 | 0 | <is_nullable, has_optional_parts, |
2303 | 0 | true, true, has_desc_parts>; |
2304 | 0 | } else { |
2305 | 0 | def->tuple_compare = tuple_compare_slowpath |
2306 | 0 | <is_nullable, has_optional_parts, |
2307 | 0 | true, false, has_desc_parts>; |
2308 | 0 | def->tuple_compare_with_key = tuple_compare_with_key_slowpath |
2309 | 0 | <is_nullable, has_optional_parts, |
2310 | 0 | true, false, has_desc_parts>; |
2311 | 0 | } |
2312 | 0 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, false, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<false, false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<false, false, false>(key_def*) |
2313 | | |
2314 | | /* Proxy-template. */ |
2315 | | template<bool is_nullable, bool has_optional_parts> |
2316 | | static void |
2317 | | key_def_set_compare_func_json(struct key_def *def) |
2318 | 0 | { |
2319 | 0 | assert(def->has_json_paths); |
2320 | 0 | if (key_def_has_desc_parts(def)) |
2321 | 0 | key_def_set_compare_func_json |
2322 | 0 | <is_nullable, has_optional_parts, true>(def); |
2323 | 0 | else |
2324 | 0 | key_def_set_compare_func_json |
2325 | 0 | <is_nullable, has_optional_parts, false>(def); |
2326 | 0 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_json<false, false>(key_def*) |
2327 | | |
2328 | | /* Forced non-required comment. */ |
2329 | | template<bool is_nullable, bool has_desc_parts> |
2330 | | static void |
2331 | | key_def_set_compare_func_of_func_index(struct key_def *def) |
2332 | 0 | { |
2333 | 0 | assert(def->for_func_index); |
2334 | 0 | def->tuple_compare = func_index_compare<is_nullable, has_desc_parts>; |
2335 | 0 | def->tuple_compare_with_key = func_index_compare_with_key |
2336 | 0 | <is_nullable, has_desc_parts>; |
2337 | 0 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<true, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<true, false>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<false, true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<false, false>(key_def*) |
2338 | | |
2339 | | /* Proxy-template. */ |
2340 | | template<bool is_nullable> |
2341 | | static void |
2342 | | key_def_set_compare_func_of_func_index(struct key_def *def) |
2343 | 0 | { |
2344 | 0 | assert(def->for_func_index); |
2345 | 0 | if (key_def_has_desc_parts(def)) |
2346 | 0 | key_def_set_compare_func_of_func_index<is_nullable, true>(def); |
2347 | 0 | else |
2348 | 0 | key_def_set_compare_func_of_func_index<is_nullable, false>(def); |
2349 | 0 | } Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<true>(key_def*) Unexecuted instantiation: tuple_compare.cc:void key_def_set_compare_func_of_func_index<false>(key_def*) |
2350 | | |
2351 | | void |
2352 | | key_def_set_compare_func(struct key_def *def) |
2353 | 8.52k | { |
2354 | 8.52k | if (def->for_func_index) { |
2355 | 0 | if (def->is_nullable) |
2356 | 0 | key_def_set_compare_func_of_func_index<true>(def); |
2357 | 0 | else |
2358 | 0 | key_def_set_compare_func_of_func_index<false>(def); |
2359 | 8.52k | } else if (!def->is_nullable && !def->has_json_paths && |
2360 | 8.52k | !key_def_has_collation(def) && !key_def_has_desc_parts(def)) { |
2361 | 8.51k | key_def_set_compare_func_fast(def); |
2362 | 8.51k | } else if (!def->has_json_paths) { |
2363 | 10 | if (def->is_nullable && def->has_optional_parts) { |
2364 | 0 | key_def_set_compare_func_plain<true, true>(def); |
2365 | 10 | } else if (def->is_nullable && !def->has_optional_parts) { |
2366 | 10 | key_def_set_compare_func_plain<true, false>(def); |
2367 | 10 | } else { |
2368 | 0 | assert(!def->is_nullable && !def->has_optional_parts); |
2369 | 0 | key_def_set_compare_func_plain<false, false>(def); |
2370 | 0 | } |
2371 | 10 | } else { |
2372 | 0 | if (def->is_nullable && def->has_optional_parts) { |
2373 | 0 | key_def_set_compare_func_json<true, true>(def); |
2374 | 0 | } else if (def->is_nullable && !def->has_optional_parts) { |
2375 | 0 | key_def_set_compare_func_json<true, false>(def); |
2376 | 0 | } else { |
2377 | 0 | assert(!def->is_nullable && !def->has_optional_parts); |
2378 | 0 | key_def_set_compare_func_json<false, false>(def); |
2379 | 0 | } |
2380 | 0 | } |
2381 | | /* |
2382 | | * We are setting compare functions to NULL in case the key_def |
2383 | | * contains non-comparable type. Thus in case we later discover |
2384 | | * compare function equal to NULL we assume that the key_def |
2385 | | * contains incomparable type. It has to be revised if the |
2386 | | * new case where we are setting compare functions to NULL |
2387 | | * appears. |
2388 | | */ |
2389 | 8.52k | if (key_def_incomparable_type(def) != field_type_MAX) { |
2390 | 64 | def->tuple_compare = NULL; |
2391 | 64 | def->tuple_compare_with_key = NULL; |
2392 | 64 | } |
2393 | 8.52k | key_def_set_hint_func(def); |
2394 | 8.52k | } |