Coverage Report

Created: 2025-07-01 06:58

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