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  ibool nulls_unequal,
865  /* in: TRUE if this is for index statistics
866  cardinality estimation, and innodb_stats_method
867  is "nulls_unequal" or "nulls_ignored" */
868  ulint* matched_fields,
872  ulint* matched_bytes)
876 {
877  ulint rec1_n_fields; /* the number of fields in rec */
878  ulint rec1_f_len; /* length of current field in rec */
879  const byte* rec1_b_ptr; /* pointer to the current byte
880  in rec field */
881  ulint rec1_byte; /* value of current byte to be
882  compared in rec */
883  ulint rec2_n_fields; /* the number of fields in rec */
884  ulint rec2_f_len; /* length of current field in rec */
885  const byte* rec2_b_ptr; /* pointer to the current byte
886  in rec field */
887  ulint rec2_byte; /* value of current byte to be
888  compared in rec */
889  ulint cur_field; /* current field number */
890  ulint cur_bytes; /* number of already matched
891  bytes in current field */
892  int ret = 0; /* return value */
893  ulint comp;
894 
895  ut_ad(rec1 && rec2 && index);
896  ut_ad(rec_offs_validate(rec1, index, offsets1));
897  ut_ad(rec_offs_validate(rec2, index, offsets2));
898  ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
899 
900  comp = rec_offs_comp(offsets1);
901  rec1_n_fields = rec_offs_n_fields(offsets1);
902  rec2_n_fields = rec_offs_n_fields(offsets2);
903 
904  cur_field = *matched_fields;
905  cur_bytes = *matched_bytes;
906 
907  /* Match fields in a loop */
908 
909  while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
910 
911  ulint mtype;
912  ulint prtype;
913 
914  if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
915  /* This is for the insert buffer B-tree. */
916  mtype = DATA_BINARY;
917  prtype = 0;
918  } else {
919  const dict_col_t* col
920  = dict_index_get_nth_col(index, cur_field);
921 
922  mtype = col->mtype;
923  prtype = col->prtype;
924  }
925 
926  rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
927  cur_field, &rec1_f_len);
928  rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
929  cur_field, &rec2_f_len);
930 
931  if (cur_bytes == 0) {
932  if (cur_field == 0) {
933  /* Test if rec is the predefined minimum
934  record */
935  if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
936  & REC_INFO_MIN_REC_FLAG)) {
937 
938  if (!(rec_get_info_bits(rec2, comp)
939  & REC_INFO_MIN_REC_FLAG)) {
940  ret = -1;
941  }
942 
943  goto order_resolved;
944 
945  } else if (UNIV_UNLIKELY
946  (rec_get_info_bits(rec2, comp)
947  & REC_INFO_MIN_REC_FLAG)) {
948 
949  ret = 1;
950 
951  goto order_resolved;
952  }
953  }
954 
955  if (rec_offs_nth_extern(offsets1, cur_field)
956  || rec_offs_nth_extern(offsets2, cur_field)) {
957  /* We do not compare to an externally
958  stored field */
959 
960  goto order_resolved;
961  }
962 
963  if (rec1_f_len == UNIV_SQL_NULL
964  || rec2_f_len == UNIV_SQL_NULL) {
965 
966  if (rec1_f_len == rec2_f_len) {
967  /* This is limited to stats collection,
968  cannot use it for regular search */
969  if (nulls_unequal) {
970  ret = -1;
971  } else {
972  goto next_field;
973  }
974  } else if (rec2_f_len == UNIV_SQL_NULL) {
975 
976  /* We define the SQL null to be the
977  smallest possible value of a field
978  in the alphabetical order */
979 
980  ret = 1;
981  } else {
982  ret = -1;
983  }
984 
985  goto order_resolved;
986  }
987  }
988 
989  if (mtype >= DATA_FLOAT
990  || (mtype == DATA_BLOB
991  && 0 == (prtype & DATA_BINARY_TYPE)
992  && dtype_get_charset_coll(prtype)
993  != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
994 
995  ret = cmp_whole_field(mtype, prtype,
996  rec1_b_ptr,
997  (unsigned) rec1_f_len,
998  rec2_b_ptr,
999  (unsigned) rec2_f_len);
1000  if (ret != 0) {
1001  cur_bytes = 0;
1002 
1003  goto order_resolved;
1004  } else {
1005  goto next_field;
1006  }
1007  }
1008 
1009  /* Set the pointers at the current byte */
1010  rec1_b_ptr = rec1_b_ptr + cur_bytes;
1011  rec2_b_ptr = rec2_b_ptr + cur_bytes;
1012 
1013  /* Compare then the fields */
1014  for (;;) {
1015  if (rec2_f_len <= cur_bytes) {
1016 
1017  if (rec1_f_len <= cur_bytes) {
1018 
1019  goto next_field;
1020  }
1021 
1022  rec2_byte = dtype_get_pad_char(mtype, prtype);
1023 
1024  if (rec2_byte == ULINT_UNDEFINED) {
1025  ret = 1;
1026 
1027  goto order_resolved;
1028  }
1029  } else {
1030  rec2_byte = *rec2_b_ptr;
1031  }
1032 
1033  if (rec1_f_len <= cur_bytes) {
1034  rec1_byte = dtype_get_pad_char(mtype, prtype);
1035 
1036  if (rec1_byte == ULINT_UNDEFINED) {
1037  ret = -1;
1038 
1039  goto order_resolved;
1040  }
1041  } else {
1042  rec1_byte = *rec1_b_ptr;
1043  }
1044 
1045  if (rec1_byte == rec2_byte) {
1046  /* If the bytes are equal, they will remain
1047  such even after the collation transformation
1048  below */
1049 
1050  goto next_byte;
1051  }
1052 
1053  if (mtype <= DATA_CHAR
1054  || (mtype == DATA_BLOB
1055  && !(prtype & DATA_BINARY_TYPE))) {
1056 
1057  rec1_byte = cmp_collate(rec1_byte);
1058  rec2_byte = cmp_collate(rec2_byte);
1059  }
1060 
1061  if (rec1_byte < rec2_byte) {
1062  ret = -1;
1063  goto order_resolved;
1064  } else if (rec1_byte > rec2_byte) {
1065  ret = 1;
1066  goto order_resolved;
1067  }
1068 next_byte:
1069  /* Next byte */
1070 
1071  cur_bytes++;
1072  rec1_b_ptr++;
1073  rec2_b_ptr++;
1074  }
1075 
1076 next_field:
1077  cur_field++;
1078  cur_bytes = 0;
1079  }
1080 
1081  ut_ad(cur_bytes == 0);
1082 
1083  /* If we ran out of fields, rec1 was equal to rec2 up
1084  to the common fields */
1085  ut_ad(ret == 0);
1086 order_resolved:
1087 
1088  ut_ad((ret >= - 1) && (ret <= 1));
1089 
1090  *matched_fields = cur_field;
1091  *matched_bytes = cur_bytes;
1092 
1093  return(ret);
1094 }
1095 
1096 #ifdef UNIV_DEBUG
1097 /*************************************************************/
1105 static
1106 int
1107 cmp_debug_dtuple_rec_with_match(
1108 /*============================*/
1109  const dtuple_t* dtuple,
1110  const rec_t* rec,
1114  const ulint* offsets,
1115  ulint* matched_fields)
1119 {
1120  const dfield_t* dtuple_field; /* current field in logical record */
1121  ulint dtuple_f_len; /* the length of the current field
1122  in the logical record */
1123  const byte* dtuple_f_data; /* pointer to the current logical
1124  field data */
1125  ulint rec_f_len; /* length of current field in rec */
1126  const byte* rec_f_data; /* pointer to the current rec field */
1127  int ret = 3333; /* return value */
1128  ulint cur_field; /* current field number */
1129 
1130  ut_ad(dtuple && rec && matched_fields);
1131  ut_ad(dtuple_check_typed(dtuple));
1132  ut_ad(rec_offs_validate(rec, NULL, offsets));
1133 
1134  ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
1135  ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
1136 
1137  cur_field = *matched_fields;
1138 
1139  if (cur_field == 0) {
1140  if (UNIV_UNLIKELY
1141  (rec_get_info_bits(rec, rec_offs_comp(offsets))
1142  & REC_INFO_MIN_REC_FLAG)) {
1143 
1144  ret = !(dtuple_get_info_bits(dtuple)
1145  & REC_INFO_MIN_REC_FLAG);
1146 
1147  goto order_resolved;
1148  }
1149 
1150  if (UNIV_UNLIKELY
1151  (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
1152  ret = -1;
1153 
1154  goto order_resolved;
1155  }
1156  }
1157 
1158  /* Match fields in a loop; stop if we run out of fields in dtuple */
1159 
1160  while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
1161 
1162  ulint mtype;
1163  ulint prtype;
1164 
1165  dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
1166  {
1167  const dtype_t* type
1168  = dfield_get_type(dtuple_field);
1169 
1170  mtype = type->mtype;
1171  prtype = type->prtype;
1172  }
1173 
1174  dtuple_f_data = dfield_get_data(dtuple_field);
1175  dtuple_f_len = dfield_get_len(dtuple_field);
1176 
1177  rec_f_data = rec_get_nth_field(rec, offsets,
1178  cur_field, &rec_f_len);
1179 
1180  if (rec_offs_nth_extern(offsets, cur_field)) {
1181  /* We do not compare to an externally stored field */
1182 
1183  ret = 0;
1184 
1185  goto order_resolved;
1186  }
1187 
1188  ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
1189  rec_f_data, rec_f_len);
1190  if (ret != 0) {
1191  goto order_resolved;
1192  }
1193 
1194  cur_field++;
1195  }
1196 
1197  ret = 0; /* If we ran out of fields, dtuple was equal to rec
1198  up to the common fields */
1199 order_resolved:
1200  ut_ad((ret >= - 1) && (ret <= 1));
1201 
1202  *matched_fields = cur_field;
1203 
1204  return(ret);
1205 }
1206 #endif /* UNIV_DEBUG */