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 dtuple_t
* dtuple
, /* in: data tuple */
50 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 unsigned char* a
, /* in: data field */
74 unsigned int a_length
, /* in: data field length,
76 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 unsigned char* a
, /* in: data field */
161 unsigned int a_length
, /* in: data field length,
163 unsigned char* 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 byte
* data1
, /* in: data field (== a pointer to a memory
290 ulint len1
, /* in: data field length or UNIV_SQL_NULL */
291 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 dtuple_t
* dtuple
, /* in: data tuple */
416 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 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 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 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 (rec_info
& REC_INFO_MIN_REC_FLAG
) {
463 ret
= !(tup_info
& REC_INFO_MIN_REC_FLAG
);
465 } else if (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_UNLIKELY(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 dtuple_t
* dtuple
, /* in: data tuple */
656 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 dtuple_t
* dtuple
, /* in: data tuple */
676 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 /*****************************************************************
708 This function is used to compare two physical records. Only the common
709 first fields are compared, and if an externally stored field is
710 encountered, then 0 is returned. */
713 cmp_rec_rec_with_match(
714 /*===================*/
715 /* out: 1, 0 , -1 if rec1 is greater, equal,
716 less, respectively, than rec2; only the common
717 first fields are compared */
718 rec_t
* rec1
, /* in: physical record */
719 rec_t
* rec2
, /* in: physical record */
720 const ulint
* offsets1
,/* in: rec_get_offsets(rec1, index) */
721 const ulint
* offsets2
,/* in: rec_get_offsets(rec2, index) */
722 dict_index_t
* index
, /* in: data dictionary index */
724 /* in: TRUE if this is for index statistics
725 cardinality estimation, and innodb_stats_method
726 is "nulls_unequal" or "nulls_ignored" */
727 ulint
* matched_fields
, /* in/out: number of already completely
728 matched fields; when the function returns,
729 contains the value the for current
731 ulint
* matched_bytes
) /* in/out: number of already matched
732 bytes within the first field not completely
733 matched; when the function returns, contains
734 the value for the current comparison */
736 #ifndef UNIV_HOTBACKUP
737 ulint rec1_n_fields
; /* the number of fields in rec */
738 ulint rec1_f_len
; /* length of current field in rec */
739 byte
* rec1_b_ptr
; /* pointer to the current byte in rec field */
740 ulint rec1_byte
; /* value of current byte to be compared in
742 ulint rec2_n_fields
; /* the number of fields in rec */
743 ulint rec2_f_len
; /* length of current field in rec */
744 byte
* rec2_b_ptr
; /* pointer to the current byte in rec field */
745 ulint rec2_byte
; /* value of current byte to be compared in
747 ulint cur_field
; /* current field number */
748 ulint cur_bytes
; /* number of already matched bytes in current
750 int ret
= 3333; /* return value */
753 ut_ad(rec1
&& rec2
&& index
);
754 ut_ad(rec_offs_validate(rec1
, index
, offsets1
));
755 ut_ad(rec_offs_validate(rec2
, index
, offsets2
));
756 ut_ad(rec_offs_comp(offsets1
) == rec_offs_comp(offsets2
));
758 comp
= rec_offs_comp(offsets1
);
759 rec1_n_fields
= rec_offs_n_fields(offsets1
);
760 rec2_n_fields
= rec_offs_n_fields(offsets2
);
762 cur_field
= *matched_fields
;
763 cur_bytes
= *matched_bytes
;
765 /* Match fields in a loop */
767 while ((cur_field
< rec1_n_fields
) && (cur_field
< rec2_n_fields
)) {
772 if (UNIV_UNLIKELY(index
->type
& DICT_UNIVERSAL
)) {
773 /* This is for the insert buffer B-tree. */
777 const dict_col_t
* col
778 = dict_index_get_nth_col(index
, cur_field
);
781 prtype
= col
->prtype
;
784 rec1_b_ptr
= rec_get_nth_field(rec1
, offsets1
,
785 cur_field
, &rec1_f_len
);
786 rec2_b_ptr
= rec_get_nth_field(rec2
, offsets2
,
787 cur_field
, &rec2_f_len
);
789 if (cur_bytes
== 0) {
790 if (cur_field
== 0) {
791 /* Test if rec is the predefined minimum
793 if (rec_get_info_bits(rec1
, comp
)
794 & REC_INFO_MIN_REC_FLAG
) {
796 if (rec_get_info_bits(rec2
, comp
)
797 & REC_INFO_MIN_REC_FLAG
) {
805 } else if (rec_get_info_bits(rec2
, comp
)
806 & REC_INFO_MIN_REC_FLAG
) {
814 if (rec_offs_nth_extern(offsets1
, cur_field
)
815 || rec_offs_nth_extern(offsets2
, cur_field
)) {
816 /* We do not compare to an externally
824 if (rec1_f_len
== UNIV_SQL_NULL
825 || rec2_f_len
== UNIV_SQL_NULL
) {
827 if (rec1_f_len
== rec2_f_len
) {
828 /* This is limited to stats collection,
829 cannot use it for regular search */
835 } else if (rec2_f_len
== UNIV_SQL_NULL
) {
837 /* We define the SQL null to be the
838 smallest possible value of a field
839 in the alphabetical order */
850 if (mtype
>= DATA_FLOAT
851 || (mtype
== DATA_BLOB
852 && 0 == (prtype
& DATA_BINARY_TYPE
)
853 && dtype_get_charset_coll(prtype
)
854 != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL
)) {
856 ret
= cmp_whole_field(mtype
, prtype
,
858 (unsigned) rec1_f_len
,
860 (unsigned) rec2_f_len
);
870 /* Set the pointers at the current byte */
871 rec1_b_ptr
= rec1_b_ptr
+ cur_bytes
;
872 rec2_b_ptr
= rec2_b_ptr
+ cur_bytes
;
874 /* Compare then the fields */
876 if (rec2_f_len
<= cur_bytes
) {
878 if (rec1_f_len
<= cur_bytes
) {
883 rec2_byte
= dtype_get_pad_char(mtype
, prtype
);
885 if (rec2_byte
== ULINT_UNDEFINED
) {
891 rec2_byte
= *rec2_b_ptr
;
894 if (rec1_f_len
<= cur_bytes
) {
895 rec1_byte
= dtype_get_pad_char(mtype
, prtype
);
897 if (rec1_byte
== ULINT_UNDEFINED
) {
903 rec1_byte
= *rec1_b_ptr
;
906 if (rec1_byte
== rec2_byte
) {
907 /* If the bytes are equal, they will remain
908 such even after the collation transformation
914 if (mtype
<= DATA_CHAR
915 || (mtype
== DATA_BLOB
916 && !(prtype
& DATA_BINARY_TYPE
))) {
918 rec1_byte
= cmp_collate(rec1_byte
);
919 rec2_byte
= cmp_collate(rec2_byte
);
922 if (rec1_byte
< rec2_byte
) {
925 } else if (rec1_byte
> rec2_byte
) {
942 ut_ad(cur_bytes
== 0);
944 ret
= 0; /* If we ran out of fields, rec1 was equal to rec2 up
945 to the common fields */
948 ut_ad((ret
>= - 1) && (ret
<= 1));
950 *matched_fields
= cur_field
;
951 *matched_bytes
= cur_bytes
;
954 #else /* !UNIV_HOTBACKUP */
955 /* This function depends on MySQL code that is not included in
956 InnoDB Hot Backup builds. Besides, this function should never
957 be called in InnoDB Hot Backup. */
960 #endif /* !UNIV_HOTBACKUP */
964 /*****************************************************************
965 Used in debug checking of cmp_dtuple_... .
966 This function is used to compare a data tuple to a physical record. If
967 dtuple has n fields then rec must have either m >= n fields, or it must
968 differ from dtuple in some of the m fields rec has. If encounters an
969 externally stored field, returns 0. */
972 cmp_debug_dtuple_rec_with_match(
973 /*============================*/
974 /* out: 1, 0, -1, if dtuple is greater, equal,
975 less than rec, respectively, when only the
976 common first fields are compared */
977 dtuple_t
* dtuple
, /* in: data tuple */
978 rec_t
* rec
, /* in: physical record which differs from
979 dtuple in some of the common fields, or which
980 has an equal number or more fields than
982 const ulint
* offsets
,/* in: array returned by rec_get_offsets() */
983 ulint
* matched_fields
) /* in/out: number of already
984 completely matched fields; when function
985 returns, contains the value for current
988 dfield_t
* dtuple_field
; /* current field in logical record */
989 ulint dtuple_f_len
; /* the length of the current field
990 in the logical record */
991 byte
* dtuple_f_data
; /* pointer to the current logical
993 ulint rec_f_len
; /* length of current field in rec */
994 byte
* rec_f_data
; /* pointer to the current rec field */
995 int ret
= 3333; /* return value */
996 ulint cur_field
; /* current field number */
998 ut_ad(dtuple
&& rec
&& matched_fields
);
999 ut_ad(dtuple_check_typed(dtuple
));
1000 ut_ad(rec_offs_validate(rec
, NULL
, offsets
));
1002 ut_ad(*matched_fields
<= dtuple_get_n_fields_cmp(dtuple
));
1003 ut_ad(*matched_fields
<= rec_offs_n_fields(offsets
));
1005 cur_field
= *matched_fields
;
1007 if (cur_field
== 0) {
1008 if (rec_get_info_bits(rec
, rec_offs_comp(offsets
))
1009 & REC_INFO_MIN_REC_FLAG
) {
1011 ret
= !(dtuple_get_info_bits(dtuple
)
1012 & REC_INFO_MIN_REC_FLAG
);
1014 goto order_resolved
;
1017 if (dtuple_get_info_bits(dtuple
) & REC_INFO_MIN_REC_FLAG
) {
1020 goto order_resolved
;
1024 /* Match fields in a loop; stop if we run out of fields in dtuple */
1026 while (cur_field
< dtuple_get_n_fields_cmp(dtuple
)) {
1031 dtuple_field
= dtuple_get_nth_field(dtuple
, cur_field
);
1034 = dfield_get_type(dtuple_field
);
1036 mtype
= type
->mtype
;
1037 prtype
= type
->prtype
;
1040 dtuple_f_data
= dfield_get_data(dtuple_field
);
1041 dtuple_f_len
= dfield_get_len(dtuple_field
);
1043 rec_f_data
= rec_get_nth_field(rec
, offsets
,
1044 cur_field
, &rec_f_len
);
1046 if (rec_offs_nth_extern(offsets
, cur_field
)) {
1047 /* We do not compare to an externally stored field */
1051 goto order_resolved
;
1054 ret
= cmp_data_data(mtype
, prtype
, dtuple_f_data
, dtuple_f_len
,
1055 rec_f_data
, rec_f_len
);
1057 goto order_resolved
;
1063 ret
= 0; /* If we ran out of fields, dtuple was equal to rec
1064 up to the common fields */
1066 ut_ad((ret
>= - 1) && (ret
<= 1));
1068 *matched_fields
= cur_field
;
1072 #endif /* UNIV_DEBUG */