Atthepresent,thecomparisonfunctionsreturn0inthecase, wheretworecordsdisagreeonlyinthewaythatone
has more fields than the other. */
#ifndef DBUG_OFF /** @return whether a data type is compatible with strnncoll() functions */ staticbool is_strnncoll_compatible(ulint type)
{ switch (type) { case MYSQL_TYPE_BIT: case MYSQL_TYPE_STRING: case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_TINY_BLOB: case MYSQL_TYPE_MEDIUM_BLOB: case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: case MYSQL_TYPE_VARCHAR: returntrue; default: returnfalse;
}
} #endif/* DBUG_OFF */
/*************************************************************//**
Returns TRUEif two columns are equal for comparison purposes.
@returnTRUEif the columns are considered equal in comparisons */
ibool
cmp_cols_are_equal( /*===============*/ const dict_col_t* col1, /*!< in: column 1 */ const dict_col_t* col2, /*!< in: column 2 */
ibool check_charsets) /*!< in: whether to check charsets */
{ if (dtype_is_non_binary_string_type(col1->mtype, col1->prtype)
&& dtype_is_non_binary_string_type(col2->mtype, col2->prtype)) {
/* Both are non-binary string types: they can be compared if
and only if the charset-collation is the same */
if (a_length != b_length) { if (a_length < b_length) { return(-swap_flag);
}
return(swap_flag);
}
while (a_length > 0 && *a == *b) {
a++; b++; a_length--;
}
if (a_length == 0) { return(0);
}
if (*a <= *b) {
swap_flag = -swap_flag;
}
return(swap_flag);
}
/** Compare two data fields. @parammtypemaintype @paramprtypeprecisetype @paramdescendingwhethertousedescendingorder @paramdata1datafield @paramlen1lengthofdata1inbytes,orUNIV_SQL_NULL @paramdata2datafield @paramlen2lengthofdata2inbytes,orUNIV_SQL_NULL @returnthecomparisonresultofdata1anddata2 @retval0ifdata1isequaltodata2 @retvalnegativeifdata1islessthandata2
@retval positive if data1 is greater than data2 */ int cmp_data(ulint mtype, ulint prtype, bool descending, const byte *data1, size_t len1, const byte *data2, size_t len2)
noexcept
{
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) return0;
/* We define the SQL null to be the smallest possible value of a field. */
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:
cmp= cmp_decimal(data1, len1, data2, len2); goto func_exit; case DATA_DOUBLE:
{ constdouble af= mach_double_read(data1), bf= mach_double_read(data2);
cmp= af > bf ? 1 : bf > af ? -1 : 0;
} goto func_exit; case DATA_FLOAT:
{ constfloat af= mach_float_read(data1), bf= mach_float_read(data2);
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))
{
cmp= memcmp(data1, data2, len); if (cmp) goto func_exit;
data1+= len;
data2+= len;
len1-= len;
len2-= len;
} if (len1)
{ const byte *end= &data1[len1]; do
cmp= static_cast<int>(*data1++ - byte{0x20}); while (cmp == 0 && data1 < end);
} elseif (len2)
{ const byte *end= &data2[len2]; do
cmp= static_cast<int>(byte{0x20} - *data2++); while (cmp == 0 && data2 < end);
} goto func_exit;
} /* fall through */ case DATA_INT: case DATA_SYS_CHILD: case DATA_SYS: break; case DATA_GEOMETRY:
ut_ad(prtype & DATA_BINARY_TYPE); if (prtype & DATA_GIS_MBR)
{
ut_ad(len1 == DATA_MBR_LEN);
ut_ad(len2 == DATA_MBR_LEN);
cmp= cmp_geometry_field(data1, data2); goto func_exit;
} break; case DATA_BLOB: if (prtype & DATA_BINARY_TYPE) break; /* fall through */ case DATA_VARMYSQL:
DBUG_ASSERT(is_strnncoll_compatible(prtype & DATA_MYSQL_TYPE_MASK)); if (CHARSET_INFO *cs= all_charsets[dtype_get_charset_coll(prtype)])
{
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)])
{
cmp= cs->coll->
strnncollsp_nchars(cs, data1, len1, data2, len2, std::max(len1, len2),
MY_STRNNCOLLSP_NCHARS_EMULATE_TRIMMED_TRAILING_SPACES); goto func_exit;
} goto no_collation; case DATA_VARCHAR: case DATA_CHAR: /* latin1_swedish_ci is treated as a special case in InnoDB. Becauseitisafixed-lengthencoding(mbminlen=mbmaxlen=1), non-NULLCHAR(n)valueswillalwaysoccupynbytesandwe
can invoke strnncollsp() instead of strnncollsp_nchars(). */
cmp= my_charset_latin1.strnncollsp(data1, len1, data2, len2); goto func_exit;
}
if (ulint len= std::min(len1, len2))
{
cmp= memcmp(data1, data2, len); if (cmp) goto func_exit;
}
cmp= int(len1 - len2); goto func_exit;
}
/** Compare a data tuple to a physical record. @paramdtupledatatuple @paramrecB-treeindexrecord @paramindexB-treeindex @paramoffsetsrec_get_offsets(rec,index) @paramn_cmpnumberoffieldstocompare @parammatched_fieldsnumberofcompletelymatchedfields @returnthecomparisonresultofdtupleandrec @retval0ifdtupleisequaltorec @retvalnegativeifdtupleislessthanrec
@retval positive if dtuple is greater than rec */ 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, uint16_t *matched_fields)
{ int ret = 0; /* return value */
/* We should never compare against an externally storedfield.Onlyclusteredindexrecordscan containexternallystoredfields,andthefirstfields
(primary key fields) should already differ. */
ut_ad(!rec_offs_nth_extern(offsets, cur_field)); /* We should never compare against instantly added columns. Columnscanonlybeinstantlyaddedtoclusteredindex leafpagerecords,andthefirstfields(primarykeyfields)
should already differ. */
ut_ad(!rec_offs_nth_default(offsets, cur_field));
ret = cmp_data(type->mtype, type->prtype,
index->fields[cur_field].descending,
dtuple_b_ptr, dtuple_f_len,
rec_b_ptr, rec_f_len); if (ret) { break;
}
}
*matched_fields = cur_field; return ret;
}
/** Check if a dtuple is a prefix of a record. @paramdtupledatatuple @paramrecindexrecord @paramindexindex @paramoffsetsrec_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)
{
uint16_t matched_fields= 0, 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;
}
/*************************************************************//**
Compare two physical record fields.
@retval positive if rec1 field is greater than rec2
@retval negative if rec1 field is less than rec2
@retval 0if rec1 field equals to rec2 */ static MY_ATTRIBUTE((nonnull, warn_unused_result)) int
cmp_rec_rec_simple_field( /*=====================*/ const rec_t* rec1, /*!< in: physical record */ const rec_t* rec2, /*!< in: physical record */ const rec_offs* offsets1,/*!< in: rec_get_offsets(rec1, ...) */ const rec_offs* offsets2,/*!< in: rec_get_offsets(rec2, ...) */ const dict_index_t* index, /*!< in: data dictionary index */
ulint n) /*!< in: field to compare */
{ const byte* rec1_b_ptr; const byte* rec2_b_ptr;
ulint rec1_f_len;
ulint rec2_f_len; const dict_field_t* field = dict_index_get_nth_field(index, n);
/** Compare two physical records that contain the same number of columns, noneofwhicharestoredexternally. @retvalpositiveifrec1(includingnon-orderingcolumns)isgreaterthanrec2 @retvalnegativeifrec1(includingnon-orderingcolumns)islessthanrec2
@retval 0 if rec1 is a duplicate of rec2 */ int
cmp_rec_rec_simple( /*===============*/ const rec_t* rec1, /*!< in: physical record */ const rec_t* rec2, /*!< in: physical record */ const rec_offs* offsets1,/*!< in: rec_get_offsets(rec1, ...) */ const rec_offs* offsets2,/*!< in: rec_get_offsets(rec2, ...) */ const dict_index_t* index, /*!< in: data dictionary index */ struct TABLE* table) /*!< in: MySQL table, for reporting duplicatekeyvalueifapplicable,
or NULL */
{
ulint n;
ulint n_uniq = dict_index_get_n_unique(index); bool null_eq = false;
for (n = 0; n < n_uniq; n++) { int cmp = cmp_rec_rec_simple_field(
rec1, rec2, offsets1, offsets2, index, n);
if (cmp) { return(cmp);
}
/* If the fields are internally equal, they must both
be NULL or non-NULL. */
ut_ad(rec_offs_nth_sql_null(offsets1, n)
== rec_offs_nth_sql_null(offsets2, n));
/* If we ran out of fields, the ordering columns of rec1 were
equal to rec2. Issue a duplicate key error if needed. */
if (!null_eq && index->is_unique()) { if (table) { /* Report erroneous row using new version
of table. */
innobase_rec_to_mysql(table, rec1, index, offsets1);
} return(0);
}
/* Else, keep comparing so that we have the full internal
order. */ for (; n < dict_index_get_n_fields(index); n++) { int cmp = cmp_rec_rec_simple_field(
rec1, rec2, offsets1, offsets2, index, n);
if (cmp) { return(cmp);
}
/* If the fields are internally equal, they must both
be NULL or non-NULL. */
ut_ad(rec_offs_nth_sql_null(offsets1, n)
== rec_offs_nth_sql_null(offsets2, n));
}
/* This should never be reached. Internally, an index must
never contain duplicate entries. */
ut_ad(0); return(0);
}
/** Compare two B-tree or R-tree records. Onlythecommonfirstfieldsarecompared,andexternallystoredfield aretreatedasequal. @param[in]rec1record(possiblynotonanindexpage) @param[in]rec2B-treeorR-treerecordinanindexpage @param[in]offsets1rec_get_offsets(rec1,index) @param[in]offsets2rec_get_offsets(rec2,index) @param[in]nulls_unequaltrueifthisisforindexcardinality statisticsestimationwith innodb_stats_method=nulls_unequal orinnodb_stats_method=nulls_ignored @param[out]matched_fieldsnumberofcompletelymatchedfields withinthefirstfieldnotcompletelymatched @retval0ifrec1isequaltorec2 @retvalnegativeifrec1islessthanrec2
@retval positive if rec1 is greater than rec2 */ int
cmp_rec_rec( const rec_t* rec1, const rec_t* rec2, const rec_offs* offsets1, const rec_offs* offsets2, const dict_index_t* index, bool nulls_unequal,
ulint* matched_fields)
{
ulint rec1_f_len; /* length of current field in rec */ const byte* rec1_b_ptr; /* pointer to the current byte
in rec field */
ulint rec2_f_len; /* length of current field in rec */ const byte* rec2_b_ptr; /* pointer to the current byte
in rec field */
ulint cur_field = 0; /* current field number */ int ret = 0; /* return value */
/* Test if rec is the predefined minimum record */ if (UNIV_UNLIKELY(rec_get_info_bits(rec1, comp)
& REC_INFO_MIN_REC_FLAG)) {
ret = UNIV_UNLIKELY(rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG)
? 0 : -1; goto order_resolved;
} elseif (UNIV_UNLIKELY
(rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG)) {
ret = 1; goto order_resolved;
}
/* For non-leaf spatial index records, the dict_index_get_n_unique_in_tree()doesincludethechildpage number,becausespatialindexnodepointersonlycontain theMBR(minimumboundingrectangle)andthechildpagenumber.
ForB-treenodepointers,thekeyalone(secondaryindex columnsandPRIMARYKEYcolumns)mustbeunique,andthereis
no need to compare the child page number. */
n_fields = std::min(rec_offs_n_fields(offsets1),
rec_offs_n_fields(offsets2));
n_fields = std::min<ulint>(n_fields,
dict_index_get_n_unique_in_tree(index));
/* We should never encounter an externally stored field. Externallystoredfieldsonlyexistinclusteredindex leafpagerecords.Thesefieldsshouldalreadydiffer intheprimarykeycolumnsalready,beforeDB_TRX_ID,
DB_ROLL_PTR, and any externally stored columns. */
ut_ad(!rec_offs_nth_extern(offsets1, cur_field));
ut_ad(!rec_offs_nth_extern(offsets2, cur_field));
ut_ad(!rec_offs_nth_default(offsets1, cur_field));
ut_ad(!rec_offs_nth_default(offsets2, cur_field));
if (nulls_unequal
&& rec1_f_len == UNIV_SQL_NULL
&& rec2_f_len == UNIV_SQL_NULL) {
ret = -1; goto order_resolved;
}
ret = cmp_data(mtype, prtype, descending,
rec1_b_ptr, rec1_f_len, rec2_b_ptr, rec2_f_len); if (ret) { goto order_resolved;
}
}
/* If we ran out of fields, rec1 was equal to rec2 up
to the common fields */
ut_ad(ret == 0);
order_resolved: if (matched_fields) {
*matched_fields = cur_field;
} return ret;
}
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.20Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-10-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.