1
/*****************************************************************************
3
Copyright (C) 1994, 2009, Innobase Oy. All Rights Reserved.
5
This program is free software; you can redistribute it and/or modify it under
6
the terms of the GNU General Public License as published by the Free Software
7
Foundation; version 2 of the License.
9
This program is distributed in the hope that it will be useful, but WITHOUT
10
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
13
You should have received a copy of the GNU General Public License along with
14
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
15
St, Fifth Floor, Boston, MA 02110-1301 USA
17
*****************************************************************************/
19
/*******************************************************************//**
21
Comparison services for records
23
Created 7/1/1994 Heikki Tuuri
24
************************************************************************/
37
The records are put into alphabetical order in the following
38
way: let F be the first field where two records disagree.
39
If there is a character in some position n where the the
40
records disagree, the order is determined by comparison of
41
the characters at position n, possibly after
42
collating transformation. If there is no such character,
43
but the corresponding fields have different lengths, then
44
if the data type of the fields is paddable,
45
shorter field is padded with a padding character. If the
46
data type is not paddable, longer field is considered greater.
47
Finally, the SQL null is bigger than any other value.
49
At the present, the comparison functions return 0 in the case,
50
where two records disagree only in the way that one
51
has more fields than the other. */
54
/*************************************************************//**
55
Used in debug checking of cmp_dtuple_... .
56
This function is used to compare a data tuple to a physical record. If
57
dtuple has n fields then rec must have either m >= n fields, or it must
58
differ from dtuple in some of the m fields rec has.
59
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
60
respectively, when only the common first fields are compared */
63
cmp_debug_dtuple_rec_with_match(
64
/*============================*/
65
const dtuple_t* dtuple, /*!< in: data tuple */
66
const rec_t* rec, /*!< in: physical record which differs from
67
dtuple in some of the common fields, or which
68
has an equal number or more fields than
70
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
71
ulint* matched_fields);/*!< in/out: number of already
72
completely matched fields; when function
73
returns, contains the value for current
75
#endif /* UNIV_DEBUG */
76
/*************************************************************//**
77
This function is used to compare two data fields for which the data type
78
is such that we must use MySQL code to compare them. The prototype here
79
must be a copy of the the one in ha_innobase.cc!
80
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
85
int mysql_type, /*!< in: MySQL type */
86
uint charset_number, /*!< in: number of the charset */
87
const unsigned char* a, /*!< in: data field */
88
unsigned int a_length, /*!< in: data field length,
90
const unsigned char* b, /*!< in: data field */
91
unsigned int b_length); /*!< in: data field length,
93
/*********************************************************************//**
94
Transforms the character code so that it is ordered appropriately for the
95
language. This is only used for the latin1 char set. MySQL does the
96
comparisons for other char sets.
97
@return collation order position */
102
ulint code) /*!< in: code of a character stored in database record */
104
return((ulint) srv_latin1_ordering[code]);
107
/*************************************************************//**
108
Returns TRUE if two columns are equal for comparison purposes.
109
@return TRUE if the columns are considered equal in comparisons */
114
const dict_col_t* col1, /*!< in: column 1 */
115
const dict_col_t* col2, /*!< in: column 2 */
116
ibool check_charsets)
117
/*!< in: whether to check charsets */
119
if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
120
&& dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
122
/* Both are non-binary string types: they can be compared if
123
and only if the charset-collation is the same */
125
if (check_charsets) {
126
return(dtype_get_charset_coll(col1->prtype)
127
== dtype_get_charset_coll(col2->prtype));
133
if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
134
&& dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
136
/* Both are binary string types: they can be compared */
141
if (col1->mtype != col2->mtype) {
146
if (col1->mtype == DATA_INT
147
&& (col1->prtype & DATA_UNSIGNED)
148
!= (col2->prtype & DATA_UNSIGNED)) {
150
/* The storage format of an unsigned integer is different
151
from a signed integer: in a signed integer we OR
152
0x8000... to the value of positive integers. */
157
return(col1->mtype != DATA_INT || col1->len == col2->len);
160
/*************************************************************//**
161
Innobase uses this function to compare two data fields for which the data type
162
is such that we must compare whole fields or call MySQL to do the comparison
163
@return 1, 0, -1, if a is greater, equal, less than b, respectively */
168
ulint mtype, /*!< in: main type */
169
ulint prtype, /*!< in: precise type */
170
const byte* a, /*!< in: data field */
171
unsigned int a_length, /*!< in: data field length,
173
const byte* b, /*!< in: data field */
174
unsigned int b_length) /*!< in: data field length,
186
/* Remove preceding spaces */
187
for (; a_length && *a == ' '; a++, a_length--) {}
188
for (; b_length && *b == ' '; b++, b_length--) {}
201
} else if (*b == '-') {
206
while (a_length > 0 && (*a == '+' || *a == '0')) {
210
while (b_length > 0 && (*b == '+' || *b == '0')) {
214
if (a_length != b_length) {
215
if (a_length < b_length) {
222
while (a_length > 0 && *a == *b) {
224
a++; b++; a_length--;
238
d_1 = mach_double_read(a);
239
d_2 = mach_double_read(b);
243
} else if (d_2 > d_1) {
250
f_1 = mach_float_read(a);
251
f_2 = mach_float_read(b);
255
} else if (f_2 > f_1) {
261
if (prtype & DATA_BINARY_TYPE) {
263
ut_print_timestamp(stderr);
265
" InnoDB: Error: comparing a binary BLOB"
266
" with a character set sensitive\n"
267
"InnoDB: comparison!\n");
272
return(innobase_mysql_cmp(
273
(int)(prtype & DATA_MYSQL_TYPE_MASK),
274
(uint)dtype_get_charset_coll(prtype),
275
a, a_length, b, b_length));
278
"InnoDB: unknown type number %lu\n",
286
/*************************************************************//**
287
This function is used to compare two data fields for which we know the
289
@return 1, 0, -1, if data1 is greater, equal, less than data2, respectively */
294
ulint mtype, /*!< in: main type */
295
ulint prtype, /*!< in: precise type */
296
const byte* data1, /*!< in: data field (== a pointer to a memory
298
ulint len1, /*!< in: data field length or UNIV_SQL_NULL */
299
const byte* data2, /*!< in: data field (== a pointer to a memory
301
ulint len2) /*!< in: data field length or UNIV_SQL_NULL */
307
if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
314
if (len1 == UNIV_SQL_NULL) {
315
/* We define the SQL null to be the smallest possible
316
value of a field in the alphabetical order */
324
if (mtype >= DATA_FLOAT
325
|| (mtype == DATA_BLOB
326
&& 0 == (prtype & DATA_BINARY_TYPE)
327
&& dtype_get_charset_coll(prtype)
328
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
330
return(cmp_whole_field(mtype, prtype,
331
data1, (unsigned) len1,
332
data2, (unsigned) len2));
335
/* Compare then the fields */
340
if (len1 <= cur_bytes) {
341
if (len2 <= cur_bytes) {
346
data1_byte = dtype_get_pad_char(mtype, prtype);
348
if (data1_byte == ULINT_UNDEFINED) {
356
if (len2 <= cur_bytes) {
357
data2_byte = dtype_get_pad_char(mtype, prtype);
359
if (data2_byte == ULINT_UNDEFINED) {
367
if (data1_byte == data2_byte) {
368
/* If the bytes are equal, they will remain such even
369
after the collation transformation below */
374
if (mtype <= DATA_CHAR
375
|| (mtype == DATA_BLOB
376
&& 0 == (prtype & DATA_BINARY_TYPE))) {
378
data1_byte = cmp_collate(data1_byte);
379
data2_byte = cmp_collate(data2_byte);
382
if (data1_byte > data2_byte) {
385
} else if (data1_byte < data2_byte) {
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
406
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
407
respectively, when only the common first fields are compared, or until
408
the first externally stored field in rec */
411
cmp_dtuple_rec_with_match(
412
/*======================*/
413
const dtuple_t* dtuple, /*!< in: data tuple */
414
const rec_t* rec, /*!< in: physical record which differs from
415
dtuple in some of the common fields, or which
416
has an equal number or more fields than
418
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
419
ulint* matched_fields, /*!< in/out: number of already completely
420
matched fields; when function returns,
421
contains the value for current comparison */
422
ulint* matched_bytes) /*!< in/out: number of already matched
423
bytes within the first field not completely
424
matched; when function returns, contains the
425
value for current comparison */
427
const dfield_t* dtuple_field; /* current field in logical record */
428
ulint dtuple_f_len; /* the length of the current field
429
in the logical record */
430
const byte* dtuple_b_ptr; /* pointer to the current byte in
431
logical field data */
432
ulint dtuple_byte; /* value of current byte to be compared
434
ulint rec_f_len; /* length of current field in rec */
435
const byte* rec_b_ptr; /* pointer to the current byte in
437
ulint rec_byte; /* value of current byte to be
439
ulint cur_field; /* current field number */
440
ulint cur_bytes; /* number of already matched bytes
442
int ret = 3333; /* return value */
444
ut_ad(dtuple && rec && matched_fields && matched_bytes);
445
ut_ad(dtuple_check_typed(dtuple));
446
ut_ad(rec_offs_validate(rec, NULL, offsets));
448
cur_field = *matched_fields;
449
cur_bytes = *matched_bytes;
451
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
452
ut_ad(cur_field <= rec_offs_n_fields(offsets));
454
if (cur_bytes == 0 && cur_field == 0) {
455
ulint rec_info = rec_get_info_bits(rec,
456
rec_offs_comp(offsets));
457
ulint tup_info = dtuple_get_info_bits(dtuple);
459
if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
460
ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
462
} else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
468
/* Match fields in a loop; stop if we run out of fields in dtuple
469
or find an externally stored field */
471
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
476
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
479
= dfield_get_type(dtuple_field);
482
prtype = type->prtype;
485
dtuple_f_len = dfield_get_len(dtuple_field);
487
rec_b_ptr = rec_get_nth_field(rec, offsets,
488
cur_field, &rec_f_len);
490
/* If we have matched yet 0 bytes, it may be that one or
491
both the fields are SQL null, or the record or dtuple may be
492
the predefined minimum record, or the field is externally
495
if (UNIV_LIKELY(cur_bytes == 0)) {
496
if (rec_offs_nth_extern(offsets, cur_field)) {
497
/* We do not compare to an externally
505
if (dtuple_f_len == UNIV_SQL_NULL) {
506
if (rec_f_len == UNIV_SQL_NULL) {
513
} else if (rec_f_len == UNIV_SQL_NULL) {
514
/* We define the SQL null to be the
515
smallest possible value of a field
516
in the alphabetical order */
523
if (mtype >= DATA_FLOAT
524
|| (mtype == DATA_BLOB
525
&& 0 == (prtype & DATA_BINARY_TYPE)
526
&& dtype_get_charset_coll(prtype)
527
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
529
ret = cmp_whole_field(mtype, prtype,
530
static_cast<const unsigned char *>(dfield_get_data(dtuple_field)),
531
(unsigned) dtuple_f_len,
532
rec_b_ptr, (unsigned) rec_f_len);
543
/* Set the pointers at the current byte */
545
rec_b_ptr = rec_b_ptr + cur_bytes;
546
dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
548
/* Compare then the fields */
551
if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
552
if (dtuple_f_len <= cur_bytes) {
557
rec_byte = dtype_get_pad_char(mtype, prtype);
559
if (rec_byte == ULINT_UNDEFINED) {
565
rec_byte = *rec_b_ptr;
568
if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
569
dtuple_byte = dtype_get_pad_char(mtype,
572
if (dtuple_byte == ULINT_UNDEFINED) {
578
dtuple_byte = *dtuple_b_ptr;
581
if (dtuple_byte == rec_byte) {
582
/* If the bytes are equal, they will
583
remain such even after the collation
584
transformation below */
589
if (mtype <= DATA_CHAR
590
|| (mtype == DATA_BLOB
591
&& !(prtype & DATA_BINARY_TYPE))) {
593
rec_byte = cmp_collate(rec_byte);
594
dtuple_byte = cmp_collate(dtuple_byte);
597
ret = (int) (dtuple_byte - rec_byte);
598
if (UNIV_LIKELY(ret)) {
619
ut_ad(cur_bytes == 0);
621
ret = 0; /* If we ran out of fields, dtuple was equal to rec
622
up to the common fields */
624
ut_ad((ret >= - 1) && (ret <= 1));
625
ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
627
ut_ad(*matched_fields == cur_field); /* In the debug version, the
628
above cmp_debug_... sets
629
*matched_fields to a value */
630
*matched_fields = cur_field;
631
*matched_bytes = cur_bytes;
636
/**************************************************************//**
637
Compares a data tuple to a physical record.
638
@see cmp_dtuple_rec_with_match
639
@return 1, 0, -1, if dtuple is greater, equal, less than rec, respectively */
644
const dtuple_t* dtuple, /*!< in: data tuple */
645
const rec_t* rec, /*!< in: physical record */
646
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
648
ulint matched_fields = 0;
649
ulint matched_bytes = 0;
651
ut_ad(rec_offs_validate(rec, NULL, offsets));
652
return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
653
&matched_fields, &matched_bytes));
656
/**************************************************************//**
657
Checks if a dtuple is a prefix of a record. The last field in dtuple
658
is allowed to be a prefix of the corresponding field in the record.
659
@return TRUE if prefix */
662
cmp_dtuple_is_prefix_of_rec(
663
/*========================*/
664
const dtuple_t* dtuple, /*!< in: data tuple */
665
const rec_t* rec, /*!< in: physical record */
666
const ulint* offsets)/*!< in: array returned by rec_get_offsets() */
669
ulint matched_fields = 0;
670
ulint matched_bytes = 0;
672
ut_ad(rec_offs_validate(rec, NULL, offsets));
673
n_fields = dtuple_get_n_fields(dtuple);
675
if (n_fields > rec_offs_n_fields(offsets)) {
680
cmp_dtuple_rec_with_match(dtuple, rec, offsets,
681
&matched_fields, &matched_bytes);
682
if (matched_fields == n_fields) {
687
if (matched_fields == n_fields - 1
688
&& matched_bytes == dfield_get_len(
689
dtuple_get_nth_field(dtuple, n_fields - 1))) {
696
/*************************************************************//**
697
Compare two physical records that contain the same number of columns,
698
none of which are stored externally.
699
@return 1, 0, -1 if rec1 is greater, equal, less, respectively, than rec2 */
704
const rec_t* rec1, /*!< in: physical record */
705
const rec_t* rec2, /*!< in: physical record */
706
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, ...) */
707
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, ...) */
708
const dict_index_t* index, /*!< in: data dictionary index */
709
ibool* null_eq)/*!< out: set to TRUE if
710
found matching null values */
712
ulint rec1_f_len; /*!< length of current field in rec1 */
713
const byte* rec1_b_ptr; /*!< pointer to the current byte
715
ulint rec1_byte; /*!< value of current byte to be
717
ulint rec2_f_len; /*!< length of current field in rec2 */
718
const byte* rec2_b_ptr; /*!< pointer to the current byte
720
ulint rec2_byte; /*!< value of current byte to be
722
ulint cur_field; /*!< current field number */
725
n_uniq = dict_index_get_n_unique(index);
726
ut_ad(rec_offs_n_fields(offsets1) >= n_uniq);
727
ut_ad(rec_offs_n_fields(offsets2) >= n_uniq);
729
ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
731
for (cur_field = 0; cur_field < n_uniq; cur_field++) {
738
const dict_col_t* col
739
= dict_index_get_nth_col(index, cur_field);
742
prtype = col->prtype;
745
ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
746
ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
748
rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
749
cur_field, &rec1_f_len);
750
rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
751
cur_field, &rec2_f_len);
753
if (rec1_f_len == UNIV_SQL_NULL
754
|| rec2_f_len == UNIV_SQL_NULL) {
756
if (rec1_f_len == rec2_f_len) {
763
} else if (rec2_f_len == UNIV_SQL_NULL) {
765
/* We define the SQL null to be the
766
smallest possible value of a field
767
in the alphabetical order */
775
if (mtype >= DATA_FLOAT
776
|| (mtype == DATA_BLOB
777
&& 0 == (prtype & DATA_BINARY_TYPE)
778
&& dtype_get_charset_coll(prtype)
779
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
780
int ret = cmp_whole_field(mtype, prtype,
782
(unsigned) rec1_f_len,
784
(unsigned) rec2_f_len);
792
/* Compare the fields */
793
for (cur_bytes = 0;; cur_bytes++, rec1_b_ptr++, rec2_b_ptr++) {
794
if (rec2_f_len <= cur_bytes) {
796
if (rec1_f_len <= cur_bytes) {
801
rec2_byte = dtype_get_pad_char(mtype, prtype);
803
if (rec2_byte == ULINT_UNDEFINED) {
807
rec2_byte = *rec2_b_ptr;
810
if (rec1_f_len <= cur_bytes) {
811
rec1_byte = dtype_get_pad_char(mtype, prtype);
813
if (rec1_byte == ULINT_UNDEFINED) {
817
rec1_byte = *rec1_b_ptr;
820
if (rec1_byte == rec2_byte) {
821
/* If the bytes are equal, they will remain
822
such even after the collation transformation
828
if (mtype <= DATA_CHAR
829
|| (mtype == DATA_BLOB
830
&& !(prtype & DATA_BINARY_TYPE))) {
832
rec1_byte = cmp_collate(rec1_byte);
833
rec2_byte = cmp_collate(rec2_byte);
836
if (rec1_byte < rec2_byte) {
838
} else if (rec1_byte > rec2_byte) {
846
/* If we ran out of fields, rec1 was equal to rec2. */
850
/*************************************************************//**
851
This function is used to compare two physical records. Only the common
852
first fields are compared, and if an externally stored field is
853
encountered, then 0 is returned.
854
@return 1, 0, -1 if rec1 is greater, equal, less, respectively */
857
cmp_rec_rec_with_match(
858
/*===================*/
859
const rec_t* rec1, /*!< in: physical record */
860
const rec_t* rec2, /*!< in: physical record */
861
const ulint* offsets1,/*!< in: rec_get_offsets(rec1, index) */
862
const ulint* offsets2,/*!< in: rec_get_offsets(rec2, index) */
863
dict_index_t* index, /*!< in: data dictionary index */
864
ulint* matched_fields, /*!< in/out: number of already completely
865
matched fields; when the function returns,
866
contains the value the for current
868
ulint* matched_bytes) /*!< in/out: number of already matched
869
bytes within the first field not completely
870
matched; when the function returns, contains
871
the value for the current comparison */
873
ulint rec1_n_fields; /* the number of fields in rec */
874
ulint rec1_f_len; /* length of current field in rec */
875
const byte* rec1_b_ptr; /* pointer to the current byte
877
ulint rec1_byte; /* value of current byte to be
879
ulint rec2_n_fields; /* the number of fields in rec */
880
ulint rec2_f_len; /* length of current field in rec */
881
const byte* rec2_b_ptr; /* pointer to the current byte
883
ulint rec2_byte; /* value of current byte to be
885
ulint cur_field; /* current field number */
886
ulint cur_bytes; /* number of already matched
887
bytes in current field */
888
int ret = 0; /* return value */
891
ut_ad(rec1 && rec2 && index);
892
ut_ad(rec_offs_validate(rec1, index, offsets1));
893
ut_ad(rec_offs_validate(rec2, index, offsets2));
894
ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
896
comp = rec_offs_comp(offsets1);
897
rec1_n_fields = rec_offs_n_fields(offsets1);
898
rec2_n_fields = rec_offs_n_fields(offsets2);
900
cur_field = *matched_fields;
901
cur_bytes = *matched_bytes;
903
/* Match fields in a loop */
905
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
910
if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
911
/* This is for the insert buffer B-tree. */
915
const dict_col_t* col
916
= dict_index_get_nth_col(index, cur_field);
919
prtype = col->prtype;
922
rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
923
cur_field, &rec1_f_len);
924
rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
925
cur_field, &rec2_f_len);
927
if (cur_bytes == 0) {
928
if (cur_field == 0) {
929
/* Test if rec is the predefined minimum
931
if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
932
& REC_INFO_MIN_REC_FLAG)) {
934
if (!(rec_get_info_bits(rec2, comp)
935
& REC_INFO_MIN_REC_FLAG)) {
941
} else if (UNIV_UNLIKELY
942
(rec_get_info_bits(rec2, comp)
943
& REC_INFO_MIN_REC_FLAG)) {
951
if (rec_offs_nth_extern(offsets1, cur_field)
952
|| rec_offs_nth_extern(offsets2, cur_field)) {
953
/* We do not compare to an externally
959
if (rec1_f_len == UNIV_SQL_NULL
960
|| rec2_f_len == UNIV_SQL_NULL) {
962
if (rec1_f_len == rec2_f_len) {
966
} else if (rec2_f_len == UNIV_SQL_NULL) {
968
/* We define the SQL null to be the
969
smallest possible value of a field
970
in the alphabetical order */
981
if (mtype >= DATA_FLOAT
982
|| (mtype == DATA_BLOB
983
&& 0 == (prtype & DATA_BINARY_TYPE)
984
&& dtype_get_charset_coll(prtype)
985
!= DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
987
ret = cmp_whole_field(mtype, prtype,
989
(unsigned) rec1_f_len,
991
(unsigned) rec2_f_len);
1001
/* Set the pointers at the current byte */
1002
rec1_b_ptr = rec1_b_ptr + cur_bytes;
1003
rec2_b_ptr = rec2_b_ptr + cur_bytes;
1005
/* Compare then the fields */
1007
if (rec2_f_len <= cur_bytes) {
1009
if (rec1_f_len <= cur_bytes) {
1014
rec2_byte = dtype_get_pad_char(mtype, prtype);
1016
if (rec2_byte == ULINT_UNDEFINED) {
1019
goto order_resolved;
1022
rec2_byte = *rec2_b_ptr;
1025
if (rec1_f_len <= cur_bytes) {
1026
rec1_byte = dtype_get_pad_char(mtype, prtype);
1028
if (rec1_byte == ULINT_UNDEFINED) {
1031
goto order_resolved;
1034
rec1_byte = *rec1_b_ptr;
1037
if (rec1_byte == rec2_byte) {
1038
/* If the bytes are equal, they will remain
1039
such even after the collation transformation
1045
if (mtype <= DATA_CHAR
1046
|| (mtype == DATA_BLOB
1047
&& !(prtype & DATA_BINARY_TYPE))) {
1049
rec1_byte = cmp_collate(rec1_byte);
1050
rec2_byte = cmp_collate(rec2_byte);
1053
if (rec1_byte < rec2_byte) {
1055
goto order_resolved;
1056
} else if (rec1_byte > rec2_byte) {
1058
goto order_resolved;
1073
ut_ad(cur_bytes == 0);
1075
/* If we ran out of fields, rec1 was equal to rec2 up
1076
to the common fields */
1080
ut_ad((ret >= - 1) && (ret <= 1));
1082
*matched_fields = cur_field;
1083
*matched_bytes = cur_bytes;
1089
/*************************************************************//**
1090
Used in debug checking of cmp_dtuple_... .
1091
This function is used to compare a data tuple to a physical record. If
1092
dtuple has n fields then rec must have either m >= n fields, or it must
1093
differ from dtuple in some of the m fields rec has. If encounters an
1094
externally stored field, returns 0.
1095
@return 1, 0, -1, if dtuple is greater, equal, less than rec,
1096
respectively, when only the common first fields are compared */
1099
cmp_debug_dtuple_rec_with_match(
1100
/*============================*/
1101
const dtuple_t* dtuple, /*!< in: data tuple */
1102
const rec_t* rec, /*!< in: physical record which differs from
1103
dtuple in some of the common fields, or which
1104
has an equal number or more fields than
1106
const ulint* offsets,/*!< in: array returned by rec_get_offsets() */
1107
ulint* matched_fields) /*!< in/out: number of already
1108
completely matched fields; when function
1109
returns, contains the value for current
1112
const dfield_t* dtuple_field; /* current field in logical record */
1113
ulint dtuple_f_len; /* the length of the current field
1114
in the logical record */
1115
const byte* dtuple_f_data; /* pointer to the current logical
1117
ulint rec_f_len; /* length of current field in rec */
1118
const byte* rec_f_data; /* pointer to the current rec field */
1119
int ret = 3333; /* return value */
1120
ulint cur_field; /* current field number */
1122
ut_ad(dtuple && rec && matched_fields);
1123
ut_ad(dtuple_check_typed(dtuple));
1124
ut_ad(rec_offs_validate(rec, NULL, offsets));
1126
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
1127
ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
1129
cur_field = *matched_fields;
1131
if (cur_field == 0) {
1133
(rec_get_info_bits(rec, rec_offs_comp(offsets))
1134
& REC_INFO_MIN_REC_FLAG)) {
1136
ret = !(dtuple_get_info_bits(dtuple)
1137
& REC_INFO_MIN_REC_FLAG);
1139
goto order_resolved;
1143
(dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
1146
goto order_resolved;
1150
/* Match fields in a loop; stop if we run out of fields in dtuple */
1152
while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
1157
dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
1160
= dfield_get_type(dtuple_field);
1162
mtype = type->mtype;
1163
prtype = type->prtype;
1166
dtuple_f_data = dfield_get_data(dtuple_field);
1167
dtuple_f_len = dfield_get_len(dtuple_field);
1169
rec_f_data = rec_get_nth_field(rec, offsets,
1170
cur_field, &rec_f_len);
1172
if (rec_offs_nth_extern(offsets, cur_field)) {
1173
/* We do not compare to an externally stored field */
1177
goto order_resolved;
1180
ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
1181
rec_f_data, rec_f_len);
1183
goto order_resolved;
1189
ret = 0; /* If we ran out of fields, dtuple was equal to rec
1190
up to the common fields */
1192
ut_ad((ret >= - 1) && (ret <= 1));
1194
*matched_fields = cur_field;
1198
#endif /* UNIV_DEBUG */