Drizzled Public API Documentation

rem0cmp.cc
00001 /*****************************************************************************
00002 
00003 Copyright (C) 1994, 2009, Innobase Oy. All Rights Reserved.
00004 
00005 This program is free software; you can redistribute it and/or modify it under
00006 the terms of the GNU General Public License as published by the Free Software
00007 Foundation; version 2 of the License.
00008 
00009 This program is distributed in the hope that it will be useful, but WITHOUT
00010 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00011 FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
00012 
00013 You should have received a copy of the GNU General Public License along with
00014 this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
00015 St, Fifth Floor, Boston, MA 02110-1301 USA
00016 
00017 *****************************************************************************/
00018 
00019 /*******************************************************************/
00026 #include "rem0cmp.h"
00027 
00028 #ifdef UNIV_NONINL
00029 #include "rem0cmp.ic"
00030 #endif
00031 
00032 #include "srv0srv.h"
00033 
00034 /*    ALPHABETICAL ORDER
00035     ==================
00036 
00037 The records are put into alphabetical order in the following
00038 way: let F be the first field where two records disagree.
00039 If there is a character in some position n where the the
00040 records disagree, the order is determined by comparison of
00041 the characters at position n, possibly after
00042 collating transformation. If there is no such character,
00043 but the corresponding fields have different lengths, then
00044 if the data type of the fields is paddable,
00045 shorter field is padded with a padding character. If the
00046 data type is not paddable, longer field is considered greater.
00047 Finally, the SQL null is bigger than any other value.
00048 
00049 At the present, the comparison functions return 0 in the case,
00050 where two records disagree only in the way that one
00051 has more fields than the other. */
00052 
00053 #ifdef UNIV_DEBUG
00054 /*************************************************************/
00061 static
00062 int
00063 cmp_debug_dtuple_rec_with_match(
00064 /*============================*/
00065   const dtuple_t* dtuple, 
00066   const rec_t*  rec,  
00070   const ulint*  offsets,
00071   ulint*    matched_fields);
00075 #endif /* UNIV_DEBUG */
00076 /*************************************************************/
00081 extern
00082 int
00083 innobase_mysql_cmp(
00084 /*===============*/
00085   int   mysql_type, 
00086   uint    charset_number, 
00087   const unsigned char* a,   
00088   unsigned int  a_length, 
00090   const unsigned char* b,   
00091   unsigned int  b_length);  
00093 /*********************************************************************/
00098 UNIV_INLINE
00099 ulint
00100 cmp_collate(
00101 /*========*/
00102   ulint code) 
00103 {
00104   return((ulint) srv_latin1_ordering[code]);
00105 }
00106 
00107 /*************************************************************/
00110 UNIV_INTERN
00111 ibool
00112 cmp_cols_are_equal(
00113 /*===============*/
00114   const dict_col_t* col1, 
00115   const dict_col_t* col2, 
00116   ibool     check_charsets)
00118 {
00119   if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
00120       && dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
00121 
00122     /* Both are non-binary string types: they can be compared if
00123     and only if the charset-collation is the same */
00124 
00125     if (check_charsets) {
00126       return(dtype_get_charset_coll(col1->prtype)
00127              == dtype_get_charset_coll(col2->prtype));
00128     } else {
00129       return(TRUE);
00130     }
00131   }
00132 
00133   if (dtype_is_binary_string_type(col1->mtype, col1->prtype)
00134       && dtype_is_binary_string_type(col2->mtype, col2->prtype)) {
00135 
00136     /* Both are binary string types: they can be compared */
00137 
00138     return(TRUE);
00139   }
00140 
00141   if (col1->mtype != col2->mtype) {
00142 
00143     return(FALSE);
00144   }
00145 
00146   if (col1->mtype == DATA_INT
00147       && (col1->prtype & DATA_UNSIGNED)
00148       != (col2->prtype & DATA_UNSIGNED)) {
00149 
00150     /* The storage format of an unsigned integer is different
00151     from a signed integer: in a signed integer we OR
00152     0x8000... to the value of positive integers. */
00153 
00154     return(FALSE);
00155   }
00156 
00157   return(col1->mtype != DATA_INT || col1->len == col2->len);
00158 }
00159 
00160 /*************************************************************/
00164 static
00165 int
00166 cmp_whole_field(
00167 /*============*/
00168   ulint   mtype,    
00169   ulint   prtype,   
00170   const byte* a,    
00171   unsigned int  a_length, 
00173   const byte* b,    
00174   unsigned int  b_length) 
00176 {
00177   float   f_1;
00178   float   f_2;
00179   double    d_1;
00180   double    d_2;
00181   int   swap_flag = 1;
00182 
00183   switch (mtype) {
00184 
00185   case DATA_DECIMAL:
00186     /* Remove preceding spaces */
00187     for (; a_length && *a == ' '; a++, a_length--) {}
00188     for (; b_length && *b == ' '; b++, b_length--) {}
00189 
00190     if (*a == '-') {
00191       if (*b != '-') {
00192         return(-1);
00193       }
00194 
00195       a++; b++;
00196       a_length--;
00197       b_length--;
00198 
00199       swap_flag = -1;
00200 
00201     } else if (*b == '-') {
00202 
00203       return(1);
00204     }
00205 
00206     while (a_length > 0 && (*a == '+' || *a == '0')) {
00207       a++; a_length--;
00208     }
00209 
00210     while (b_length > 0 && (*b == '+' || *b == '0')) {
00211       b++; b_length--;
00212     }
00213 
00214     if (a_length != b_length) {
00215       if (a_length < b_length) {
00216         return(-swap_flag);
00217       }
00218 
00219       return(swap_flag);
00220     }
00221 
00222     while (a_length > 0 && *a == *b) {
00223 
00224       a++; b++; a_length--;
00225     }
00226 
00227     if (a_length == 0) {
00228 
00229       return(0);
00230     }
00231 
00232     if (*a > *b) {
00233       return(swap_flag);
00234     }
00235 
00236     return(-swap_flag);
00237   case DATA_DOUBLE:
00238     d_1 = mach_double_read(a);
00239     d_2 = mach_double_read(b);
00240 
00241     if (d_1 > d_2) {
00242       return(1);
00243     } else if (d_2 > d_1) {
00244       return(-1);
00245     }
00246 
00247     return(0);
00248 
00249   case DATA_FLOAT:
00250     f_1 = mach_float_read(a);
00251     f_2 = mach_float_read(b);
00252 
00253     if (f_1 > f_2) {
00254       return(1);
00255     } else if (f_2 > f_1) {
00256       return(-1);
00257     }
00258 
00259     return(0);
00260   case DATA_BLOB:
00261     if (prtype & DATA_BINARY_TYPE) {
00262 
00263       ut_print_timestamp(stderr);
00264       fprintf(stderr,
00265         "  InnoDB: Error: comparing a binary BLOB"
00266         " with a character set sensitive\n"
00267         "InnoDB: comparison!\n");
00268     }
00269     /* fall through */
00270   case DATA_VARMYSQL:
00271   case DATA_MYSQL:
00272     return(innobase_mysql_cmp(
00273              (int)(prtype & DATA_MYSQL_TYPE_MASK),
00274              (uint)dtype_get_charset_coll(prtype),
00275              a, a_length, b, b_length));
00276   default:
00277     fprintf(stderr,
00278       "InnoDB: unknown type number %lu\n",
00279       (ulong) mtype);
00280     ut_error;
00281   }
00282 
00283   return(0);
00284 }
00285 
00286 /*************************************************************/
00290 UNIV_INTERN
00291 int
00292 cmp_data_data_slow(
00293 /*===============*/
00294   ulint   mtype,  
00295   ulint   prtype, 
00296   const byte* data1,  
00298   ulint   len1, 
00299   const byte* data2,  
00301   ulint   len2) 
00302 {
00303   ulint data1_byte;
00304   ulint data2_byte;
00305   ulint cur_bytes;
00306 
00307   if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) {
00308 
00309     if (len1 == len2) {
00310 
00311       return(0);
00312     }
00313 
00314     if (len1 == UNIV_SQL_NULL) {
00315       /* We define the SQL null to be the smallest possible
00316       value of a field in the alphabetical order */
00317 
00318       return(-1);
00319     }
00320 
00321     return(1);
00322   }
00323 
00324   if (mtype >= DATA_FLOAT
00325       || (mtype == DATA_BLOB
00326     && 0 == (prtype & DATA_BINARY_TYPE)
00327     && dtype_get_charset_coll(prtype)
00328     != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
00329 
00330     return(cmp_whole_field(mtype, prtype,
00331                data1, (unsigned) len1,
00332                data2, (unsigned) len2));
00333   }
00334 
00335   /* Compare then the fields */
00336 
00337   cur_bytes = 0;
00338 
00339   for (;;) {
00340     if (len1 <= cur_bytes) {
00341       if (len2 <= cur_bytes) {
00342 
00343         return(0);
00344       }
00345 
00346       data1_byte = dtype_get_pad_char(mtype, prtype);
00347 
00348       if (data1_byte == ULINT_UNDEFINED) {
00349 
00350         return(-1);
00351       }
00352     } else {
00353       data1_byte = *data1;
00354     }
00355 
00356     if (len2 <= cur_bytes) {
00357       data2_byte = dtype_get_pad_char(mtype, prtype);
00358 
00359       if (data2_byte == ULINT_UNDEFINED) {
00360 
00361         return(1);
00362       }
00363     } else {
00364       data2_byte = *data2;
00365     }
00366 
00367     if (data1_byte == data2_byte) {
00368       /* If the bytes are equal, they will remain such even
00369       after the collation transformation below */
00370 
00371       goto next_byte;
00372     }
00373 
00374     if (mtype <= DATA_CHAR
00375         || (mtype == DATA_BLOB
00376       && 0 == (prtype & DATA_BINARY_TYPE))) {
00377 
00378       data1_byte = cmp_collate(data1_byte);
00379       data2_byte = cmp_collate(data2_byte);
00380     }
00381 
00382     if (data1_byte > data2_byte) {
00383 
00384       return(1);
00385     } else if (data1_byte < data2_byte) {
00386 
00387       return(-1);
00388     }
00389 next_byte:
00390     /* Next byte */
00391     cur_bytes++;
00392     data1++;
00393     data2++;
00394   }
00395 
00396 }
00397 
00398 /*************************************************************/
00409 UNIV_INTERN
00410 int
00411 cmp_dtuple_rec_with_match(
00412 /*======================*/
00413   const dtuple_t* dtuple, 
00414   const rec_t*  rec,  
00418   const ulint*  offsets,
00419   ulint*    matched_fields, 
00422   ulint*    matched_bytes) 
00426 {
00427   const dfield_t* dtuple_field; /* current field in logical record */
00428   ulint   dtuple_f_len; /* the length of the current field
00429           in the logical record */
00430   const byte* dtuple_b_ptr; /* pointer to the current byte in
00431           logical field data */
00432   ulint   dtuple_byte;  /* value of current byte to be compared
00433           in dtuple*/
00434   ulint   rec_f_len;  /* length of current field in rec */
00435   const byte* rec_b_ptr;  /* pointer to the current byte in
00436           rec field */
00437   ulint   rec_byte; /* value of current byte to be
00438           compared in rec */
00439   ulint   cur_field;  /* current field number */
00440   ulint   cur_bytes;  /* number of already matched bytes
00441           in current field */
00442   int   ret = 3333; /* return value */
00443 
00444   ut_ad(dtuple && rec && matched_fields && matched_bytes);
00445   ut_ad(dtuple_check_typed(dtuple));
00446   ut_ad(rec_offs_validate(rec, NULL, offsets));
00447 
00448   cur_field = *matched_fields;
00449   cur_bytes = *matched_bytes;
00450 
00451   ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
00452   ut_ad(cur_field <= rec_offs_n_fields(offsets));
00453 
00454   if (cur_bytes == 0 && cur_field == 0) {
00455     ulint rec_info = rec_get_info_bits(rec,
00456                  rec_offs_comp(offsets));
00457     ulint tup_info = dtuple_get_info_bits(dtuple);
00458 
00459     if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) {
00460       ret = !(tup_info & REC_INFO_MIN_REC_FLAG);
00461       goto order_resolved;
00462     } else if (UNIV_UNLIKELY(tup_info & REC_INFO_MIN_REC_FLAG)) {
00463       ret = -1;
00464       goto order_resolved;
00465     }
00466   }
00467 
00468   /* Match fields in a loop; stop if we run out of fields in dtuple
00469   or find an externally stored field */
00470 
00471   while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
00472 
00473     ulint mtype;
00474     ulint prtype;
00475 
00476     dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
00477     {
00478       const dtype_t*  type
00479         = dfield_get_type(dtuple_field);
00480 
00481       mtype = type->mtype;
00482       prtype = type->prtype;
00483     }
00484 
00485     dtuple_f_len = dfield_get_len(dtuple_field);
00486 
00487     rec_b_ptr = rec_get_nth_field(rec, offsets,
00488                 cur_field, &rec_f_len);
00489 
00490     /* If we have matched yet 0 bytes, it may be that one or
00491     both the fields are SQL null, or the record or dtuple may be
00492     the predefined minimum record, or the field is externally
00493     stored */
00494 
00495     if (UNIV_LIKELY(cur_bytes == 0)) {
00496       if (rec_offs_nth_extern(offsets, cur_field)) {
00497         /* We do not compare to an externally
00498         stored field */
00499 
00500         ret = 0;
00501 
00502         goto order_resolved;
00503       }
00504 
00505       if (dtuple_f_len == UNIV_SQL_NULL) {
00506         if (rec_f_len == UNIV_SQL_NULL) {
00507 
00508           goto next_field;
00509         }
00510 
00511         ret = -1;
00512         goto order_resolved;
00513       } else if (rec_f_len == UNIV_SQL_NULL) {
00514         /* We define the SQL null to be the
00515         smallest possible value of a field
00516         in the alphabetical order */
00517 
00518         ret = 1;
00519         goto order_resolved;
00520       }
00521     }
00522 
00523     if (mtype >= DATA_FLOAT
00524         || (mtype == DATA_BLOB
00525       && 0 == (prtype & DATA_BINARY_TYPE)
00526       && dtype_get_charset_coll(prtype)
00527       != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
00528 
00529       ret = cmp_whole_field(mtype, prtype,
00530                 static_cast<const unsigned char *>(dfield_get_data(dtuple_field)),
00531                 (unsigned) dtuple_f_len,
00532                 rec_b_ptr, (unsigned) rec_f_len);
00533 
00534       if (ret != 0) {
00535         cur_bytes = 0;
00536 
00537         goto order_resolved;
00538       } else {
00539         goto next_field;
00540       }
00541     }
00542 
00543     /* Set the pointers at the current byte */
00544 
00545     rec_b_ptr = rec_b_ptr + cur_bytes;
00546     dtuple_b_ptr = (byte*)dfield_get_data(dtuple_field)
00547       + cur_bytes;
00548     /* Compare then the fields */
00549 
00550     for (;;) {
00551       if (UNIV_UNLIKELY(rec_f_len <= cur_bytes)) {
00552         if (dtuple_f_len <= cur_bytes) {
00553 
00554           goto next_field;
00555         }
00556 
00557         rec_byte = dtype_get_pad_char(mtype, prtype);
00558 
00559         if (rec_byte == ULINT_UNDEFINED) {
00560           ret = 1;
00561 
00562           goto order_resolved;
00563         }
00564       } else {
00565         rec_byte = *rec_b_ptr;
00566       }
00567 
00568       if (UNIV_UNLIKELY(dtuple_f_len <= cur_bytes)) {
00569         dtuple_byte = dtype_get_pad_char(mtype,
00570                  prtype);
00571 
00572         if (dtuple_byte == ULINT_UNDEFINED) {
00573           ret = -1;
00574 
00575           goto order_resolved;
00576         }
00577       } else {
00578         dtuple_byte = *dtuple_b_ptr;
00579       }
00580 
00581       if (dtuple_byte == rec_byte) {
00582         /* If the bytes are equal, they will
00583         remain such even after the collation
00584         transformation below */
00585 
00586         goto next_byte;
00587       }
00588 
00589       if (mtype <= DATA_CHAR
00590           || (mtype == DATA_BLOB
00591         && !(prtype & DATA_BINARY_TYPE))) {
00592 
00593         rec_byte = cmp_collate(rec_byte);
00594         dtuple_byte = cmp_collate(dtuple_byte);
00595       }
00596 
00597       ret = (int) (dtuple_byte - rec_byte);
00598       if (UNIV_LIKELY(ret)) {
00599         if (ret < 0) {
00600           ret = -1;
00601           goto order_resolved;
00602         } else {
00603           ret = 1;
00604           goto order_resolved;
00605         }
00606       }
00607 next_byte:
00608       /* Next byte */
00609       cur_bytes++;
00610       rec_b_ptr++;
00611       dtuple_b_ptr++;
00612     }
00613 
00614 next_field:
00615     cur_field++;
00616     cur_bytes = 0;
00617   }
00618 
00619   ut_ad(cur_bytes == 0);
00620 
00621   ret = 0;  /* If we ran out of fields, dtuple was equal to rec
00622       up to the common fields */
00623 order_resolved:
00624   ut_ad((ret >= - 1) && (ret <= 1));
00625   ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
00626                  matched_fields));
00627   ut_ad(*matched_fields == cur_field); /* In the debug version, the
00628                above cmp_debug_... sets
00629                *matched_fields to a value */
00630   *matched_fields = cur_field;
00631   *matched_bytes = cur_bytes;
00632 
00633   return(ret);
00634 }
00635 
00636 /**************************************************************/
00640 UNIV_INTERN
00641 int
00642 cmp_dtuple_rec(
00643 /*===========*/
00644   const dtuple_t* dtuple, 
00645   const rec_t*  rec,  
00646   const ulint*  offsets)
00647 {
00648   ulint matched_fields  = 0;
00649   ulint matched_bytes = 0;
00650 
00651   ut_ad(rec_offs_validate(rec, NULL, offsets));
00652   return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
00653            &matched_fields, &matched_bytes));
00654 }
00655 
00656 /**************************************************************/
00660 UNIV_INTERN
00661 ibool
00662 cmp_dtuple_is_prefix_of_rec(
00663 /*========================*/
00664   const dtuple_t* dtuple, 
00665   const rec_t*  rec,  
00666   const ulint*  offsets)
00667 {
00668   ulint n_fields;
00669   ulint matched_fields  = 0;
00670   ulint matched_bytes = 0;
00671 
00672   ut_ad(rec_offs_validate(rec, NULL, offsets));
00673   n_fields = dtuple_get_n_fields(dtuple);
00674 
00675   if (n_fields > rec_offs_n_fields(offsets)) {
00676 
00677     return(FALSE);
00678   }
00679 
00680   cmp_dtuple_rec_with_match(dtuple, rec, offsets,
00681           &matched_fields, &matched_bytes);
00682   if (matched_fields == n_fields) {
00683 
00684     return(TRUE);
00685   }
00686 
00687   if (matched_fields == n_fields - 1
00688       && matched_bytes == dfield_get_len(
00689         dtuple_get_nth_field(dtuple, n_fields - 1))) {
00690     return(TRUE);
00691   }
00692 
00693   return(FALSE);
00694 }
00695 
00696 /*************************************************************/
00700 UNIV_INTERN
00701 int
00702 cmp_rec_rec_simple(
00703 /*===============*/
00704   const rec_t*    rec1, 
00705   const rec_t*    rec2, 
00706   const ulint*    offsets1,
00707   const ulint*    offsets2,
00708   const dict_index_t* index,  
00709   ibool*      null_eq)
00711 {
00712   ulint   rec1_f_len; 
00713   const byte* rec1_b_ptr; 
00715   ulint   rec1_byte;  
00717   ulint   rec2_f_len; 
00718   const byte* rec2_b_ptr; 
00720   ulint   rec2_byte;  
00722   ulint   cur_field;  
00723   ulint   n_uniq;
00724 
00725   n_uniq = dict_index_get_n_unique(index);
00726   ut_ad(rec_offs_n_fields(offsets1) >= n_uniq);
00727   ut_ad(rec_offs_n_fields(offsets2) >= n_uniq);
00728 
00729   ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
00730 
00731   for (cur_field = 0; cur_field < n_uniq; cur_field++) {
00732 
00733     ulint cur_bytes;
00734     ulint mtype;
00735     ulint prtype;
00736 
00737     {
00738       const dict_col_t* col
00739         = dict_index_get_nth_col(index, cur_field);
00740 
00741       mtype = col->mtype;
00742       prtype = col->prtype;
00743     }
00744 
00745     ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
00746     ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
00747 
00748     rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
00749                  cur_field, &rec1_f_len);
00750     rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
00751                  cur_field, &rec2_f_len);
00752 
00753     if (rec1_f_len == UNIV_SQL_NULL
00754         || rec2_f_len == UNIV_SQL_NULL) {
00755 
00756       if (rec1_f_len == rec2_f_len) {
00757         if (null_eq) {
00758           *null_eq = TRUE;
00759         }
00760 
00761         goto next_field;
00762 
00763       } else if (rec2_f_len == UNIV_SQL_NULL) {
00764 
00765         /* We define the SQL null to be the
00766         smallest possible value of a field
00767         in the alphabetical order */
00768 
00769         return(1);
00770       } else {
00771         return(-1);
00772       }
00773     }
00774 
00775     if (mtype >= DATA_FLOAT
00776         || (mtype == DATA_BLOB
00777       && 0 == (prtype & DATA_BINARY_TYPE)
00778       && dtype_get_charset_coll(prtype)
00779       != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
00780       int ret = cmp_whole_field(mtype, prtype,
00781               rec1_b_ptr,
00782               (unsigned) rec1_f_len,
00783               rec2_b_ptr,
00784               (unsigned) rec2_f_len);
00785       if (ret) {
00786         return(ret);
00787       }
00788 
00789       goto next_field;
00790     }
00791 
00792     /* Compare the fields */
00793     for (cur_bytes = 0;; cur_bytes++, rec1_b_ptr++, rec2_b_ptr++) {
00794       if (rec2_f_len <= cur_bytes) {
00795 
00796         if (rec1_f_len <= cur_bytes) {
00797 
00798           goto next_field;
00799         }
00800 
00801         rec2_byte = dtype_get_pad_char(mtype, prtype);
00802 
00803         if (rec2_byte == ULINT_UNDEFINED) {
00804           return(1);
00805         }
00806       } else {
00807         rec2_byte = *rec2_b_ptr;
00808       }
00809 
00810       if (rec1_f_len <= cur_bytes) {
00811         rec1_byte = dtype_get_pad_char(mtype, prtype);
00812 
00813         if (rec1_byte == ULINT_UNDEFINED) {
00814           return(-1);
00815         }
00816       } else {
00817         rec1_byte = *rec1_b_ptr;
00818       }
00819 
00820       if (rec1_byte == rec2_byte) {
00821         /* If the bytes are equal, they will remain
00822         such even after the collation transformation
00823         below */
00824 
00825         continue;
00826       }
00827 
00828       if (mtype <= DATA_CHAR
00829           || (mtype == DATA_BLOB
00830         && !(prtype & DATA_BINARY_TYPE))) {
00831 
00832         rec1_byte = cmp_collate(rec1_byte);
00833         rec2_byte = cmp_collate(rec2_byte);
00834       }
00835 
00836       if (rec1_byte < rec2_byte) {
00837         return(-1);
00838       } else if (rec1_byte > rec2_byte) {
00839         return(1);
00840       }
00841     }
00842 next_field:
00843     continue;
00844   }
00845 
00846   /* If we ran out of fields, rec1 was equal to rec2. */
00847   return(0);
00848 }
00849 
00850 /*************************************************************/
00855 UNIV_INTERN
00856 int
00857 cmp_rec_rec_with_match(
00858 /*===================*/
00859   const rec_t*  rec1, 
00860   const rec_t*  rec2, 
00861   const ulint*  offsets1,
00862   const ulint*  offsets2,
00863   dict_index_t* index,  
00864   ulint*    matched_fields, 
00868   ulint*    matched_bytes) 
00872 {
00873   ulint   rec1_n_fields;  /* the number of fields in rec */
00874   ulint   rec1_f_len; /* length of current field in rec */
00875   const byte* rec1_b_ptr; /* pointer to the current byte
00876           in rec field */
00877   ulint   rec1_byte;  /* value of current byte to be
00878           compared in rec */
00879   ulint   rec2_n_fields;  /* the number of fields in rec */
00880   ulint   rec2_f_len; /* length of current field in rec */
00881   const byte* rec2_b_ptr; /* pointer to the current byte
00882           in rec field */
00883   ulint   rec2_byte;  /* value of current byte to be
00884           compared in rec */
00885   ulint   cur_field;  /* current field number */
00886   ulint   cur_bytes;  /* number of already matched
00887           bytes in current field */
00888   int   ret = 0;  /* return value */
00889   ulint   comp;
00890 
00891   ut_ad(rec1 && rec2 && index);
00892   ut_ad(rec_offs_validate(rec1, index, offsets1));
00893   ut_ad(rec_offs_validate(rec2, index, offsets2));
00894   ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
00895 
00896   comp = rec_offs_comp(offsets1);
00897   rec1_n_fields = rec_offs_n_fields(offsets1);
00898   rec2_n_fields = rec_offs_n_fields(offsets2);
00899 
00900   cur_field = *matched_fields;
00901   cur_bytes = *matched_bytes;
00902 
00903   /* Match fields in a loop */
00904 
00905   while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
00906 
00907     ulint mtype;
00908     ulint prtype;
00909 
00910     if (UNIV_UNLIKELY(index->type & DICT_UNIVERSAL)) {
00911       /* This is for the insert buffer B-tree. */
00912       mtype = DATA_BINARY;
00913       prtype = 0;
00914     } else {
00915       const dict_col_t* col
00916         = dict_index_get_nth_col(index, cur_field);
00917 
00918       mtype = col->mtype;
00919       prtype = col->prtype;
00920     }
00921 
00922     rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
00923                  cur_field, &rec1_f_len);
00924     rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
00925                  cur_field, &rec2_f_len);
00926 
00927     if (cur_bytes == 0) {
00928       if (cur_field == 0) {
00929         /* Test if rec is the predefined minimum
00930         record */
00931         if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
00932               & REC_INFO_MIN_REC_FLAG)) {
00933 
00934           if (!(rec_get_info_bits(rec2, comp)
00935                 & REC_INFO_MIN_REC_FLAG)) {
00936             ret = -1;
00937           }
00938 
00939           goto order_resolved;
00940 
00941         } else if (UNIV_UNLIKELY
00942              (rec_get_info_bits(rec2, comp)
00943               & REC_INFO_MIN_REC_FLAG)) {
00944 
00945           ret = 1;
00946 
00947           goto order_resolved;
00948         }
00949       }
00950 
00951       if (rec_offs_nth_extern(offsets1, cur_field)
00952           || rec_offs_nth_extern(offsets2, cur_field)) {
00953         /* We do not compare to an externally
00954         stored field */
00955 
00956         goto order_resolved;
00957       }
00958 
00959       if (rec1_f_len == UNIV_SQL_NULL
00960           || rec2_f_len == UNIV_SQL_NULL) {
00961 
00962         if (rec1_f_len == rec2_f_len) {
00963 
00964           goto next_field;
00965 
00966         } else if (rec2_f_len == UNIV_SQL_NULL) {
00967 
00968           /* We define the SQL null to be the
00969           smallest possible value of a field
00970           in the alphabetical order */
00971 
00972           ret = 1;
00973         } else {
00974           ret = -1;
00975         }
00976 
00977         goto order_resolved;
00978       }
00979     }
00980 
00981     if (mtype >= DATA_FLOAT
00982         || (mtype == DATA_BLOB
00983       && 0 == (prtype & DATA_BINARY_TYPE)
00984       && dtype_get_charset_coll(prtype)
00985       != DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL)) {
00986 
00987       ret = cmp_whole_field(mtype, prtype,
00988                 rec1_b_ptr,
00989                 (unsigned) rec1_f_len,
00990                 rec2_b_ptr,
00991                 (unsigned) rec2_f_len);
00992       if (ret != 0) {
00993         cur_bytes = 0;
00994 
00995         goto order_resolved;
00996       } else {
00997         goto next_field;
00998       }
00999     }
01000 
01001     /* Set the pointers at the current byte */
01002     rec1_b_ptr = rec1_b_ptr + cur_bytes;
01003     rec2_b_ptr = rec2_b_ptr + cur_bytes;
01004 
01005     /* Compare then the fields */
01006     for (;;) {
01007       if (rec2_f_len <= cur_bytes) {
01008 
01009         if (rec1_f_len <= cur_bytes) {
01010 
01011           goto next_field;
01012         }
01013 
01014         rec2_byte = dtype_get_pad_char(mtype, prtype);
01015 
01016         if (rec2_byte == ULINT_UNDEFINED) {
01017           ret = 1;
01018 
01019           goto order_resolved;
01020         }
01021       } else {
01022         rec2_byte = *rec2_b_ptr;
01023       }
01024 
01025       if (rec1_f_len <= cur_bytes) {
01026         rec1_byte = dtype_get_pad_char(mtype, prtype);
01027 
01028         if (rec1_byte == ULINT_UNDEFINED) {
01029           ret = -1;
01030 
01031           goto order_resolved;
01032         }
01033       } else {
01034         rec1_byte = *rec1_b_ptr;
01035       }
01036 
01037       if (rec1_byte == rec2_byte) {
01038         /* If the bytes are equal, they will remain
01039         such even after the collation transformation
01040         below */
01041 
01042         goto next_byte;
01043       }
01044 
01045       if (mtype <= DATA_CHAR
01046           || (mtype == DATA_BLOB
01047         && !(prtype & DATA_BINARY_TYPE))) {
01048 
01049         rec1_byte = cmp_collate(rec1_byte);
01050         rec2_byte = cmp_collate(rec2_byte);
01051       }
01052 
01053       if (rec1_byte < rec2_byte) {
01054         ret = -1;
01055         goto order_resolved;
01056       } else if (rec1_byte > rec2_byte) {
01057         ret = 1;
01058         goto order_resolved;
01059       }
01060 next_byte:
01061       /* Next byte */
01062 
01063       cur_bytes++;
01064       rec1_b_ptr++;
01065       rec2_b_ptr++;
01066     }
01067 
01068 next_field:
01069     cur_field++;
01070     cur_bytes = 0;
01071   }
01072 
01073   ut_ad(cur_bytes == 0);
01074 
01075   /* If we ran out of fields, rec1 was equal to rec2 up
01076   to the common fields */
01077   ut_ad(ret == 0);
01078 order_resolved:
01079 
01080   ut_ad((ret >= - 1) && (ret <= 1));
01081 
01082   *matched_fields = cur_field;
01083   *matched_bytes = cur_bytes;
01084 
01085   return(ret);
01086 }
01087 
01088 #ifdef UNIV_DEBUG
01089 /*************************************************************/
01097 static
01098 int
01099 cmp_debug_dtuple_rec_with_match(
01100 /*============================*/
01101   const dtuple_t* dtuple, 
01102   const rec_t*  rec,  
01106   const ulint*  offsets,
01107   ulint*    matched_fields) 
01111 {
01112   const dfield_t* dtuple_field; /* current field in logical record */
01113   ulint   dtuple_f_len; /* the length of the current field
01114           in the logical record */
01115   const byte* dtuple_f_data;  /* pointer to the current logical
01116           field data */
01117   ulint   rec_f_len;  /* length of current field in rec */
01118   const byte* rec_f_data; /* pointer to the current rec field */
01119   int   ret = 3333; /* return value */
01120   ulint   cur_field;  /* current field number */
01121 
01122   ut_ad(dtuple && rec && matched_fields);
01123   ut_ad(dtuple_check_typed(dtuple));
01124   ut_ad(rec_offs_validate(rec, NULL, offsets));
01125 
01126   ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
01127   ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
01128 
01129   cur_field = *matched_fields;
01130 
01131   if (cur_field == 0) {
01132     if (UNIV_UNLIKELY
01133         (rec_get_info_bits(rec, rec_offs_comp(offsets))
01134          & REC_INFO_MIN_REC_FLAG)) {
01135 
01136       ret = !(dtuple_get_info_bits(dtuple)
01137         & REC_INFO_MIN_REC_FLAG);
01138 
01139       goto order_resolved;
01140     }
01141 
01142     if (UNIV_UNLIKELY
01143         (dtuple_get_info_bits(dtuple) & REC_INFO_MIN_REC_FLAG)) {
01144       ret = -1;
01145 
01146       goto order_resolved;
01147     }
01148   }
01149 
01150   /* Match fields in a loop; stop if we run out of fields in dtuple */
01151 
01152   while (cur_field < dtuple_get_n_fields_cmp(dtuple)) {
01153 
01154     ulint mtype;
01155     ulint prtype;
01156 
01157     dtuple_field = dtuple_get_nth_field(dtuple, cur_field);
01158     {
01159       const dtype_t*  type
01160         = dfield_get_type(dtuple_field);
01161 
01162       mtype = type->mtype;
01163       prtype = type->prtype;
01164     }
01165 
01166     dtuple_f_data = dfield_get_data(dtuple_field);
01167     dtuple_f_len = dfield_get_len(dtuple_field);
01168 
01169     rec_f_data = rec_get_nth_field(rec, offsets,
01170                  cur_field, &rec_f_len);
01171 
01172     if (rec_offs_nth_extern(offsets, cur_field)) {
01173       /* We do not compare to an externally stored field */
01174 
01175       ret = 0;
01176 
01177       goto order_resolved;
01178     }
01179 
01180     ret = cmp_data_data(mtype, prtype, dtuple_f_data, dtuple_f_len,
01181             rec_f_data, rec_f_len);
01182     if (ret != 0) {
01183       goto order_resolved;
01184     }
01185 
01186     cur_field++;
01187   }
01188 
01189   ret = 0;  /* If we ran out of fields, dtuple was equal to rec
01190       up to the common fields */
01191 order_resolved:
01192   ut_ad((ret >= - 1) && (ret <= 1));
01193 
01194   *matched_fields = cur_field;
01195 
01196   return(ret);
01197 }
01198 #endif /* UNIV_DEBUG */