1
/***********************************************************************
2
Comparison services for records
4
(c) 1994-1996 Innobase Oy
6
Created 7/1/1994 Heikki Tuuri
7
************************************************************************/
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.
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. */
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. */
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
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
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! */
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,
76
const unsigned char* b, /* in: data field */
77
unsigned int b_length); /* in: data field length,
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. */
88
/* out: collation order position */
89
ulint code) /* in: code of a character stored in database record */
91
return((ulint) srv_latin1_ordering[code]);
94
/*****************************************************************
95
Returns TRUE if two columns are equal for comparison purposes. */
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 */
107
if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
108
&& dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
110
/* Both are non-binary string types: they can be compared if
111
and only if the charset-collation is the same */
113
if (check_charsets) {
114
return(dtype_get_charset_coll(col1->prtype)
115
== dtype_get_charset_coll(col2->prtype));
121
if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
122
&& dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
124
/* Both are binary string types: they can be compared */
129
if (col1->mtype != col2->mtype) {
134
if (col1->mtype == DATA_INT
135
&& (col1->prtype & DATA_UNSIGNED)
136
!= (col2->prtype & DATA_UNSIGNED)) {
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. */
145
return(col1->mtype != DATA_INT || col1->len == col2->len);
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 */
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,
163
const byte* b, /* in: data field */
164
unsigned int b_length) /* in: data field length,
176
/* Remove preceding spaces */
177
for (; a_length && *a == ' '; a++, a_length--);
178
for (; b_length && *b == ' '; b++, b_length--);
191
} else if (*b == '-') {
196
while (a_length > 0 && (*a == '+' || *a == '0')) {
200
while (b_length > 0 && (*b == '+' || *b == '0')) {
204
if (a_length != b_length) {
205
if (a_length < b_length) {
212
while (a_length > 0 && *a == *b) {
214
a++; b++; a_length--;
228
d_1 = mach_double_read(a);
229
d_2 = mach_double_read(b);
233
} else if (d_2 > d_1) {
240
f_1 = mach_float_read(a);
241
f_2 = mach_float_read(b);
245
} else if (f_2 > f_1) {
251
if (prtype & DATA_BINARY_TYPE) {
253
ut_print_timestamp(stderr);
255
" InnoDB: Error: comparing a binary BLOB"
256
" with a character set sensitive\n"
257
"InnoDB: comparison!\n");
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));
268
"InnoDB: unknown type number %lu\n",
275
#endif /* !UNIV_HOTBACKUP */
277
/*****************************************************************
278
This function is used to compare two data fields for which we know the
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
290
ulint len1, /* in: data field length or UNIV_SQL_NULL */
291
const byte* data2, /* in: data field (== a pointer to a memory
293
ulint len2) /* in: data field length or UNIV_SQL_NULL */
295
#ifndef UNIV_HOTBACKUP
300
if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
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 */
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)) {
323
return(cmp_whole_field(mtype, prtype,
324
data1, (unsigned) len1,
325
data2, (unsigned) len2));
328
/* Compare then the fields */
333
if (len1 <= cur_bytes) {
334
if (len2 <= cur_bytes) {
339
data1_byte = dtype_get_pad_char(mtype, prtype);
341
if (data1_byte == ULINT_UNDEFINED) {
349
if (len2 <= cur_bytes) {
350
data2_byte = dtype_get_pad_char(mtype, prtype);
352
if (data2_byte == ULINT_UNDEFINED) {
360
if (data1_byte == data2_byte) {
361
/* If the bytes are equal, they will remain such even
362
after the collation transformation below */
367
if (mtype <= DATA_CHAR
368
|| (mtype == DATA_BLOB
369
&& 0 == (prtype & DATA_BINARY_TYPE))) {
371
data1_byte = cmp_collate(data1_byte);
372
data2_byte = cmp_collate(data2_byte);
375
if (data1_byte > data2_byte) {
378
} else if (data1_byte < data2_byte) {
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. */
393
#endif /* !UNIV_HOTBACKUP */
395
return(0); /* Not reached */
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
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
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
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 */
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
437
ulint rec_f_len; /* length of current field in rec */
438
const byte* rec_b_ptr; /* pointer to the current byte in
440
ulint rec_byte; /* value of current byte to be
442
ulint cur_field; /* current field number */
443
ulint cur_bytes; /* number of already matched bytes
445
int ret = 3333; /* return value */
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));
451
cur_field = *matched_fields;
452
cur_bytes = *matched_bytes;
454
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
455
ut_ad(cur_field <= rec_offs_n_fields(offsets));
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);
462
if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
463
ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
465
} else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
471
/* Match fields in a loop; stop if we run out of fields in dtuple
472
or find an externally stored field */
474
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
479
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
482
= dfield_get_type(dtuple_field);
485
prtype = type->prtype;
488
dtuple_f_len = dfield_get_len(dtuple_field);
490
rec_b_ptr = rec_get_nth_field(rec, offsets,
491
cur_field, &rec_f_len);
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
498
if (UNIV_LIKELY(cur_bytes == 0)) {
499
if (rec_offs_nth_extern(offsets, cur_field)) {
500
/* We do not compare to an externally
508
if (dtuple_f_len == UNIV_SQL_NULL) {
509
if (rec_f_len == UNIV_SQL_NULL) {
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 */
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)) {
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);
546
/* Set the pointers at the current byte */
548
rec_b_ptr = rec_b_ptr + cur_bytes;
549
dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
551
/* Compare then the fields */
554
if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
555
if (dtuple_f_len <= cur_bytes) {
560
rec_byte = dtype_get_pad_char(mtype, prtype);
562
if (rec_byte == ULINT_UNDEFINED) {
568
rec_byte = *rec_b_ptr;
571
if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
572
dtuple_byte = dtype_get_pad_char(mtype,
575
if (dtuple_byte == ULINT_UNDEFINED) {
581
dtuple_byte = *dtuple_b_ptr;
584
if (dtuple_byte == rec_byte) {
585
/* If the bytes are equal, they will
586
remain such even after the collation
587
transformation below */
592
if (mtype <= DATA_CHAR
593
|| (mtype == DATA_BLOB
594
&& !(prtype & DATA_BINARY_TYPE))) {
596
rec_byte = cmp_collate(rec_byte);
597
dtuple_byte = cmp_collate(dtuple_byte);
600
ret = (int) (dtuple_byte - rec_byte);
601
if (UNIV_LIKELY(ret)) {
622
ut_ad(cur_bytes == 0);
624
ret = 0; /* If we ran out of fields, dtuple was equal to rec
625
up to the common fields */
627
ut_ad((ret >= - 1) && (ret <= 1));
628
ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
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;
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. */
643
#endif /* !UNIV_HOTBACKUP */
646
/******************************************************************
647
Compares a data tuple to a physical record. */
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() */
659
ulint matched_fields = 0;
660
ulint matched_bytes = 0;
662
ut_ad(rec_offs_validate(rec, NULL, offsets));
663
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
664
&matched_fields, &matched_bytes));
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. */
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() */
680
ulint matched_fields = 0;
681
ulint matched_bytes = 0;
683
ut_ad(rec_offs_validate(rec, NULL, offsets));
684
n_fields = dtuple_get_n_fields(dtuple);
686
if (n_fields > rec_offs_n_fields(offsets)) {
691
cmp_dtuple_rec_with_match(dtuple, rec, offsets,
692
&matched_fields, &matched_bytes);
693
if (matched_fields == n_fields) {
698
if (matched_fields == n_fields - 1
699
&& matched_bytes == dfield_get_len(
700
dtuple_get_nth_field(dtuple, n_fields - 1))) {
707
#ifndef UNIV_HOTBACKUP
708
/*****************************************************************
709
Compare two physical records that contain the same number of columns,
710
none of which are stored externally. */
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 */
723
ulint rec1_f_len; /* length of current field in rec1 */
724
const byte* rec1_b_ptr; /* pointer to the current byte
726
ulint rec1_byte; /* value of current byte to be
728
ulint rec2_f_len; /* length of current field in rec2 */
729
const byte* rec2_b_ptr; /* pointer to the current byte
731
ulint rec2_byte; /* value of current byte to be
733
ulint cur_field; /* current field number */
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);
740
ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
742
for (cur_field = 0; cur_field < n_uniq; cur_field++) {
749
const dict_col_t* col
750
= dict_index_get_nth_col(index, cur_field);
753
prtype = col->prtype;
756
ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
757
ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
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);
764
if (rec1_f_len == UNIV_SQL_NULL
765
|| rec2_f_len == UNIV_SQL_NULL) {
767
if (rec1_f_len == rec2_f_len) {
771
} else if (rec2_f_len == UNIV_SQL_NULL) {
773
/* We define the SQL null to be the
774
smallest possible value of a field
775
in the alphabetical order */
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,
790
(unsigned) rec1_f_len,
792
(unsigned) rec2_f_len);
800
/* Compare the fields */
801
for (cur_bytes = 0;; cur_bytes++, rec1_b_ptr++, rec2_b_ptr++) {
802
if (rec2_f_len <= cur_bytes) {
804
if (rec1_f_len <= cur_bytes) {
809
rec2_byte = dtype_get_pad_char(mtype, prtype);
811
if (rec2_byte == ULINT_UNDEFINED) {
815
rec2_byte = *rec2_b_ptr;
818
if (rec1_f_len <= cur_bytes) {
819
rec1_byte = dtype_get_pad_char(mtype, prtype);
821
if (rec1_byte == ULINT_UNDEFINED) {
825
rec1_byte = *rec1_b_ptr;
828
if (rec1_byte == rec2_byte) {
829
/* If the bytes are equal, they will remain
830
such even after the collation transformation
836
if (mtype <= DATA_CHAR
837
|| (mtype == DATA_BLOB
838
&& !(prtype & DATA_BINARY_TYPE))) {
840
rec1_byte = cmp_collate(rec1_byte);
841
rec2_byte = cmp_collate(rec2_byte);
844
if (rec1_byte < rec2_byte) {
846
} else if (rec1_byte > rec2_byte) {
854
/* If we ran out of fields, rec1 was equal to rec2. */
857
#endif /* !UNIV_HOTBACKUP */
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. */
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
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 */
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
889
ulint rec1_byte; /* value of current byte to be
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
895
ulint rec2_byte; /* value of current byte to be
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 */
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));
908
comp = rec_offs_comp(offsets1);
909
rec1_n_fields = rec_offs_n_fields(offsets1);
910
rec2_n_fields = rec_offs_n_fields(offsets2);
912
cur_field = *matched_fields;
913
cur_bytes = *matched_bytes;
915
/* Match fields in a loop */
917
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
922
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
923
/* This is for the insert buffer B-tree. */
927
const dict_col_t* col
928
= dict_index_get_nth_col(index, cur_field);
931
prtype = col->prtype;
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);
939
if (cur_bytes == 0) {
940
if (cur_field == 0) {
941
/* Test if rec is the predefined minimum
943
if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
944
& REC_INFO_MIN_REC_FLAG)) {
946
if (!(rec_get_info_bits(rec2, comp)
947
& REC_INFO_MIN_REC_FLAG)) {
953
} else if (UNIV_UNLIKELY
954
(rec_get_info_bits(rec2, comp)
955
& REC_INFO_MIN_REC_FLAG)) {
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
971
if (rec1_f_len == UNIV_SQL_NULL
972
|| rec2_f_len == UNIV_SQL_NULL) {
974
if (rec1_f_len == rec2_f_len) {
978
} else if (rec2_f_len == UNIV_SQL_NULL) {
980
/* We define the SQL null to be the
981
smallest possible value of a field
982
in the alphabetical order */
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)) {
999
ret = cmp_whole_field(mtype, prtype,
1001
(unsigned) rec1_f_len,
1003
(unsigned) rec2_f_len);
1007
goto order_resolved;
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;
1017
/* Compare then the fields */
1019
if (rec2_f_len <= cur_bytes) {
1021
if (rec1_f_len <= cur_bytes) {
1026
rec2_byte = dtype_get_pad_char(mtype, prtype);
1028
if (rec2_byte == ULINT_UNDEFINED) {
1031
goto order_resolved;
1034
rec2_byte = *rec2_b_ptr;
1037
if (rec1_f_len <= cur_bytes) {
1038
rec1_byte = dtype_get_pad_char(mtype, prtype);
1040
if (rec1_byte == ULINT_UNDEFINED) {
1043
goto order_resolved;
1046
rec1_byte = *rec1_b_ptr;
1049
if (rec1_byte == rec2_byte) {
1050
/* If the bytes are equal, they will remain
1051
such even after the collation transformation
1057
if (mtype <= DATA_CHAR
1058
|| (mtype == DATA_BLOB
1059
&& !(prtype & DATA_BINARY_TYPE))) {
1061
rec1_byte = cmp_collate(rec1_byte);
1062
rec2_byte = cmp_collate(rec2_byte);
1065
if (rec1_byte < rec2_byte) {
1067
goto order_resolved;
1068
} else if (rec1_byte > rec2_byte) {
1070
goto order_resolved;
1085
ut_ad(cur_bytes == 0);
1087
/* If we ran out of fields, rec1 was equal to rec2 up
1088
to the common fields */
1092
ut_ad((ret >= - 1) && (ret <= 1));
1094
*matched_fields = cur_field;
1095
*matched_bytes = cur_bytes;
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. */
1104
#endif /* !UNIV_HOTBACKUP */
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. */
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
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
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
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 */
1142
ut_ad(dtuple && rec && matched_fields);
1143
ut_ad(dtuple_check_typed(dtuple));
1144
ut_ad(rec_offs_validate(rec, NULL, offsets));
1146
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
1147
ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
1149
cur_field = *matched_fields;
1151
if (cur_field == 0) {
1153
(rec_get_info_bits(rec, rec_offs_comp(offsets))
1154
& REC_INFO_MIN_REC_FLAG)) {
1156
ret = !(dtuple_get_info_bits(dtuple)
1157
& REC_INFO_MIN_REC_FLAG);
1159
goto order_resolved;
1163
(dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
1166
goto order_resolved;
1170
/* Match fields in a loop; stop if we run out of fields in dtuple */
1172
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
1177
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
1180
= dfield_get_type(dtuple_field);
1182
mtype = type->mtype;
1183
prtype = type->prtype;
1186
dtuple_f_data = dfield_get_data(dtuple_field);
1187
dtuple_f_len = dfield_get_len(dtuple_field);
1189
rec_f_data = rec_get_nth_field(rec, offsets,
1190
cur_field, &rec_f_len);
1192
if (rec_offs_nth_extern(offsets, cur_field)) {
1193
/* We do not compare to an externally stored field */
1197
goto order_resolved;
1200
ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
1201
rec_f_data, rec_f_len);
1203
goto order_resolved;
1209
ret = 0; /* If we ran out of fields, dtuple was equal to rec
1210
up to the common fields */
1212
ut_ad((ret >= - 1) && (ret <= 1));
1214
*matched_fields = cur_field;
1218
#endif /* UNIV_DEBUG */