mirror of
https://github.com/MariaDB/server.git
synced 2025-01-19 13:32:33 +01:00
When buffering an insert to a prefix index of a variable-length column,
do not incorrectly mark the column as fixed-length. (Bug #28138) ibuf_entry_build(): Instead of prefix_len, pass fixed_len to dtype_new_store_for_order_and_null_size(). Add debug assertions. btr_index_rec_validate(): Correct a comment about prefix indexes. rec_get_converted_size_new(), rec_convert_dtuple_to_rec_new(): Add debug assertions and comments. dict_col_type_assert_equal(): New debug function.
This commit is contained in:
parent
3b74dd4a61
commit
3b705b44e4
5 changed files with 82 additions and 6 deletions
|
@ -2606,8 +2606,11 @@ btr_index_rec_validate(
|
|||
|
||||
rec_get_nth_field(rec, offsets, i, &len);
|
||||
|
||||
/* Note that prefix indexes are not fixed size even when
|
||||
their type is CHAR. */
|
||||
/* Note that if fixed_size != 0, it equals the
|
||||
length of a fixed-size column in the clustered index.
|
||||
A prefix index of the column is of fixed, but different
|
||||
length. When fixed_size == 0, prefix_len is the maximum
|
||||
length of the prefix index column. */
|
||||
|
||||
if ((dict_index_get_nth_field(index, i)->prefix_len == 0
|
||||
&& len != UNIV_SQL_NULL && fixed_size
|
||||
|
|
|
@ -1440,6 +1440,9 @@ ibuf_entry_build(
|
|||
*buf2++ = 0; /* write the compact format indicator */
|
||||
}
|
||||
for (i = 0; i < n_fields; i++) {
|
||||
ulint fixed_len;
|
||||
const dict_field_t* ifield;
|
||||
|
||||
/* We add 4 below because we have the 4 extra fields at the
|
||||
start of an ibuf record */
|
||||
|
||||
|
@ -1447,10 +1450,30 @@ ibuf_entry_build(
|
|||
entry_field = dtuple_get_nth_field(entry, i);
|
||||
dfield_copy(field, entry_field);
|
||||
|
||||
ifield = dict_index_get_nth_field(index, i);
|
||||
/* Prefix index columns of fixed-length columns are of
|
||||
fixed length. However, in the function call below,
|
||||
dfield_get_type(entry_field) contains the fixed length
|
||||
of the column in the clustered index. Replace it with
|
||||
the fixed length of the secondary index column. */
|
||||
fixed_len = ifield->fixed_len;
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
if (fixed_len) {
|
||||
/* dict_index_add_col() should guarantee these */
|
||||
ut_ad(fixed_len <= (ulint) entry_field->type.len);
|
||||
if (ifield->prefix_len) {
|
||||
ut_ad(ifield->prefix_len == fixed_len);
|
||||
} else {
|
||||
ut_ad(fixed_len
|
||||
== (ulint) entry_field->type.len);
|
||||
}
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
dtype_new_store_for_order_and_null_size(
|
||||
buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
|
||||
dfield_get_type(entry_field),
|
||||
dict_index_get_nth_field(index, i)->prefix_len);
|
||||
dfield_get_type(entry_field), fixed_len);
|
||||
}
|
||||
|
||||
/* Store the type info in buf2 to field 3 of tuple */
|
||||
|
|
|
@ -92,6 +92,17 @@ dict_col_copy_type_noninline(
|
|||
/*=========================*/
|
||||
const dict_col_t* col, /* in: column */
|
||||
dtype_t* type); /* out: data type */
|
||||
#ifdef UNIV_DEBUG
|
||||
/*************************************************************************
|
||||
Assert that a column and a data type match. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_col_type_assert_equal(
|
||||
/*=======================*/
|
||||
/* out: TRUE */
|
||||
const dict_col_t* col, /* in: column */
|
||||
const dtype_t* type); /* in: data type */
|
||||
#endif /* UNIV_DEBUG */
|
||||
/***************************************************************************
|
||||
Returns the minimum size of the column. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -30,6 +30,30 @@ dict_col_copy_type(
|
|||
type->mbmaxlen = col->mbmaxlen;
|
||||
}
|
||||
|
||||
#ifdef UNIV_DEBUG
|
||||
/*************************************************************************
|
||||
Assert that a column and a data type match. */
|
||||
UNIV_INLINE
|
||||
ibool
|
||||
dict_col_type_assert_equal(
|
||||
/*=======================*/
|
||||
/* out: TRUE */
|
||||
const dict_col_t* col, /* in: column */
|
||||
const dtype_t* type) /* in: data type */
|
||||
{
|
||||
ut_ad(col);
|
||||
ut_ad(type);
|
||||
|
||||
ut_ad(col->mtype == type->mtype);
|
||||
ut_ad(col->prtype == type->prtype);
|
||||
ut_ad(col->len == type->len);
|
||||
ut_ad(col->mbminlen == type->mbminlen);
|
||||
ut_ad(col->mbmaxlen == type->mbmaxlen);
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
#endif /* UNIV_DEBUG */
|
||||
|
||||
/***************************************************************************
|
||||
Returns the minimum size of the column. */
|
||||
UNIV_INLINE
|
||||
|
|
|
@ -460,7 +460,7 @@ rec_get_converted_size_new(
|
|||
case REC_STATUS_INFIMUM:
|
||||
case REC_STATUS_SUPREMUM:
|
||||
/* infimum or supremum record, 8 bytes */
|
||||
return(size + 8); /* no extra data needed */
|
||||
return(8); /* no extra data needed */
|
||||
default:
|
||||
ut_a(0);
|
||||
return(ULINT_UNDEFINED);
|
||||
|
@ -476,10 +476,13 @@ rec_get_converted_size_new(
|
|||
len = dtuple_get_nth_field(dtuple, i)->len;
|
||||
col = dict_field_get_col(field);
|
||||
|
||||
ut_ad(len != UNIV_SQL_NULL || !(col->prtype & DATA_NOT_NULL));
|
||||
ut_ad(dict_col_type_assert_equal(
|
||||
col, dfield_get_type(dtuple_get_nth_field(
|
||||
dtuple, i))));
|
||||
|
||||
if (len == UNIV_SQL_NULL) {
|
||||
/* No length is stored for NULL fields. */
|
||||
ut_ad(!(col->prtype & DATA_NOT_NULL));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -487,10 +490,17 @@ rec_get_converted_size_new(
|
|||
|
||||
if (field->fixed_len) {
|
||||
ut_ad(len == field->fixed_len);
|
||||
/* dict_index_add_col() should guarantee this */
|
||||
ut_ad(!field->prefix_len
|
||||
|| field->fixed_len == field->prefix_len);
|
||||
} else if (len < 128
|
||||
|| (col->len < 256 && col->mtype != DATA_BLOB)) {
|
||||
size++;
|
||||
} else {
|
||||
/* For variable-length columns, we look up the
|
||||
maximum length from the column itself. If this
|
||||
is a prefix index column shorter than 256 bytes,
|
||||
this will waste one byte. */
|
||||
size += 2;
|
||||
}
|
||||
size += len;
|
||||
|
@ -892,6 +902,11 @@ rec_convert_dtuple_to_rec_new(
|
|||
len = dfield_get_len(field);
|
||||
fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
|
||||
|
||||
ut_ad(dict_col_type_assert_equal(
|
||||
dict_field_get_col(dict_index_get_nth_field(
|
||||
index, i)),
|
||||
dfield_get_type(field)));
|
||||
|
||||
if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
|
||||
if (len == UNIV_SQL_NULL)
|
||||
continue;
|
||||
|
|
Loading…
Reference in a new issue