~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/innobase/rem/rem0cmp.c

  • Committer: Daniel Nichter
  • Date: 2011-10-23 16:01:37 UTC
  • mto: This revision was merged to the branch mainline in revision 2448.
  • Revision ID: daniel@percona.com-20111023160137-7ac3blgz8z4tf8za
Add Administration Getting Started and Logging.  Capitalize SQL clause keywords.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/***********************************************************************
2
 
Comparison services for records
3
 
 
4
 
(c) 1994-1996 Innobase Oy
5
 
 
6
 
Created 7/1/1994 Heikki Tuuri
7
 
************************************************************************/
8
 
 
9
 
#include "rem0cmp.h"
10
 
 
11
 
#ifdef UNIV_NONINL
12
 
#include "rem0cmp.ic"
13
 
#endif
14
 
 
15
 
#include "srv0srv.h"
16
 
 
17
 
/*              ALPHABETICAL ORDER
18
 
                ==================
19
 
 
20
 
The records are put into alphabetical order in the following
21
 
way: let F be the first field where two records disagree.
22
 
If there is a character in some position n where the the
23
 
records disagree, the order is determined by comparison of
24
 
the characters at position n, possibly after
25
 
collating transformation. If there is no such character,
26
 
but the corresponding fields have different lengths, then
27
 
if the data type of the fields is paddable,
28
 
shorter field is padded with a padding character. If the
29
 
data type is not paddable, longer field is considered greater.
30
 
Finally, the SQL null is bigger than any other value.
31
 
 
32
 
At the present, the comparison functions return 0 in the case,
33
 
where two records disagree only in the way that one
34
 
has more fields than the other. */
35
 
 
36
 
#ifdef UNIV_DEBUG
37
 
/*****************************************************************
38
 
Used in debug checking of cmp_dtuple_... .
39
 
This function is used to compare a data tuple to a physical record. If
40
 
dtuple has n fields then rec must have either m >= n fields, or it must
41
 
differ from dtuple in some of the m fields rec has. */
42
 
static
43
 
int
44
 
cmp_debug_dtuple_rec_with_match(
45
 
/*============================*/
46
 
                                /* out: 1, 0, -1, if dtuple is greater, equal,
47
 
                                less than rec, respectively, when only the
48
 
                                common first fields are compared */
49
 
        const dtuple_t* dtuple, /* in: data tuple */
50
 
        const rec_t*    rec,    /* in: physical record which differs from
51
 
                                dtuple in some of the common fields, or which
52
 
                                has an equal number or more fields than
53
 
                                dtuple */
54
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
55
 
        ulint*          matched_fields);/* in/out: number of already
56
 
                                completely  matched fields; when function
57
 
                                returns, contains the value for current
58
 
                                comparison */
59
 
#endif /* UNIV_DEBUG */
60
 
#ifndef UNIV_HOTBACKUP
61
 
/*****************************************************************
62
 
This function is used to compare two data fields for which the data type
63
 
is such that we must use MySQL code to compare them. The prototype here
64
 
must be a copy of the the one in ha_innobase.cc! */
65
 
extern
66
 
int
67
 
innobase_mysql_cmp(
68
 
/*===============*/
69
 
                                        /* out: 1, 0, -1, if a is greater,
70
 
                                        equal, less than b, respectively */
71
 
        int             mysql_type,     /* in: MySQL type */
72
 
        uint            charset_number, /* in: number of the charset */
73
 
        const unsigned char* a,         /* in: data field */
74
 
        unsigned int    a_length,       /* in: data field length,
75
 
                                        not UNIV_SQL_NULL */
76
 
        const unsigned char* b,         /* in: data field */
77
 
        unsigned int    b_length);      /* in: data field length,
78
 
                                        not UNIV_SQL_NULL */
79
 
#endif /* !UNIV_HOTBACKUP */
80
 
/*************************************************************************
81
 
Transforms the character code so that it is ordered appropriately for the
82
 
language. This is only used for the latin1 char set. MySQL does the
83
 
comparisons for other char sets. */
84
 
UNIV_INLINE
85
 
ulint
86
 
cmp_collate(
87
 
/*========*/
88
 
                        /* out: collation order position */
89
 
        ulint   code)   /* in: code of a character stored in database record */
90
 
{
91
 
        return((ulint) srv_latin1_ordering[code]);
92
 
}
93
 
 
94
 
/*****************************************************************
95
 
Returns TRUE if two columns are equal for comparison purposes. */
96
 
UNIV_INTERN
97
 
ibool
98
 
cmp_cols_are_equal(
99
 
/*===============*/
100
 
                                        /* out: TRUE if the columns are
101
 
                                        considered equal in comparisons */
102
 
        const dict_col_t*       col1,   /* in: column 1 */
103
 
        const dict_col_t*       col2,   /* in: column 2 */
104
 
        ibool                   check_charsets)
105
 
                                        /* in: whether to check charsets */
106
 
{
107
 
        if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
108
 
            && dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
109
 
 
110
 
                /* Both are non-binary string types: they can be compared if
111
 
                and only if the charset-collation is the same */
112
 
 
113
 
                if (check_charsets) {
114
 
                        return(dtype_get_charset_coll(col1->prtype)
115
 
                               == dtype_get_charset_coll(col2->prtype));
116
 
                } else {
117
 
                        return(TRUE);
118
 
                }
119
 
        }
120
 
 
121
 
        if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
122
 
            && dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
123
 
 
124
 
                /* Both are binary string types: they can be compared */
125
 
 
126
 
                return(TRUE);
127
 
        }
128
 
 
129
 
        if (col1->mtype != col2->mtype) {
130
 
 
131
 
                return(FALSE);
132
 
        }
133
 
 
134
 
        if (col1->mtype == DATA_INT
135
 
            && (col1->prtype & DATA_UNSIGNED)
136
 
            != (col2->prtype & DATA_UNSIGNED)) {
137
 
 
138
 
                /* The storage format of an unsigned integer is different
139
 
                from a signed integer: in a signed integer we OR
140
 
                0x8000... to the value of positive integers. */
141
 
 
142
 
                return(FALSE);
143
 
        }
144
 
 
145
 
        return(col1->mtype != DATA_INT || col1->len == col2->len);
146
 
}
147
 
 
148
 
#ifndef UNIV_HOTBACKUP
149
 
/*****************************************************************
150
 
Innobase uses this function to compare two data fields for which the data type
151
 
is such that we must compare whole fields or call MySQL to do the comparison */
152
 
static
153
 
int
154
 
cmp_whole_field(
155
 
/*============*/
156
 
                                        /* out: 1, 0, -1, if a is greater,
157
 
                                        equal, less than b, respectively */
158
 
        ulint           mtype,          /* in: main type */
159
 
        ulint           prtype,         /* in: precise type */
160
 
        const byte*     a,              /* in: data field */
161
 
        unsigned int    a_length,       /* in: data field length,
162
 
                                        not UNIV_SQL_NULL */
163
 
        const byte*     b,              /* in: data field */
164
 
        unsigned int    b_length)       /* in: data field length,
165
 
                                        not UNIV_SQL_NULL */
166
 
{
167
 
        float           f_1;
168
 
        float           f_2;
169
 
        double          d_1;
170
 
        double          d_2;
171
 
        int             swap_flag       = 1;
172
 
 
173
 
        switch (mtype) {
174
 
 
175
 
        case DATA_DECIMAL:
176
 
                /* Remove preceding spaces */
177
 
                for (; a_length && *a == ' '; a++, a_length--);
178
 
                for (; b_length && *b == ' '; b++, b_length--);
179
 
 
180
 
                if (*a == '-') {
181
 
                        if (*b != '-') {
182
 
                                return(-1);
183
 
                        }
184
 
 
185
 
                        a++; b++;
186
 
                        a_length--;
187
 
                        b_length--;
188
 
 
189
 
                        swap_flag = -1;
190
 
 
191
 
                } else if (*b == '-') {
192
 
 
193
 
                        return(1);
194
 
                }
195
 
 
196
 
                while (a_length > 0 && (*a == '+' || *a == '0')) {
197
 
                        a++; a_length--;
198
 
                }
199
 
 
200
 
                while (b_length > 0 && (*b == '+' || *b == '0')) {
201
 
                        b++; b_length--;
202
 
                }
203
 
 
204
 
                if (a_length != b_length) {
205
 
                        if (a_length < b_length) {
206
 
                                return(-swap_flag);
207
 
                        }
208
 
 
209
 
                        return(swap_flag);
210
 
                }
211
 
 
212
 
                while (a_length > 0 && *a == *b) {
213
 
 
214
 
                        a++; b++; a_length--;
215
 
                }
216
 
 
217
 
                if (a_length == 0) {
218
 
 
219
 
                        return(0);
220
 
                }
221
 
 
222
 
                if (*a > *b) {
223
 
                        return(swap_flag);
224
 
                }
225
 
 
226
 
                return(-swap_flag);
227
 
        case DATA_DOUBLE:
228
 
                d_1 = mach_double_read(a);
229
 
                d_2 = mach_double_read(b);
230
 
 
231
 
                if (d_1 > d_2) {
232
 
                        return(1);
233
 
                } else if (d_2 > d_1) {
234
 
                        return(-1);
235
 
                }
236
 
 
237
 
                return(0);
238
 
 
239
 
        case DATA_FLOAT:
240
 
                f_1 = mach_float_read(a);
241
 
                f_2 = mach_float_read(b);
242
 
 
243
 
                if (f_1 > f_2) {
244
 
                        return(1);
245
 
                } else if (f_2 > f_1) {
246
 
                        return(-1);
247
 
                }
248
 
 
249
 
                return(0);
250
 
        case DATA_BLOB:
251
 
                if (prtype & DATA_BINARY_TYPE) {
252
 
 
253
 
                        ut_print_timestamp(stderr);
254
 
                        fprintf(stderr,
255
 
                                "  InnoDB: Error: comparing a binary BLOB"
256
 
                                " with a character set sensitive\n"
257
 
                                "InnoDB: comparison!\n");
258
 
                }
259
 
                /* fall through */
260
 
        case DATA_VARMYSQL:
261
 
        case DATA_MYSQL:
262
 
                return(innobase_mysql_cmp(
263
 
                               (int)(prtype & DATA_MYSQL_TYPE_MASK),
264
 
                               (uint)dtype_get_charset_coll(prtype),
265
 
                               a, a_length, b, b_length));
266
 
        default:
267
 
                fprintf(stderr,
268
 
                        "InnoDB: unknown type number %lu\n",
269
 
                        (ulong) mtype);
270
 
                ut_error;
271
 
        }
272
 
 
273
 
        return(0);
274
 
}
275
 
#endif /* !UNIV_HOTBACKUP */
276
 
 
277
 
/*****************************************************************
278
 
This function is used to compare two data fields for which we know the
279
 
data type. */
280
 
UNIV_INTERN
281
 
int
282
 
cmp_data_data_slow(
283
 
/*===============*/
284
 
                                /* out: 1, 0, -1, if data1 is greater, equal,
285
 
                                less than data2, respectively */
286
 
        ulint           mtype,  /* in: main type */
287
 
        ulint           prtype, /* in: precise type */
288
 
        const byte*     data1,  /* in: data field (== a pointer to a memory
289
 
                                buffer) */
290
 
        ulint           len1,   /* in: data field length or UNIV_SQL_NULL */
291
 
        const byte*     data2,  /* in: data field (== a pointer to a memory
292
 
                                buffer) */
293
 
        ulint           len2)   /* in: data field length or UNIV_SQL_NULL */
294
 
{
295
 
#ifndef UNIV_HOTBACKUP
296
 
        ulint   data1_byte;
297
 
        ulint   data2_byte;
298
 
        ulint   cur_bytes;
299
 
 
300
 
        if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
301
 
 
302
 
                if (len1 == len2) {
303
 
 
304
 
                        return(0);
305
 
                }
306
 
 
307
 
                if (len1 == UNIV_SQL_NULL) {
308
 
                        /* We define the SQL null to be the smallest possible
309
 
                        value of a field in the alphabetical order */
310
 
 
311
 
                        return(-1);
312
 
                }
313
 
 
314
 
                return(1);
315
 
        }
316
 
 
317
 
        if (mtype >= DATA_FLOAT
318
 
            || (mtype == DATA_BLOB
319
 
                && 0 == (prtype & DATA_BINARY_TYPE)
320
 
                && dtype_get_charset_coll(prtype)
321
 
                != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
322
 
 
323
 
                return(cmp_whole_field(mtype, prtype,
324
 
                                       data1, (unsigned) len1,
325
 
                                       data2, (unsigned) len2));
326
 
        }
327
 
 
328
 
        /* Compare then the fields */
329
 
 
330
 
        cur_bytes = 0;
331
 
 
332
 
        for (;;) {
333
 
                if (len1 <= cur_bytes) {
334
 
                        if (len2 <= cur_bytes) {
335
 
 
336
 
                                return(0);
337
 
                        }
338
 
 
339
 
                        data1_byte = dtype_get_pad_char(mtype, prtype);
340
 
 
341
 
                        if (data1_byte == ULINT_UNDEFINED) {
342
 
 
343
 
                                return(-1);
344
 
                        }
345
 
                } else {
346
 
                        data1_byte = *data1;
347
 
                }
348
 
 
349
 
                if (len2 <= cur_bytes) {
350
 
                        data2_byte = dtype_get_pad_char(mtype, prtype);
351
 
 
352
 
                        if (data2_byte == ULINT_UNDEFINED) {
353
 
 
354
 
                                return(1);
355
 
                        }
356
 
                } else {
357
 
                        data2_byte = *data2;
358
 
                }
359
 
 
360
 
                if (data1_byte == data2_byte) {
361
 
                        /* If the bytes are equal, they will remain such even
362
 
                        after the collation transformation below */
363
 
 
364
 
                        goto next_byte;
365
 
                }
366
 
 
367
 
                if (mtype <= DATA_CHAR
368
 
                    || (mtype == DATA_BLOB
369
 
                        && 0 == (prtype & DATA_BINARY_TYPE))) {
370
 
 
371
 
                        data1_byte = cmp_collate(data1_byte);
372
 
                        data2_byte = cmp_collate(data2_byte);
373
 
                }
374
 
 
375
 
                if (data1_byte > data2_byte) {
376
 
 
377
 
                        return(1);
378
 
                } else if (data1_byte < data2_byte) {
379
 
 
380
 
                        return(-1);
381
 
                }
382
 
next_byte:
383
 
                /* Next byte */
384
 
                cur_bytes++;
385
 
                data1++;
386
 
                data2++;
387
 
        }
388
 
#else /* !UNIV_HOTBACKUP */
389
 
        /* This function depends on MySQL code that is not included in
390
 
        InnoDB Hot Backup builds.  Besides, this function should never
391
 
        be called in InnoDB Hot Backup. */
392
 
        ut_error;
393
 
#endif /* !UNIV_HOTBACKUP */
394
 
 
395
 
        return(0);              /* Not reached */
396
 
}
397
 
 
398
 
/*****************************************************************
399
 
This function is used to compare a data tuple to a physical record.
400
 
Only dtuple->n_fields_cmp first fields are taken into account for
401
 
the the data tuple! If we denote by n = n_fields_cmp, then rec must
402
 
have either m >= n fields, or it must differ from dtuple in some of
403
 
the m fields rec has. If rec has an externally stored field we do not
404
 
compare it but return with value 0 if such a comparison should be
405
 
made. */
406
 
UNIV_INTERN
407
 
int
408
 
cmp_dtuple_rec_with_match(
409
 
/*======================*/
410
 
                                /* out: 1, 0, -1, if dtuple is greater, equal,
411
 
                                less than rec, respectively, when only the
412
 
                                common first fields are compared, or
413
 
                                until the first externally stored field in
414
 
                                rec */
415
 
        const dtuple_t* dtuple, /* in: data tuple */
416
 
        const rec_t*    rec,    /* in: physical record which differs from
417
 
                                dtuple in some of the common fields, or which
418
 
                                has an equal number or more fields than
419
 
                                dtuple */
420
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
421
 
        ulint*          matched_fields, /* in/out: number of already completely
422
 
                                matched fields; when function returns,
423
 
                                contains the value for current comparison */
424
 
        ulint*          matched_bytes) /* in/out: number of already matched
425
 
                                bytes within the first field not completely
426
 
                                matched; when function returns, contains the
427
 
                                value for current comparison */
428
 
{
429
 
#ifndef UNIV_HOTBACKUP
430
 
        const dfield_t* dtuple_field;   /* current field in logical record */
431
 
        ulint           dtuple_f_len;   /* the length of the current field
432
 
                                        in the logical record */
433
 
        const byte*     dtuple_b_ptr;   /* pointer to the current byte in
434
 
                                        logical field data */
435
 
        ulint           dtuple_byte;    /* value of current byte to be compared
436
 
                                        in dtuple*/
437
 
        ulint           rec_f_len;      /* length of current field in rec */
438
 
        const byte*     rec_b_ptr;      /* pointer to the current byte in
439
 
                                        rec field */
440
 
        ulint           rec_byte;       /* value of current byte to be
441
 
                                        compared in rec */
442
 
        ulint           cur_field;      /* current field number */
443
 
        ulint           cur_bytes;      /* number of already matched bytes
444
 
                                        in current field */
445
 
        int             ret = 3333;     /* return value */
446
 
 
447
 
        ut_ad(dtuple && rec && matched_fields && matched_bytes);
448
 
        ut_ad(dtuple_check_typed(dtuple));
449
 
        ut_ad(rec_offs_validate(rec, NULL, offsets));
450
 
 
451
 
        cur_field = *matched_fields;
452
 
        cur_bytes = *matched_bytes;
453
 
 
454
 
        ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
455
 
        ut_ad(cur_field <= rec_offs_n_fields(offsets));
456
 
 
457
 
        if (cur_bytes == 0 && cur_field == 0) {
458
 
                ulint   rec_info = rec_get_info_bits(rec,
459
 
                                                     rec_offs_comp(offsets));
460
 
                ulint   tup_info = dtuple_get_info_bits(dtuple);
461
 
 
462
 
                if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
463
 
                        ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
464
 
                        goto order_resolved;
465
 
                } else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
466
 
                        ret = -1;
467
 
                        goto order_resolved;
468
 
                }
469
 
        }
470
 
 
471
 
        /* Match fields in a loop; stop if we run out of fields in dtuple
472
 
        or find an externally stored field */
473
 
 
474
 
        while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
475
 
 
476
 
                ulint   mtype;
477
 
                ulint   prtype;
478
 
 
479
 
                dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
480
 
                {
481
 
                        const dtype_t*  type
482
 
                                = dfield_get_type(dtuple_field);
483
 
 
484
 
                        mtype = type->mtype;
485
 
                        prtype = type->prtype;
486
 
                }
487
 
 
488
 
                dtuple_f_len = dfield_get_len(dtuple_field);
489
 
 
490
 
                rec_b_ptr = rec_get_nth_field(rec, offsets,
491
 
                                              cur_field, &rec_f_len);
492
 
 
493
 
                /* If we have matched yet 0 bytes, it may be that one or
494
 
                both the fields are SQL null, or the record or dtuple may be
495
 
                the predefined minimum record, or the field is externally
496
 
                stored */
497
 
 
498
 
                if (UNIV_LIKELY(cur_bytes == 0)) {
499
 
                        if (rec_offs_nth_extern(offsets, cur_field)) {
500
 
                                /* We do not compare to an externally
501
 
                                stored field */
502
 
 
503
 
                                ret = 0;
504
 
 
505
 
                                goto order_resolved;
506
 
                        }
507
 
 
508
 
                        if (dtuple_f_len == UNIV_SQL_NULL) {
509
 
                                if (rec_f_len == UNIV_SQL_NULL) {
510
 
 
511
 
                                        goto next_field;
512
 
                                }
513
 
 
514
 
                                ret = -1;
515
 
                                goto order_resolved;
516
 
                        } else if (rec_f_len == UNIV_SQL_NULL) {
517
 
                                /* We define the SQL null to be the
518
 
                                smallest possible value of a field
519
 
                                in the alphabetical order */
520
 
 
521
 
                                ret = 1;
522
 
                                goto order_resolved;
523
 
                        }
524
 
                }
525
 
 
526
 
                if (mtype >= DATA_FLOAT
527
 
                    || (mtype == DATA_BLOB
528
 
                        && 0 == (prtype & DATA_BINARY_TYPE)
529
 
                        && dtype_get_charset_coll(prtype)
530
 
                        != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
531
 
 
532
 
                        ret = cmp_whole_field(mtype, prtype,
533
 
                                              dfield_get_data(dtuple_field),
534
 
                                              (unsigned) dtuple_f_len,
535
 
                                              rec_b_ptr, (unsigned) rec_f_len);
536
 
 
537
 
                        if (ret != 0) {
538
 
                                cur_bytes = 0;
539
 
 
540
 
                                goto order_resolved;
541
 
                        } else {
542
 
                                goto next_field;
543
 
                        }
544
 
                }
545
 
 
546
 
                /* Set the pointers at the current byte */
547
 
 
548
 
                rec_b_ptr = rec_b_ptr + cur_bytes;
549
 
                dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
550
 
                        + cur_bytes;
551
 
                /* Compare then the fields */
552
 
 
553
 
                for (;;) {
554
 
                        if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
555
 
                                if (dtuple_f_len <= cur_bytes) {
556
 
 
557
 
                                        goto next_field;
558
 
                                }
559
 
 
560
 
                                rec_byte = dtype_get_pad_char(mtype, prtype);
561
 
 
562
 
                                if (rec_byte == ULINT_UNDEFINED) {
563
 
                                        ret = 1;
564
 
 
565
 
                                        goto order_resolved;
566
 
                                }
567
 
                        } else {
568
 
                                rec_byte = *rec_b_ptr;
569
 
                        }
570
 
 
571
 
                        if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
572
 
                                dtuple_byte = dtype_get_pad_char(mtype,
573
 
                                                                 prtype);
574
 
 
575
 
                                if (dtuple_byte == ULINT_UNDEFINED) {
576
 
                                        ret = -1;
577
 
 
578
 
                                        goto order_resolved;
579
 
                                }
580
 
                        } else {
581
 
                                dtuple_byte = *dtuple_b_ptr;
582
 
                        }
583
 
 
584
 
                        if (dtuple_byte == rec_byte) {
585
 
                                /* If the bytes are equal, they will
586
 
                                remain such even after the collation
587
 
                                transformation below */
588
 
 
589
 
                                goto next_byte;
590
 
                        }
591
 
 
592
 
                        if (mtype <= DATA_CHAR
593
 
                            || (mtype == DATA_BLOB
594
 
                                && !(prtype & DATA_BINARY_TYPE))) {
595
 
 
596
 
                                rec_byte = cmp_collate(rec_byte);
597
 
                                dtuple_byte = cmp_collate(dtuple_byte);
598
 
                        }
599
 
 
600
 
                        ret = (int) (dtuple_byte - rec_byte);
601
 
                        if (UNIV_LIKELY(ret)) {
602
 
                                if (ret < 0) {
603
 
                                        ret = -1;
604
 
                                        goto order_resolved;
605
 
                                } else {
606
 
                                        ret = 1;
607
 
                                        goto order_resolved;
608
 
                                }
609
 
                        }
610
 
next_byte:
611
 
                        /* Next byte */
612
 
                        cur_bytes++;
613
 
                        rec_b_ptr++;
614
 
                        dtuple_b_ptr++;
615
 
                }
616
 
 
617
 
next_field:
618
 
                cur_field++;
619
 
                cur_bytes = 0;
620
 
        }
621
 
 
622
 
        ut_ad(cur_bytes == 0);
623
 
 
624
 
        ret = 0;        /* If we ran out of fields, dtuple was equal to rec
625
 
                        up to the common fields */
626
 
order_resolved:
627
 
        ut_ad((ret >= - 1) && (ret <= 1));
628
 
        ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
629
 
                                                     matched_fields));
630
 
        ut_ad(*matched_fields == cur_field); /* In the debug version, the
631
 
                                             above cmp_debug_... sets
632
 
                                             *matched_fields to a value */
633
 
        *matched_fields = cur_field;
634
 
        *matched_bytes = cur_bytes;
635
 
 
636
 
        return(ret);
637
 
#else /* !UNIV_HOTBACKUP */
638
 
        /* This function depends on MySQL code that is not included in
639
 
        InnoDB Hot Backup builds.  Besides, this function should never
640
 
        be called in InnoDB Hot Backup. */
641
 
        ut_error;
642
 
        return(0);
643
 
#endif /* !UNIV_HOTBACKUP */
644
 
}
645
 
 
646
 
/******************************************************************
647
 
Compares a data tuple to a physical record. */
648
 
UNIV_INTERN
649
 
int
650
 
cmp_dtuple_rec(
651
 
/*===========*/
652
 
                                /* out: 1, 0, -1, if dtuple is greater, equal,
653
 
                                less than rec, respectively; see the comments
654
 
                                for cmp_dtuple_rec_with_match */
655
 
        const dtuple_t* dtuple, /* in: data tuple */
656
 
        const rec_t*    rec,    /* in: physical record */
657
 
        const ulint*    offsets)/* in: array returned by rec_get_offsets() */
658
 
{
659
 
        ulint   matched_fields  = 0;
660
 
        ulint   matched_bytes   = 0;
661
 
 
662
 
        ut_ad(rec_offs_validate(rec, NULL, offsets));
663
 
        return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
664
 
                                         &matched_fields, &matched_bytes));
665
 
}
666
 
 
667
 
/******************************************************************
668
 
Checks if a dtuple is a prefix of a record. The last field in dtuple
669
 
is allowed to be a prefix of the corresponding field in the record. */
670
 
UNIV_INTERN
671
 
ibool
672
 
cmp_dtuple_is_prefix_of_rec(
673
 
/*========================*/
674
 
                                /* out: TRUE if prefix */
675
 
        const dtuple_t* dtuple, /* in: data tuple */
676
 
        const rec_t*    rec,    /* in: physical record */
677
 
        const ulint*    offsets)/* in: array returned by rec_get_offsets() */
678
 
{
679
 
        ulint   n_fields;
680
 
        ulint   matched_fields  = 0;
681
 
        ulint   matched_bytes   = 0;
682
 
 
683
 
        ut_ad(rec_offs_validate(rec, NULL, offsets));
684
 
        n_fields = dtuple_get_n_fields(dtuple);
685
 
 
686
 
        if (n_fields > rec_offs_n_fields(offsets)) {
687
 
 
688
 
                return(FALSE);
689
 
        }
690
 
 
691
 
        cmp_dtuple_rec_with_match(dtuple, rec, offsets,
692
 
                                  &matched_fields, &matched_bytes);
693
 
        if (matched_fields == n_fields) {
694
 
 
695
 
                return(TRUE);
696
 
        }
697
 
 
698
 
        if (matched_fields == n_fields - 1
699
 
            && matched_bytes == dfield_get_len(
700
 
                    dtuple_get_nth_field(dtuple, n_fields - 1))) {
701
 
                return(TRUE);
702
 
        }
703
 
 
704
 
        return(FALSE);
705
 
}
706
 
 
707
 
#ifndef UNIV_HOTBACKUP
708
 
/*****************************************************************
709
 
Compare two physical records that contain the same number of columns,
710
 
none of which are stored externally. */
711
 
UNIV_INTERN
712
 
int
713
 
cmp_rec_rec_simple(
714
 
/*===============*/
715
 
                                        /* out: 1, 0 , -1 if rec1 is greater,
716
 
                                        equal, less, respectively, than rec2 */
717
 
        const rec_t*            rec1,   /* in: physical record */
718
 
        const rec_t*            rec2,   /* in: physical record */
719
 
        const ulint*            offsets1,/* in: rec_get_offsets(rec1, index) */
720
 
        const ulint*            offsets2,/* in: rec_get_offsets(rec2, index) */
721
 
        const dict_index_t*     index)  /* in: data dictionary index */
722
 
{
723
 
        ulint           rec1_f_len;     /* length of current field in rec1 */
724
 
        const byte*     rec1_b_ptr;     /* pointer to the current byte
725
 
                                        in rec1 field */
726
 
        ulint           rec1_byte;      /* value of current byte to be
727
 
                                        compared in rec1 */
728
 
        ulint           rec2_f_len;     /* length of current field in rec2 */
729
 
        const byte*     rec2_b_ptr;     /* pointer to the current byte
730
 
                                        in rec2 field */
731
 
        ulint           rec2_byte;      /* value of current byte to be
732
 
                                        compared in rec2 */
733
 
        ulint           cur_field;      /* current field number */
734
 
        ulint           n_uniq;
735
 
 
736
 
        n_uniq = dict_index_get_n_unique(index);
737
 
        ut_ad(rec_offs_n_fields(offsets1) >= n_uniq);
738
 
        ut_ad(rec_offs_n_fields(offsets2) >= n_uniq);
739
 
 
740
 
        ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
741
 
 
742
 
        for (cur_field = 0; cur_field < n_uniq; cur_field++) {
743
 
 
744
 
                ulint   cur_bytes;
745
 
                ulint   mtype;
746
 
                ulint   prtype;
747
 
 
748
 
                {
749
 
                        const dict_col_t*       col
750
 
                                = dict_index_get_nth_col(index, cur_field);
751
 
 
752
 
                        mtype = col->mtype;
753
 
                        prtype = col->prtype;
754
 
                }
755
 
 
756
 
                ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
757
 
                ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
758
 
 
759
 
                rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
760
 
                                               cur_field, &rec1_f_len);
761
 
                rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
762
 
                                               cur_field, &rec2_f_len);
763
 
 
764
 
                if (rec1_f_len == UNIV_SQL_NULL
765
 
                    || rec2_f_len == UNIV_SQL_NULL) {
766
 
 
767
 
                        if (rec1_f_len == rec2_f_len) {
768
 
 
769
 
                                goto next_field;
770
 
 
771
 
                        } else if (rec2_f_len == UNIV_SQL_NULL) {
772
 
 
773
 
                                /* We define the SQL null to be the
774
 
                                smallest possible value of a field
775
 
                                in the alphabetical order */
776
 
 
777
 
                                return(1);
778
 
                        } else {
779
 
                                return(-1);
780
 
                        }
781
 
                }
782
 
 
783
 
                if (mtype >= DATA_FLOAT
784
 
                    || (mtype == DATA_BLOB
785
 
                        && 0 == (prtype & DATA_BINARY_TYPE)
786
 
                        && dtype_get_charset_coll(prtype)
787
 
                        != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
788
 
                        int ret = cmp_whole_field(mtype, prtype,
789
 
                                                  rec1_b_ptr,
790
 
                                                  (unsigned) rec1_f_len,
791
 
                                                  rec2_b_ptr,
792
 
                                                  (unsigned) rec2_f_len);
793
 
                        if (ret) {
794
 
                                return(ret);
795
 
                        }
796
 
 
797
 
                        goto next_field;
798
 
                }
799
 
 
800
 
                /* Compare the fields */
801
 
                for (cur_bytes = 0;; cur_bytes++, rec1_b_ptr++, rec2_b_ptr++) {
802
 
                        if (rec2_f_len <= cur_bytes) {
803
 
 
804
 
                                if (rec1_f_len <= cur_bytes) {
805
 
 
806
 
                                        goto next_field;
807
 
                                }
808
 
 
809
 
                                rec2_byte = dtype_get_pad_char(mtype, prtype);
810
 
 
811
 
                                if (rec2_byte == ULINT_UNDEFINED) {
812
 
                                        return(1);
813
 
                                }
814
 
                        } else {
815
 
                                rec2_byte = *rec2_b_ptr;
816
 
                        }
817
 
 
818
 
                        if (rec1_f_len <= cur_bytes) {
819
 
                                rec1_byte = dtype_get_pad_char(mtype, prtype);
820
 
 
821
 
                                if (rec1_byte == ULINT_UNDEFINED) {
822
 
                                        return(-1);
823
 
                                }
824
 
                        } else {
825
 
                                rec1_byte = *rec1_b_ptr;
826
 
                        }
827
 
 
828
 
                        if (rec1_byte == rec2_byte) {
829
 
                                /* If the bytes are equal, they will remain
830
 
                                such even after the collation transformation
831
 
                                below */
832
 
 
833
 
                                continue;
834
 
                        }
835
 
 
836
 
                        if (mtype <= DATA_CHAR
837
 
                            || (mtype == DATA_BLOB
838
 
                                && !(prtype & DATA_BINARY_TYPE))) {
839
 
 
840
 
                                rec1_byte = cmp_collate(rec1_byte);
841
 
                                rec2_byte = cmp_collate(rec2_byte);
842
 
                        }
843
 
 
844
 
                        if (rec1_byte < rec2_byte) {
845
 
                                return(-1);
846
 
                        } else if (rec1_byte > rec2_byte) {
847
 
                                return(1);
848
 
                        }
849
 
                }
850
 
next_field:
851
 
                continue;
852
 
        }
853
 
 
854
 
        /* If we ran out of fields, rec1 was equal to rec2. */
855
 
        return(0);
856
 
}
857
 
#endif /* !UNIV_HOTBACKUP */
858
 
 
859
 
/*****************************************************************
860
 
This function is used to compare two physical records. Only the common
861
 
first fields are compared, and if an externally stored field is
862
 
encountered, then 0 is returned. */
863
 
UNIV_INTERN
864
 
int
865
 
cmp_rec_rec_with_match(
866
 
/*===================*/
867
 
                                /* out: 1, 0 , -1 if rec1 is greater, equal,
868
 
                                less, respectively, than rec2; only the common
869
 
                                first fields are compared */
870
 
        const rec_t*    rec1,   /* in: physical record */
871
 
        const rec_t*    rec2,   /* in: physical record */
872
 
        const ulint*    offsets1,/* in: rec_get_offsets(rec1, index) */
873
 
        const ulint*    offsets2,/* in: rec_get_offsets(rec2, index) */
874
 
        dict_index_t*   index,  /* in: data dictionary index */
875
 
        ulint*          matched_fields, /* in/out: number of already completely
876
 
                                matched fields; when the function returns,
877
 
                                contains the value the for current
878
 
                                comparison */
879
 
        ulint*          matched_bytes) /* in/out: number of already matched
880
 
                                bytes within the first field not completely
881
 
                                matched; when the function returns, contains
882
 
                                the value for the current comparison */
883
 
{
884
 
#ifndef UNIV_HOTBACKUP
885
 
        ulint           rec1_n_fields;  /* the number of fields in rec */
886
 
        ulint           rec1_f_len;     /* length of current field in rec */
887
 
        const byte*     rec1_b_ptr;     /* pointer to the current byte
888
 
                                        in rec field */
889
 
        ulint           rec1_byte;      /* value of current byte to be
890
 
                                        compared in rec */
891
 
        ulint           rec2_n_fields;  /* the number of fields in rec */
892
 
        ulint           rec2_f_len;     /* length of current field in rec */
893
 
        const byte*     rec2_b_ptr;     /* pointer to the current byte
894
 
                                        in rec field */
895
 
        ulint           rec2_byte;      /* value of current byte to be
896
 
                                        compared in rec */
897
 
        ulint           cur_field;      /* current field number */
898
 
        ulint           cur_bytes;      /* number of already matched
899
 
                                        bytes in current field */
900
 
        int             ret = 0;        /* return value */
901
 
        ulint           comp;
902
 
 
903
 
        ut_ad(rec1 && rec2 && index);
904
 
        ut_ad(rec_offs_validate(rec1, index, offsets1));
905
 
        ut_ad(rec_offs_validate(rec2, index, offsets2));
906
 
        ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
907
 
 
908
 
        comp = rec_offs_comp(offsets1);
909
 
        rec1_n_fields = rec_offs_n_fields(offsets1);
910
 
        rec2_n_fields = rec_offs_n_fields(offsets2);
911
 
 
912
 
        cur_field = *matched_fields;
913
 
        cur_bytes = *matched_bytes;
914
 
 
915
 
        /* Match fields in a loop */
916
 
 
917
 
        while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
918
 
 
919
 
                ulint   mtype;
920
 
                ulint   prtype;
921
 
 
922
 
                if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
923
 
                        /* This is for the insert buffer B-tree. */
924
 
                        mtype = DATA_BINARY;
925
 
                        prtype = 0;
926
 
                } else {
927
 
                        const dict_col_t*       col
928
 
                                = dict_index_get_nth_col(index, cur_field);
929
 
 
930
 
                        mtype = col->mtype;
931
 
                        prtype = col->prtype;
932
 
                }
933
 
 
934
 
                rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
935
 
                                               cur_field, &rec1_f_len);
936
 
                rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
937
 
                                               cur_field, &rec2_f_len);
938
 
 
939
 
                if (cur_bytes == 0) {
940
 
                        if (cur_field == 0) {
941
 
                                /* Test if rec is the predefined minimum
942
 
                                record */
943
 
                                if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
944
 
                                                  & REC_INFO_MIN_REC_FLAG)) {
945
 
 
946
 
                                        if (!(rec_get_info_bits(rec2, comp)
947
 
                                              & REC_INFO_MIN_REC_FLAG)) {
948
 
                                                ret = -1;
949
 
                                        }
950
 
 
951
 
                                        goto order_resolved;
952
 
 
953
 
                                } else if (UNIV_UNLIKELY
954
 
                                           (rec_get_info_bits(rec2, comp)
955
 
                                            & REC_INFO_MIN_REC_FLAG)) {
956
 
 
957
 
                                        ret = 1;
958
 
 
959
 
                                        goto order_resolved;
960
 
                                }
961
 
                        }
962
 
 
963
 
                        if (rec_offs_nth_extern(offsets1, cur_field)
964
 
                            || rec_offs_nth_extern(offsets2, cur_field)) {
965
 
                                /* We do not compare to an externally
966
 
                                stored field */
967
 
 
968
 
                                goto order_resolved;
969
 
                        }
970
 
 
971
 
                        if (rec1_f_len == UNIV_SQL_NULL
972
 
                            || rec2_f_len == UNIV_SQL_NULL) {
973
 
 
974
 
                                if (rec1_f_len == rec2_f_len) {
975
 
 
976
 
                                        goto next_field;
977
 
 
978
 
                                } else if (rec2_f_len == UNIV_SQL_NULL) {
979
 
 
980
 
                                        /* We define the SQL null to be the
981
 
                                        smallest possible value of a field
982
 
                                        in the alphabetical order */
983
 
 
984
 
                                        ret = 1;
985
 
                                } else {
986
 
                                        ret = -1;
987
 
                                }
988
 
 
989
 
                                goto order_resolved;
990
 
                        }
991
 
                }
992
 
 
993
 
                if (mtype >= DATA_FLOAT
994
 
                    || (mtype == DATA_BLOB
995
 
                        && 0 == (prtype & DATA_BINARY_TYPE)
996
 
                        && dtype_get_charset_coll(prtype)
997
 
                        != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
998
 
 
999
 
                        ret = cmp_whole_field(mtype, prtype,
1000
 
                                              rec1_b_ptr,
1001
 
                                              (unsigned) rec1_f_len,
1002
 
                                              rec2_b_ptr,
1003
 
                                              (unsigned) rec2_f_len);
1004
 
                        if (ret != 0) {
1005
 
                                cur_bytes = 0;
1006
 
 
1007
 
                                goto order_resolved;
1008
 
                        } else {
1009
 
                                goto next_field;
1010
 
                        }
1011
 
                }
1012
 
 
1013
 
                /* Set the pointers at the current byte */
1014
 
                rec1_b_ptr = rec1_b_ptr + cur_bytes;
1015
 
                rec2_b_ptr = rec2_b_ptr + cur_bytes;
1016
 
 
1017
 
                /* Compare then the fields */
1018
 
                for (;;) {
1019
 
                        if (rec2_f_len <= cur_bytes) {
1020
 
 
1021
 
                                if (rec1_f_len <= cur_bytes) {
1022
 
 
1023
 
                                        goto next_field;
1024
 
                                }
1025
 
 
1026
 
                                rec2_byte = dtype_get_pad_char(mtype, prtype);
1027
 
 
1028
 
                                if (rec2_byte == ULINT_UNDEFINED) {
1029
 
                                        ret = 1;
1030
 
 
1031
 
                                        goto order_resolved;
1032
 
                                }
1033
 
                        } else {
1034
 
                                rec2_byte = *rec2_b_ptr;
1035
 
                        }
1036
 
 
1037
 
                        if (rec1_f_len <= cur_bytes) {
1038
 
                                rec1_byte = dtype_get_pad_char(mtype, prtype);
1039
 
 
1040
 
                                if (rec1_byte == ULINT_UNDEFINED) {
1041
 
                                        ret = -1;
1042
 
 
1043
 
                                        goto order_resolved;
1044
 
                                }
1045
 
                        } else {
1046
 
                                rec1_byte = *rec1_b_ptr;
1047
 
                        }
1048
 
 
1049
 
                        if (rec1_byte == rec2_byte) {
1050
 
                                /* If the bytes are equal, they will remain
1051
 
                                such even after the collation transformation
1052
 
                                below */
1053
 
 
1054
 
                                goto next_byte;
1055
 
                        }
1056
 
 
1057
 
                        if (mtype <= DATA_CHAR
1058
 
                            || (mtype == DATA_BLOB
1059
 
                                && !(prtype & DATA_BINARY_TYPE))) {
1060
 
 
1061
 
                                rec1_byte = cmp_collate(rec1_byte);
1062
 
                                rec2_byte = cmp_collate(rec2_byte);
1063
 
                        }
1064
 
 
1065
 
                        if (rec1_byte < rec2_byte) {
1066
 
                                ret = -1;
1067
 
                                goto order_resolved;
1068
 
                        } else if (rec1_byte > rec2_byte) {
1069
 
                                ret = 1;
1070
 
                                goto order_resolved;
1071
 
                        }
1072
 
next_byte:
1073
 
                        /* Next byte */
1074
 
 
1075
 
                        cur_bytes++;
1076
 
                        rec1_b_ptr++;
1077
 
                        rec2_b_ptr++;
1078
 
                }
1079
 
 
1080
 
next_field:
1081
 
                cur_field++;
1082
 
                cur_bytes = 0;
1083
 
        }
1084
 
 
1085
 
        ut_ad(cur_bytes == 0);
1086
 
 
1087
 
        /* If we ran out of fields, rec1 was equal to rec2 up
1088
 
        to the common fields */
1089
 
        ut_ad(ret == 0);
1090
 
order_resolved:
1091
 
 
1092
 
        ut_ad((ret >= - 1) && (ret <= 1));
1093
 
 
1094
 
        *matched_fields = cur_field;
1095
 
        *matched_bytes = cur_bytes;
1096
 
 
1097
 
        return(ret);
1098
 
#else /* !UNIV_HOTBACKUP */
1099
 
        /* This function depends on MySQL code that is not included in
1100
 
        InnoDB Hot Backup builds.  Besides, this function should never
1101
 
        be called in InnoDB Hot Backup. */
1102
 
        ut_error;
1103
 
        return(0);
1104
 
#endif /* !UNIV_HOTBACKUP */
1105
 
}
1106
 
 
1107
 
#ifdef UNIV_DEBUG
1108
 
/*****************************************************************
1109
 
Used in debug checking of cmp_dtuple_... .
1110
 
This function is used to compare a data tuple to a physical record. If
1111
 
dtuple has n fields then rec must have either m >= n fields, or it must
1112
 
differ from dtuple in some of the m fields rec has. If encounters an
1113
 
externally stored field, returns 0. */
1114
 
static
1115
 
int
1116
 
cmp_debug_dtuple_rec_with_match(
1117
 
/*============================*/
1118
 
                                /* out: 1, 0, -1, if dtuple is greater, equal,
1119
 
                                less than rec, respectively, when only the
1120
 
                                common first fields are compared */
1121
 
        const dtuple_t* dtuple, /* in: data tuple */
1122
 
        const rec_t*    rec,    /* in: physical record which differs from
1123
 
                                dtuple in some of the common fields, or which
1124
 
                                has an equal number or more fields than
1125
 
                                dtuple */
1126
 
        const ulint*    offsets,/* in: array returned by rec_get_offsets() */
1127
 
        ulint*          matched_fields) /* in/out: number of already
1128
 
                                completely matched fields; when function
1129
 
                                returns, contains the value for current
1130
 
                                comparison */
1131
 
{
1132
 
        const dfield_t* dtuple_field;   /* current field in logical record */
1133
 
        ulint           dtuple_f_len;   /* the length of the current field
1134
 
                                        in the logical record */
1135
 
        const byte*     dtuple_f_data;  /* pointer to the current logical
1136
 
                                        field data */
1137
 
        ulint           rec_f_len;      /* length of current field in rec */
1138
 
        const byte*     rec_f_data;     /* pointer to the current rec field */
1139
 
        int             ret = 3333;     /* return value */
1140
 
        ulint           cur_field;      /* current field number */
1141
 
 
1142
 
        ut_ad(dtuple && rec && matched_fields);
1143
 
        ut_ad(dtuple_check_typed(dtuple));
1144
 
        ut_ad(rec_offs_validate(rec, NULL, offsets));
1145
 
 
1146
 
        ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
1147
 
        ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
1148
 
 
1149
 
        cur_field = *matched_fields;
1150
 
 
1151
 
        if (cur_field == 0) {
1152
 
                if (UNIV_UNLIKELY
1153
 
                    (rec_get_info_bits(rec, rec_offs_comp(offsets))
1154
 
                     & REC_INFO_MIN_REC_FLAG)) {
1155
 
 
1156
 
                        ret = !(dtuple_get_info_bits(dtuple)
1157
 
                                & REC_INFO_MIN_REC_FLAG);
1158
 
 
1159
 
                        goto order_resolved;
1160
 
                }
1161
 
 
1162
 
                if (UNIV_UNLIKELY
1163
 
                    (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
1164
 
                        ret = -1;
1165
 
 
1166
 
                        goto order_resolved;
1167
 
                }
1168
 
        }
1169
 
 
1170
 
        /* Match fields in a loop; stop if we run out of fields in dtuple */
1171
 
 
1172
 
        while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
1173
 
 
1174
 
                ulint   mtype;
1175
 
                ulint   prtype;
1176
 
 
1177
 
                dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
1178
 
                {
1179
 
                        const dtype_t*  type
1180
 
                                = dfield_get_type(dtuple_field);
1181
 
 
1182
 
                        mtype = type->mtype;
1183
 
                        prtype = type->prtype;
1184
 
                }
1185
 
 
1186
 
                dtuple_f_data = dfield_get_data(dtuple_field);
1187
 
                dtuple_f_len = dfield_get_len(dtuple_field);
1188
 
 
1189
 
                rec_f_data = rec_get_nth_field(rec, offsets,
1190
 
                                               cur_field, &rec_f_len);
1191
 
 
1192
 
                if (rec_offs_nth_extern(offsets, cur_field)) {
1193
 
                        /* We do not compare to an externally stored field */
1194
 
 
1195
 
                        ret = 0;
1196
 
 
1197
 
                        goto order_resolved;
1198
 
                }
1199
 
 
1200
 
                ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
1201
 
                                    rec_f_data, rec_f_len);
1202
 
                if (ret != 0) {
1203
 
                        goto order_resolved;
1204
 
                }
1205
 
 
1206
 
                cur_field++;
1207
 
        }
1208
 
 
1209
 
        ret = 0;        /* If we ran out of fields, dtuple was equal to rec
1210
 
                        up to the common fields */
1211
 
order_resolved:
1212
 
        ut_ad((ret >= - 1) && (ret <= 1));
1213
 
 
1214
 
        *matched_fields = cur_field;
1215
 
 
1216
 
        return(ret);
1217
 
}
1218
 
#endif /* UNIV_DEBUG */