Drizzled Public API Documentation

rem0cmp.cc
1 /*****************************************************************************
2 
3 Copyright (C) 1994, 2009, Innobase Oy. All Rights Reserved.
4 
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.
8 
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.
12 
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
16 
17 *****************************************************************************/
18 
19 /*******************************************************************/
26 #include "rem0cmp.h"
27 
28 #ifdef UNIV_NONINL
29 #include "rem0cmp.ic"
30 #endif
31 
32 #include "srv0srv.h"
33 
34 /* ALPHABETICAL ORDER
35  ==================
36 
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.
48 
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. */
52 
53 #ifdef UNIV_DEBUG
54 /*************************************************************/
61 static
62 int
63 cmp_debug_dtuple_rec_with_match(
64 /*============================*/
65  const dtuple_t* dtuple,
66  const rec_t* rec,
70  const ulint* offsets,
71  ulint* matched_fields);
75 #endif /* UNIV_DEBUG */
76 /*************************************************************/
81 extern
82 int
84 /*===============*/
85  int mysql_type,
86  uint charset_number,
87  const unsigned char* a,
88  unsigned int a_length,
90  const unsigned char* b,
91  unsigned int b_length);
93 /*********************************************************************/
98 UNIV_INLINE
99 ulint
100 cmp_collate(
101 /*========*/
102  ulint code)
103 {
104  return((ulint) srv_latin1_ordering[code]);
105 }
106 
107 /*************************************************************/
110 UNIV_INTERN
111 ibool
113 /*===============*/
114  const dict_col_t* col1,
115  const dict_col_t* col2,
116  ibool check_charsets)
118 {
119  if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
120  && dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
121 
122  /* Both are non-binary string types: they can be compared if
123  and only if the charset-collation is the same */
124 
125  if (check_charsets) {
126  return(dtype_get_charset_coll(col1->prtype)
127  == dtype_get_charset_coll(col2->prtype));
128  } else {
129  return(TRUE);
130  }
131  }
132 
133  if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
134  && dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
135 
136  /* Both are binary string types: they can be compared */
137 
138  return(TRUE);
139  }
140 
141  if (col1->mtype != col2->mtype) {
142 
143  return(FALSE);
144  }
145 
146  if (col1->mtype == DATA_INT
147  && (col1->prtype & DATA_UNSIGNED)
148  != (col2->prtype & DATA_UNSIGNED)) {
149 
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. */
153 
154  return(FALSE);
155  }
156 
157  return(col1->mtype != DATA_INT || col1->len == col2->len);
158 }
159 
160 /*************************************************************/
164 static
165 int
166 cmp_whole_field(
167 /*============*/
168  ulint mtype,
169  ulint prtype,
170  const byte* a,
171  unsigned int a_length,
173  const byte* b,
174  unsigned int b_length)
176 {
177  float f_1;
178  float f_2;
179  double d_1;
180  double d_2;
181  int swap_flag = 1;
182 
183  switch (mtype) {
184 
185  case DATA_DECIMAL:
186  /* Remove preceding spaces */
187  for (; a_length && *a == ' '; a++, a_length--) {}
188  for (; b_length && *b == ' '; b++, b_length--) {}
189 
190  if (*a == '-') {
191  if (*b != '-') {
192  return(-1);
193  }
194 
195  a++; b++;
196  a_length--;
197  b_length--;
198 
199  swap_flag = -1;
200 
201  } else if (*b == '-') {
202 
203  return(1);
204  }
205 
206  while (a_length > 0 && (*a == '+' || *a == '0')) {
207  a++; a_length--;
208  }
209 
210  while (b_length > 0 && (*b == '+' || *b == '0')) {
211  b++; b_length--;
212  }
213 
214  if (a_length != b_length) {
215  if (a_length < b_length) {
216  return(-swap_flag);
217  }
218 
219  return(swap_flag);
220  }
221 
222  while (a_length > 0 && *a == *b) {
223 
224  a++; b++; a_length--;
225  }
226 
227  if (a_length == 0) {
228 
229  return(0);
230  }
231 
232  if (*a > *b) {
233  return(swap_flag);
234  }
235 
236  return(-swap_flag);
237  case DATA_DOUBLE:
238  d_1 = mach_double_read(a);
239  d_2 = mach_double_read(b);
240 
241  if (d_1 > d_2) {
242  return(1);
243  } else if (d_2 > d_1) {
244  return(-1);
245  }
246 
247  return(0);
248 
249  case DATA_FLOAT:
250  f_1 = mach_float_read(a);
251  f_2 = mach_float_read(b);
252 
253  if (f_1 > f_2) {
254  return(1);
255  } else if (f_2 > f_1) {
256  return(-1);
257  }
258 
259  return(0);
260  case DATA_BLOB:
261  if (prtype & DATA_BINARY_TYPE) {
262 
263  ut_print_timestamp(stderr);
264  fprintf(stderr,
265  " InnoDB: Error: comparing a binary BLOB"
266  " with a character set sensitive\n"
267  "InnoDB: comparison!\n");
268  }
269  /* fall through */
270  case DATA_VARMYSQL:
271  case DATA_MYSQL:
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));
276  default:
277  fprintf(stderr,
278  "InnoDB: unknown type number %lu\n",
279  (ulong) mtype);
280  ut_error;
281  }
282 
283  return(0);
284 }
285 
286 /*************************************************************/
290 UNIV_INTERN
291 int
293 /*===============*/
294  ulint mtype,
295  ulint prtype,
296  const byte* data1,
298  ulint len1,
299  const byte* data2,
301  ulint len2)
302 {
303  ulint data1_byte;
304  ulint data2_byte;
305  ulint cur_bytes;
306 
307  if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
308 
309  if (len1 == len2) {
310 
311  return(0);
312  }
313 
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 */
317 
318  return(-1);
319  }
320 
321  return(1);
322  }
323 
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)) {
329 
330  return(cmp_whole_field(mtype, prtype,
331  data1, (unsigned) len1,
332  data2, (unsigned) len2));
333  }
334 
335  /* Compare then the fields */
336 
337  cur_bytes = 0;
338 
339  for (;;) {
340  if (len1 <= cur_bytes) {
341  if (len2 <= cur_bytes) {
342 
343  return(0);
344  }
345 
346  data1_byte = dtype_get_pad_char(mtype, prtype);
347 
348  if (data1_byte == ULINT_UNDEFINED) {
349 
350  return(-1);
351  }
352  } else {
353  data1_byte = *data1;
354  }
355 
356  if (len2 <= cur_bytes) {
357  data2_byte = dtype_get_pad_char(mtype, prtype);
358 
359  if (data2_byte == ULINT_UNDEFINED) {
360 
361  return(1);
362  }
363  } else {
364  data2_byte = *data2;
365  }
366 
367  if (data1_byte == data2_byte) {
368  /* If the bytes are equal, they will remain such even
369  after the collation transformation below */
370 
371  goto next_byte;
372  }
373 
374  if (mtype <= DATA_CHAR
375  || (mtype == DATA_BLOB
376  && 0 == (prtype & DATA_BINARY_TYPE))) {
377 
378  data1_byte = cmp_collate(data1_byte);
379  data2_byte = cmp_collate(data2_byte);
380  }
381 
382  if (data1_byte > data2_byte) {
383 
384  return(1);
385  } else if (data1_byte < data2_byte) {
386 
387  return(-1);
388  }
389 next_byte:
390  /* Next byte */
391  cur_bytes++;
392  data1++;
393  data2++;
394  }
395 
396 }
397 
398 /*************************************************************/
409 UNIV_INTERN
410 int
412 /*======================*/
413  const dtuple_t* dtuple,
414  const rec_t* rec,
418  const ulint* offsets,
419  ulint* matched_fields,
422  ulint* matched_bytes)
426 {
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
433  in dtuple*/
434  ulint rec_f_len; /* length of current field in rec */
435  const byte* rec_b_ptr; /* pointer to the current byte in
436  rec field */
437  ulint rec_byte; /* value of current byte to be
438  compared in rec */
439  ulint cur_field; /* current field number */
440  ulint cur_bytes; /* number of already matched bytes
441  in current field */
442  int ret = 3333; /* return value */
443 
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));
447 
448  cur_field = *matched_fields;
449  cur_bytes = *matched_bytes;
450 
451  ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
452  ut_ad(cur_field <= rec_offs_n_fields(offsets));
453 
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);
458 
459  if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
460  ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
461  goto order_resolved;
462  } else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
463  ret = -1;
464  goto order_resolved;
465  }
466  }
467 
468  /* Match fields in a loop; stop if we run out of fields in dtuple
469  or find an externally stored field */
470 
471  while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
472 
473  ulint mtype;
474  ulint prtype;
475 
476  dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
477  {
478  const dtype_t* type
479  = dfield_get_type(dtuple_field);
480 
481  mtype = type->mtype;
482  prtype = type->prtype;
483  }
484 
485  dtuple_f_len = dfield_get_len(dtuple_field);
486 
487  rec_b_ptr = rec_get_nth_field(rec, offsets,
488  cur_field, &rec_f_len);
489 
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
493  stored */
494 
495  if (UNIV_LIKELY(cur_bytes == 0)) {
496  if (rec_offs_nth_extern(offsets, cur_field)) {
497  /* We do not compare to an externally
498  stored field */
499 
500  ret = 0;
501 
502  goto order_resolved;
503  }
504 
505  if (dtuple_f_len == UNIV_SQL_NULL) {
506  if (rec_f_len == UNIV_SQL_NULL) {
507 
508  goto next_field;
509  }
510 
511  ret = -1;
512  goto order_resolved;
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 */
517 
518  ret = 1;
519  goto order_resolved;
520  }
521  }
522 
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)) {
528 
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);
533 
534  if (ret != 0) {
535  cur_bytes = 0;
536 
537  goto order_resolved;
538  } else {
539  goto next_field;
540  }
541  }
542 
543  /* Set the pointers at the current byte */
544 
545  rec_b_ptr = rec_b_ptr + cur_bytes;
546  dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
547  + cur_bytes;
548  /* Compare then the fields */
549 
550  for (;;) {
551  if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
552  if (dtuple_f_len <= cur_bytes) {
553 
554  goto next_field;
555  }
556 
557  rec_byte = dtype_get_pad_char(mtype, prtype);
558 
559  if (rec_byte == ULINT_UNDEFINED) {
560  ret = 1;
561 
562  goto order_resolved;
563  }
564  } else {
565  rec_byte = *rec_b_ptr;
566  }
567 
568  if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
569  dtuple_byte = dtype_get_pad_char(mtype,
570  prtype);
571 
572  if (dtuple_byte == ULINT_UNDEFINED) {
573  ret = -1;
574 
575  goto order_resolved;
576  }
577  } else {
578  dtuple_byte = *dtuple_b_ptr;
579  }
580 
581  if (dtuple_byte == rec_byte) {
582  /* If the bytes are equal, they will
583  remain such even after the collation
584  transformation below */
585 
586  goto next_byte;
587  }
588 
589  if (mtype <= DATA_CHAR
590  || (mtype == DATA_BLOB
591  && !(prtype & DATA_BINARY_TYPE))) {
592 
593  rec_byte = cmp_collate(rec_byte);
594  dtuple_byte = cmp_collate(dtuple_byte);
595  }
596 
597  ret = (int) (dtuple_byte - rec_byte);
598  if (UNIV_LIKELY(ret)) {
599  if (ret < 0) {
600  ret = -1;
601  goto order_resolved;
602  } else {
603  ret = 1;
604  goto order_resolved;
605  }
606  }
607 next_byte:
608  /* Next byte */
609  cur_bytes++;
610  rec_b_ptr++;
611  dtuple_b_ptr++;
612  }
613 
614 next_field:
615  cur_field++;
616  cur_bytes = 0;
617  }
618 
619  ut_ad(cur_bytes == 0);
620 
621  ret = 0; /* If we ran out of fields, dtuple was equal to rec
622  up to the common fields */
623 order_resolved:
624  ut_ad((ret >= - 1) && (ret <= 1));
625  ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
626  matched_fields));
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;
632 
633  return(ret);
634 }
635 
636 /**************************************************************/
640 UNIV_INTERN
641 int
643 /*===========*/
644  const dtuple_t* dtuple,
645  const rec_t* rec,
646  const ulint* offsets)
647 {
648  ulint matched_fields = 0;
649  ulint matched_bytes = 0;
650 
651  ut_ad(rec_offs_validate(rec, NULL, offsets));
652  return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
653  &matched_fields, &matched_bytes));
654 }
655 
656 /**************************************************************/
660 UNIV_INTERN
661 ibool
663 /*========================*/
664  const dtuple_t* dtuple,
665  const rec_t* rec,
666  const ulint* offsets)
667 {
668  ulint n_fields;
669  ulint matched_fields = 0;
670  ulint matched_bytes = 0;
671 
672  ut_ad(rec_offs_validate(rec, NULL, offsets));
673  n_fields = dtuple_get_n_fields(dtuple);
674 
675  if (n_fields > rec_offs_n_fields(offsets)) {
676 
677  return(FALSE);
678  }
679 
680  cmp_dtuple_rec_with_match(dtuple, rec, offsets,
681  &matched_fields, &matched_bytes);
682  if (matched_fields == n_fields) {
683 
684  return(TRUE);
685  }
686 
687  if (matched_fields == n_fields - 1
688  && matched_bytes == dfield_get_len(
689  dtuple_get_nth_field(dtuple, n_fields - 1))) {
690  return(TRUE);
691  }
692 
693  return(FALSE);
694 }
695 
696 /*************************************************************/
700 UNIV_INTERN
701 int
703 /*===============*/
704  const rec_t* rec1,
705  const rec_t* rec2,
706  const ulint* offsets1,
707  const ulint* offsets2,
708  const dict_index_t* index,
709  ibool* null_eq)
711 {
712  ulint rec1_f_len;
713  const byte* rec1_b_ptr;
715  ulint rec1_byte;
717  ulint rec2_f_len;
718  const byte* rec2_b_ptr;
720  ulint rec2_byte;
722  ulint cur_field;
723  ulint n_uniq;
724 
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);
728 
729  ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
730 
731  for (cur_field = 0; cur_field < n_uniq; cur_field++) {
732 
733  ulint cur_bytes;
734  ulint mtype;
735  ulint prtype;
736 
737  {
738  const dict_col_t* col
739  = dict_index_get_nth_col(index, cur_field);
740 
741  mtype = col->mtype;
742  prtype = col->prtype;
743  }
744 
745  ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
746  ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
747 
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);
752 
753  if (rec1_f_len == UNIV_SQL_NULL
754  || rec2_f_len == UNIV_SQL_NULL) {
755 
756  if (rec1_f_len == rec2_f_len) {
757  if (null_eq) {
758  *null_eq = TRUE;
759  }
760 
761  goto next_field;
762 
763  } else if (rec2_f_len == UNIV_SQL_NULL) {
764 
765  /* We define the SQL null to be the
766  smallest possible value of a field
767  in the alphabetical order */
768 
769  return(1);
770  } else {
771  return(-1);
772  }
773  }
774 
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,
781  rec1_b_ptr,
782  (unsigned) rec1_f_len,
783  rec2_b_ptr,
784  (unsigned) rec2_f_len);
785  if (ret) {
786  return(ret);
787  }
788 
789  goto next_field;
790  }
791 
792  /* Compare the fields */
793  for (cur_bytes = 0;; cur_bytes++, rec1_b_ptr++, rec2_b_ptr++) {
794  if (rec2_f_len <= cur_bytes) {
795 
796  if (rec1_f_len <= cur_bytes) {
797 
798  goto next_field;
799  }
800 
801  rec2_byte = dtype_get_pad_char(mtype, prtype);
802 
803  if (rec2_byte == ULINT_UNDEFINED) {
804  return(1);
805  }
806  } else {
807  rec2_byte = *rec2_b_ptr;
808  }
809 
810  if (rec1_f_len <= cur_bytes) {
811  rec1_byte = dtype_get_pad_char(mtype, prtype);
812 
813  if (rec1_byte == ULINT_UNDEFINED) {
814  return(-1);
815  }
816  } else {
817  rec1_byte = *rec1_b_ptr;
818  }
819 
820  if (rec1_byte == rec2_byte) {
821  /* If the bytes are equal, they will remain
822  such even after the collation transformation
823  below */
824 
825  continue;
826  }
827 
828  if (mtype <= DATA_CHAR
829  || (mtype == DATA_BLOB
830  && !(prtype & DATA_BINARY_TYPE))) {
831 
832  rec1_byte = cmp_collate(rec1_byte);
833  rec2_byte = cmp_collate(rec2_byte);
834  }
835 
836  if (rec1_byte < rec2_byte) {
837  return(-1);
838  } else if (rec1_byte > rec2_byte) {
839  return(1);
840  }
841  }
842 next_field:
843  continue;
844  }
845 
846  /* If we ran out of fields, rec1 was equal to rec2. */
847  return(0);
848 }
849 
850 /*************************************************************/
855 UNIV_INTERN
856 int
858 /*===================*/
859  const rec_t* rec1,
860  const rec_t* rec2,
861  const ulint* offsets1,
862  const ulint* offsets2,
863  dict_index_t* index,
864  ulint* matched_fields,
868  ulint* matched_bytes)
872 {
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
876  in rec field */
877  ulint rec1_byte; /* value of current byte to be
878  compared in rec */
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
882  in rec field */
883  ulint rec2_byte; /* value of current byte to be
884  compared in rec */
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 */
889  ulint comp;
890 
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));
895 
896  comp = rec_offs_comp(offsets1);
897  rec1_n_fields = rec_offs_n_fields(offsets1);
898  rec2_n_fields = rec_offs_n_fields(offsets2);
899 
900  cur_field = *matched_fields;
901  cur_bytes = *matched_bytes;
902 
903  /* Match fields in a loop */
904 
905  while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
906 
907  ulint mtype;
908  ulint prtype;
909 
910  if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
911  /* This is for the insert buffer B-tree. */
912  mtype = DATA_BINARY;
913  prtype = 0;
914  } else {
915  const dict_col_t* col
916  = dict_index_get_nth_col(index, cur_field);
917 
918  mtype = col->mtype;
919  prtype = col->prtype;
920  }
921 
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);
926 
927  if (cur_bytes == 0) {
928  if (cur_field == 0) {
929  /* Test if rec is the predefined minimum
930  record */
931  if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
932  & REC_INFO_MIN_REC_FLAG)) {
933 
934  if (!(rec_get_info_bits(rec2, comp)
935  & REC_INFO_MIN_REC_FLAG)) {
936  ret = -1;
937  }
938 
939  goto order_resolved;
940 
941  } else if (UNIV_UNLIKELY
942  (rec_get_info_bits(rec2, comp)
943  & REC_INFO_MIN_REC_FLAG)) {
944 
945  ret = 1;
946 
947  goto order_resolved;
948  }
949  }
950 
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
954  stored field */
955 
956  goto order_resolved;
957  }
958 
959  if (rec1_f_len == UNIV_SQL_NULL
960  || rec2_f_len == UNIV_SQL_NULL) {
961 
962  if (rec1_f_len == rec2_f_len) {
963 
964  goto next_field;
965 
966  } else if (rec2_f_len == UNIV_SQL_NULL) {
967 
968  /* We define the SQL null to be the
969  smallest possible value of a field
970  in the alphabetical order */
971 
972  ret = 1;
973  } else {
974  ret = -1;
975  }
976 
977  goto order_resolved;
978  }
979  }
980 
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)) {
986 
987  ret = cmp_whole_field(mtype, prtype,
988  rec1_b_ptr,
989  (unsigned) rec1_f_len,
990  rec2_b_ptr,
991  (unsigned) rec2_f_len);
992  if (ret != 0) {
993  cur_bytes = 0;
994 
995  goto order_resolved;
996  } else {
997  goto next_field;
998  }
999  }
1000 
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;
1004 
1005  /* Compare then the fields */
1006  for (;;) {
1007  if (rec2_f_len <= cur_bytes) {
1008 
1009  if (rec1_f_len <= cur_bytes) {
1010 
1011  goto next_field;
1012  }
1013 
1014  rec2_byte = dtype_get_pad_char(mtype, prtype);
1015 
1016  if (rec2_byte == ULINT_UNDEFINED) {
1017  ret = 1;
1018 
1019  goto order_resolved;
1020  }
1021  } else {
1022  rec2_byte = *rec2_b_ptr;
1023  }
1024 
1025  if (rec1_f_len <= cur_bytes) {
1026  rec1_byte = dtype_get_pad_char(mtype, prtype);
1027 
1028  if (rec1_byte == ULINT_UNDEFINED) {
1029  ret = -1;
1030 
1031  goto order_resolved;
1032  }
1033  } else {
1034  rec1_byte = *rec1_b_ptr;
1035  }
1036 
1037  if (rec1_byte == rec2_byte) {
1038  /* If the bytes are equal, they will remain
1039  such even after the collation transformation
1040  below */
1041 
1042  goto next_byte;
1043  }
1044 
1045  if (mtype <= DATA_CHAR
1046  || (mtype == DATA_BLOB
1047  && !(prtype & DATA_BINARY_TYPE))) {
1048 
1049  rec1_byte = cmp_collate(rec1_byte);
1050  rec2_byte = cmp_collate(rec2_byte);
1051  }
1052 
1053  if (rec1_byte < rec2_byte) {
1054  ret = -1;
1055  goto order_resolved;
1056  } else if (rec1_byte > rec2_byte) {
1057  ret = 1;
1058  goto order_resolved;
1059  }
1060 next_byte:
1061  /* Next byte */
1062 
1063  cur_bytes++;
1064  rec1_b_ptr++;
1065  rec2_b_ptr++;
1066  }
1067 
1068 next_field:
1069  cur_field++;
1070  cur_bytes = 0;
1071  }
1072 
1073  ut_ad(cur_bytes == 0);
1074 
1075  /* If we ran out of fields, rec1 was equal to rec2 up
1076  to the common fields */
1077  ut_ad(ret == 0);
1078 order_resolved:
1079 
1080  ut_ad((ret >= - 1) && (ret <= 1));
1081 
1082  *matched_fields = cur_field;
1083  *matched_bytes = cur_bytes;
1084 
1085  return(ret);
1086 }
1087 
1088 #ifdef UNIV_DEBUG
1089 /*************************************************************/
1097 static
1098 int
1099 cmp_debug_dtuple_rec_with_match(
1100 /*============================*/
1101  const dtuple_t* dtuple,
1102  const rec_t* rec,
1106  const ulint* offsets,
1107  ulint* matched_fields)
1111 {
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
1116  field data */
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 */
1121 
1122  ut_ad(dtuple && rec && matched_fields);
1123  ut_ad(dtuple_check_typed(dtuple));
1124  ut_ad(rec_offs_validate(rec, NULL, offsets));
1125 
1126  ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
1127  ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
1128 
1129  cur_field = *matched_fields;
1130 
1131  if (cur_field == 0) {
1132  if (UNIV_UNLIKELY
1133  (rec_get_info_bits(rec, rec_offs_comp(offsets))
1134  & REC_INFO_MIN_REC_FLAG)) {
1135 
1136  ret = !(dtuple_get_info_bits(dtuple)
1137  & REC_INFO_MIN_REC_FLAG);
1138 
1139  goto order_resolved;
1140  }
1141 
1142  if (UNIV_UNLIKELY
1143  (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
1144  ret = -1;
1145 
1146  goto order_resolved;
1147  }
1148  }
1149 
1150  /* Match fields in a loop; stop if we run out of fields in dtuple */
1151 
1152  while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
1153 
1154  ulint mtype;
1155  ulint prtype;
1156 
1157  dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
1158  {
1159  const dtype_t* type
1160  = dfield_get_type(dtuple_field);
1161 
1162  mtype = type->mtype;
1163  prtype = type->prtype;
1164  }
1165 
1166  dtuple_f_data = dfield_get_data(dtuple_field);
1167  dtuple_f_len = dfield_get_len(dtuple_field);
1168 
1169  rec_f_data = rec_get_nth_field(rec, offsets,
1170  cur_field, &rec_f_len);
1171 
1172  if (rec_offs_nth_extern(offsets, cur_field)) {
1173  /* We do not compare to an externally stored field */
1174 
1175  ret = 0;
1176 
1177  goto order_resolved;
1178  }
1179 
1180  ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
1181  rec_f_data, rec_f_len);
1182  if (ret != 0) {
1183  goto order_resolved;
1184  }
1185 
1186  cur_field++;
1187  }
1188 
1189  ret = 0; /* If we ran out of fields, dtuple was equal to rec
1190  up to the common fields */
1191 order_resolved:
1192  ut_ad((ret >= - 1) && (ret <= 1));
1193 
1194  *matched_fields = cur_field;
1195 
1196  return(ret);
1197 }
1198 #endif /* UNIV_DEBUG */