diff options
Diffstat (limited to 'storage/innobase/rem/rem0cmp.cc')
-rw-r--r-- | storage/innobase/rem/rem0cmp.cc | 240 |
1 files changed, 90 insertions, 150 deletions
diff --git a/storage/innobase/rem/rem0cmp.cc b/storage/innobase/rem/rem0cmp.cc index 7fb6fdac1ba..a77ddafd568 100644 --- a/storage/innobase/rem/rem0cmp.cc +++ b/storage/innobase/rem/rem0cmp.cc @@ -190,61 +190,68 @@ cmp_decimal(const byte* a, ulint a_length, const byte* b, ulint b_length) } /** Compare two data fields. -@param mtype main type -@param prtype precise type -@param data1 data field -@param len1 length of data1 in bytes, or UNIV_SQL_NULL -@param data2 data field -@param len2 length of data2 in bytes, or UNIV_SQL_NULL +@param mtype main type +@param prtype precise type +@param descending whether to use descending order +@param data1 data field +@param len1 length of data1 in bytes, or UNIV_SQL_NULL +@param data2 data field +@param len2 length of data2 in bytes, or UNIV_SQL_NULL @return the comparison result of data1 and data2 @retval 0 if data1 is equal to data2 @retval negative if data1 is less than data2 @retval positive if data1 is greater than data2 */ -static int cmp_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, - const byte *data2, ulint len2) +int cmp_data(ulint mtype, ulint prtype, bool descending, + const byte *data1, size_t len1, const byte *data2, size_t len2) { ut_ad(len1 != UNIV_SQL_DEFAULT); ut_ad(len2 != UNIV_SQL_DEFAULT); + int cmp= 0; + if (len1 == UNIV_SQL_NULL || len2 == UNIV_SQL_NULL) { if (len1 == len2) return 0; /* We define the SQL null to be the smallest possible value of a field. */ - return len1 == UNIV_SQL_NULL ? -1 : 1; + cmp= len1 == UNIV_SQL_NULL ? -1 : 1; + func_exit: + return UNIV_UNLIKELY(descending) ? -cmp : cmp; } switch (mtype) { default: ib::fatal() << "Unknown data type number " << mtype; case DATA_DECIMAL: - return cmp_decimal(data1, len1, data2, len2); + cmp= cmp_decimal(data1, len1, data2, len2); + goto func_exit; case DATA_DOUBLE: { const double af= mach_double_read(data1), bf= mach_double_read(data2); - return af > bf ? 1 : bf > af ? -1 : 0; + cmp= af > bf ? 1 : bf > af ? -1 : 0; } + goto func_exit; case DATA_FLOAT: { const float af= mach_float_read(data1), bf= mach_float_read(data2); - return af > bf ? 1 : bf > af ? -1 : 0; + cmp= af > bf ? 1 : bf > af ? -1 : 0; } + goto func_exit; case DATA_FIXBINARY: case DATA_BINARY: if (dtype_get_charset_coll(prtype) != DATA_MYSQL_BINARY_CHARSET_COLL) { if (ulint len= std::min(len1, len2)) { - if (int cmp= memcmp(data1, data2, len)) - return cmp; + cmp= memcmp(data1, data2, len); + if (cmp) + goto func_exit; data1+= len; data2+= len; len1-= len; len2-= len; } - - int cmp= 0; if (len1) { const byte *end= &data1[len1]; @@ -259,7 +266,7 @@ static int cmp_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, cmp= static_cast<int>(byte{0x20} - *data2++); while (cmp == 0 && data2 < end); } - return cmp; + goto func_exit; } /* fall through */ case DATA_INT: @@ -272,7 +279,8 @@ static int cmp_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, { ut_ad(len1 == DATA_MBR_LEN); ut_ad(len2 == DATA_MBR_LEN); - return cmp_geometry_field(data1, data2); + cmp= cmp_geometry_field(data1, data2); + goto func_exit; } break; case DATA_BLOB: @@ -282,14 +290,20 @@ static int cmp_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, case DATA_VARMYSQL: DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK)); if (CHARSET_INFO *cs= all_charsets[dtype_get_charset_coll(prtype)]) - return cs->coll->strnncollsp(cs, data1, len1, data2, len2); + { + cmp= cs->coll->strnncollsp(cs, data1, len1, data2, len2); + goto func_exit; + } no_collation: ib::fatal() << "Unable to find charset-collation for " << prtype; case DATA_MYSQL: DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK)); if (CHARSET_INFO *cs= all_charsets[dtype_get_charset_coll(prtype)]) - return cs->coll->strnncollsp_nchars(cs, data1, len1, data2, len2, - std::max(len1, len2)); + { + cmp= cs->coll->strnncollsp_nchars(cs, data1, len1, data2, len2, + std::max(len1, len2)); + goto func_exit; + } goto no_collation; case DATA_VARCHAR: case DATA_CHAR: @@ -297,62 +311,42 @@ static int cmp_data(ulint mtype, ulint prtype, const byte *data1, ulint len1, Because it is a fixed-length encoding (mbminlen=mbmaxlen=1), non-NULL CHAR(n) values will always occupy n bytes and we can invoke strnncollsp() instead of strnncollsp_nchars(). */ - return my_charset_latin1.strnncollsp(data1, len1, data2, len2); + cmp= my_charset_latin1.strnncollsp(data1, len1, data2, len2); + goto func_exit; } if (ulint len= std::min(len1, len2)) - if (int cmp= memcmp(data1, data2, len)) - return cmp; + { + cmp= memcmp(data1, data2, len); + if (cmp) + goto func_exit; + } - return len1 > len2 ? 1 : len2 > len1 ? -1 : 0; -} - -/** Compare two data fields. -@param[in] mtype main type -@param[in] prtype precise type -@param[in] data1 data field -@param[in] len1 length of data1 in bytes, or UNIV_SQL_NULL -@param[in] data2 data field -@param[in] len2 length of data2 in bytes, or UNIV_SQL_NULL -@return the comparison result of data1 and data2 -@retval 0 if data1 is equal to data2 -@retval negative if data1 is less than data2 -@retval positive if data1 is greater than data2 */ -int -cmp_data_data( - ulint mtype, - ulint prtype, - const byte* data1, - ulint len1, - const byte* data2, - ulint len2) -{ - return(cmp_data(mtype, prtype, data1, len1, data2, len2)); + cmp= int(len1 - len2); + goto func_exit; } /** Compare a data tuple to a physical record. -@param[in] dtuple data tuple -@param[in] rec B-tree record -@param[in] offsets rec_get_offsets(rec) -@param[in] n_cmp number of fields to compare -@param[in,out] matched_fields number of completely matched fields +@param dtuple data tuple +@param rec B-tree index record +@param index B-tree index +@param offsets rec_get_offsets(rec,index) +@param n_cmp number of fields to compare +@param matched_fields number of completely matched fields @return the comparison result of dtuple and rec @retval 0 if dtuple is equal to rec @retval negative if dtuple is less than rec @retval positive if dtuple is greater than rec */ -int -cmp_dtuple_rec_with_match_low( - const dtuple_t* dtuple, - const rec_t* rec, - const rec_offs* offsets, - ulint n_cmp, - ulint* matched_fields) +int cmp_dtuple_rec_with_match_low(const dtuple_t *dtuple, const rec_t *rec, + const dict_index_t *index, + const rec_offs *offsets, + ulint n_cmp, ulint *matched_fields) { ulint cur_field; /* current field number */ - int ret; /* return value */ + int ret = 0; /* return value */ ut_ad(dtuple_check_typed(dtuple)); - ut_ad(rec_offs_validate(rec, NULL, offsets)); + ut_ad(rec_offs_validate(rec, index, offsets)); cur_field = *matched_fields; @@ -366,6 +360,7 @@ cmp_dtuple_rec_with_match_low( rec_offs_comp(offsets)); ulint tup_info = dtuple_get_info_bits(dtuple); + /* The "infimum node pointer" is always first. */ if (UNIV_UNLIKELY(rec_info & REC_INFO_MIN_REC_FLAG)) { ret = !(tup_info & REC_INFO_MIN_REC_FLAG); goto order_resolved; @@ -406,7 +401,8 @@ cmp_dtuple_rec_with_match_low( ut_ad(!dfield_is_ext(dtuple_field)); - ret = cmp_data(type->mtype, type->prtype, + ret = cmp_data(type->mtype, type->prtype, !index->is_ibuf() + && index->fields[cur_field].descending, dtuple_b_ptr, dtuple_f_len, rec_b_ptr, rec_f_len); if (ret) { @@ -414,8 +410,6 @@ cmp_dtuple_rec_with_match_low( } } - ret = 0; /* If we ran out of fields, dtuple was equal to rec - up to the common fields */ order_resolved: *matched_fields = cur_field; return(ret); @@ -486,6 +480,7 @@ cmp_dtuple_rec_with_match_bytes( ut_ad(rec_offs_validate(rec, index, offsets)); ut_ad(!(REC_INFO_MIN_REC_FLAG & dtuple_get_info_bits(dtuple))); + ut_ad(!index->is_ibuf()); if (UNIV_UNLIKELY(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(rec, rec_offs_comp(offsets)))) { @@ -498,7 +493,7 @@ cmp_dtuple_rec_with_match_bytes( ulint cur_field = *matched_fields; ulint cur_bytes = *matched_bytes; ulint n_cmp = dtuple_get_n_fields_cmp(dtuple); - int ret; + int ret = 0; ut_ad(n_cmp <= dtuple_get_n_fields(dtuple)); ut_ad(cur_field <= n_cmp); @@ -559,7 +554,7 @@ cmp_dtuple_rec_with_match_bytes( } /* fall through */ default: - ret = cmp_data(type->mtype, type->prtype, + ret = cmp_data(type->mtype, type->prtype, false, dtuple_b_ptr, dtuple_f_len, rec_b_ptr, rec_f_len); @@ -623,62 +618,29 @@ next_field: ut_ad(cur_bytes == 0); - ret = 0; /* If we ran out of fields, dtuple was equal to rec - up to the common fields */ order_resolved: *matched_fields = cur_field; *matched_bytes = cur_bytes; - return(ret); + return !ret || UNIV_LIKELY(!index->fields[cur_field].descending) + ? ret : -ret; } -/** Compare a data tuple to a physical record. -@see cmp_dtuple_rec_with_match -@param[in] dtuple data tuple -@param[in] rec B-tree record -@param[in] offsets rec_get_offsets(rec); may be NULL -for ROW_FORMAT=REDUNDANT -@return the comparison result of dtuple and rec -@retval 0 if dtuple is equal to rec -@retval negative if dtuple is less than rec -@retval positive if dtuple is greater than rec */ -int -cmp_dtuple_rec( - const dtuple_t* dtuple, - const rec_t* rec, - const rec_offs* offsets) -{ - ulint matched_fields = 0; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - return(cmp_dtuple_rec_with_match(dtuple, rec, offsets, - &matched_fields)); -} - -/**************************************************************//** -Checks if a dtuple is a prefix of a record. The last field in dtuple -is allowed to be a prefix of the corresponding field in the record. -@return TRUE if prefix */ -ibool -cmp_dtuple_is_prefix_of_rec( -/*========================*/ - const dtuple_t* dtuple, /*!< in: data tuple */ - const rec_t* rec, /*!< in: physical record */ - const rec_offs* offsets)/*!< in: array returned by rec_get_offsets() */ +/** Check if a dtuple is a prefix of a record. +@param dtuple data tuple +@param rec index record +@param index index +@param offsets rec_get_offsets(rec) +@return whether dtuple is a prefix of rec */ +bool cmp_dtuple_is_prefix_of_rec(const dtuple_t *dtuple, const rec_t *rec, + const dict_index_t *index, + const rec_offs *offsets) { - ulint n_fields; - ulint matched_fields = 0; - - ut_ad(rec_offs_validate(rec, NULL, offsets)); - n_fields = dtuple_get_n_fields(dtuple); - - if (n_fields > rec_offs_n_fields(offsets)) { - ut_ad(0); - return(FALSE); - } - - cmp_dtuple_rec_with_match(dtuple, rec, offsets, &matched_fields); - return(matched_fields == n_fields); + ulint matched_fields= 0; + ulint n_fields= dtuple_get_n_fields(dtuple); + ut_ad(n_fields <= rec_offs_n_fields(offsets)); + cmp_dtuple_rec_with_match(dtuple, rec, index, offsets, &matched_fields); + return matched_fields == n_fields; } /*************************************************************//** @@ -701,7 +663,7 @@ cmp_rec_rec_simple_field( const byte* rec2_b_ptr; ulint rec1_f_len; ulint rec2_f_len; - const dict_col_t* col = dict_index_get_nth_col(index, n); + const dict_field_t* field = dict_index_get_nth_field(index, n); ut_ad(!rec_offs_nth_extern(offsets1, n)); ut_ad(!rec_offs_nth_extern(offsets2, n)); @@ -709,8 +671,9 @@ cmp_rec_rec_simple_field( rec1_b_ptr = rec_get_nth_field(rec1, offsets1, n, &rec1_f_len); rec2_b_ptr = rec_get_nth_field(rec2, offsets2, n, &rec2_f_len); - return(cmp_data(col->mtype, col->prtype, - rec1_b_ptr, rec1_f_len, rec2_b_ptr, rec2_f_len)); + return cmp_data(field->col->mtype, field->col->prtype, + field->descending, + rec1_b_ptr, rec1_f_len, rec2_b_ptr, rec2_f_len); } /** Compare two physical records that contain the same number of columns, @@ -868,16 +831,19 @@ cmp_rec_rec( for (; cur_field < n_fields; cur_field++) { ulint mtype; ulint prtype; + bool descending; if (UNIV_UNLIKELY(dict_index_is_ibuf(index))) { /* This is for the insert buffer B-tree. */ mtype = DATA_BINARY; prtype = 0; + descending = false; } else { - const dict_col_t* col = dict_index_get_nth_col( + const dict_field_t* field = dict_index_get_nth_field( index, cur_field); - mtype = col->mtype; - prtype = col->prtype; + descending = field->descending; + mtype = field->col->mtype; + prtype = field->col->prtype; if (UNIV_LIKELY(!dict_index_is_spatial(index))) { } else if (cur_field == 0) { @@ -913,9 +879,8 @@ cmp_rec_rec( goto order_resolved; } - ret = cmp_data(mtype, prtype, - rec1_b_ptr, rec1_f_len, - rec2_b_ptr, rec2_f_len); + ret = cmp_data(mtype, prtype, descending, + rec1_b_ptr, rec1_f_len, rec2_b_ptr, rec2_f_len); if (ret) { goto order_resolved; } @@ -930,28 +895,3 @@ order_resolved: } return ret; } - -#ifdef UNIV_COMPILE_TEST_FUNCS - -#ifdef HAVE_UT_CHRONO_T - -void -test_cmp_data_data(ulint len) -{ - int i; - static byte zeros[64]; - - if (len > sizeof zeros) { - len = sizeof zeros; - } - - ut_chrono_t ch(__func__); - - for (i = 1000000; i > 0; i--) { - i += cmp_data(DATA_INT, 0, zeros, len, zeros, len); - } -} - -#endif /* HAVE_UT_CHRONO_T */ - -#endif /* UNIV_COMPILE_TEST_FUNCS */ |