Commit ee599a74 authored by marko's avatar marko

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.
parent 6b308c0b
...@@ -2606,8 +2606,11 @@ btr_index_rec_validate( ...@@ -2606,8 +2606,11 @@ btr_index_rec_validate(
rec_get_nth_field(rec, offsets, i, &len); rec_get_nth_field(rec, offsets, i, &len);
/* Note that prefix indexes are not fixed size even when /* Note that if fixed_size != 0, it equals the
their type is CHAR. */ 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 if ((dict_index_get_nth_field(index, i)->prefix_len == 0
&& len != UNIV_SQL_NULL && fixed_size && len != UNIV_SQL_NULL && fixed_size
......
...@@ -1440,6 +1440,9 @@ ibuf_entry_build( ...@@ -1440,6 +1440,9 @@ ibuf_entry_build(
*buf2++ = 0; /* write the compact format indicator */ *buf2++ = 0; /* write the compact format indicator */
} }
for (i = 0; i < n_fields; i++) { 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 /* We add 4 below because we have the 4 extra fields at the
start of an ibuf record */ start of an ibuf record */
...@@ -1447,10 +1450,30 @@ ibuf_entry_build( ...@@ -1447,10 +1450,30 @@ ibuf_entry_build(
entry_field = dtuple_get_nth_field(entry, i); entry_field = dtuple_get_nth_field(entry, i);
dfield_copy(field, entry_field); 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( dtype_new_store_for_order_and_null_size(
buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE, buf2 + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE,
dfield_get_type(entry_field), dfield_get_type(entry_field), fixed_len);
dict_index_get_nth_field(index, i)->prefix_len);
} }
/* Store the type info in buf2 to field 3 of tuple */ /* Store the type info in buf2 to field 3 of tuple */
......
...@@ -92,6 +92,17 @@ dict_col_copy_type_noninline( ...@@ -92,6 +92,17 @@ dict_col_copy_type_noninline(
/*=========================*/ /*=========================*/
const dict_col_t* col, /* in: column */ const dict_col_t* col, /* in: column */
dtype_t* type); /* out: data type */ 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. */ Returns the minimum size of the column. */
UNIV_INLINE UNIV_INLINE
......
...@@ -30,6 +30,30 @@ dict_col_copy_type( ...@@ -30,6 +30,30 @@ dict_col_copy_type(
type->mbmaxlen = col->mbmaxlen; 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. */ Returns the minimum size of the column. */
UNIV_INLINE UNIV_INLINE
......
...@@ -460,7 +460,7 @@ rec_get_converted_size_new( ...@@ -460,7 +460,7 @@ rec_get_converted_size_new(
case REC_STATUS_INFIMUM: case REC_STATUS_INFIMUM:
case REC_STATUS_SUPREMUM: case REC_STATUS_SUPREMUM:
/* infimum or supremum record, 8 bytes */ /* infimum or supremum record, 8 bytes */
return(size + 8); /* no extra data needed */ return(8); /* no extra data needed */
default: default:
ut_a(0); ut_a(0);
return(ULINT_UNDEFINED); return(ULINT_UNDEFINED);
...@@ -476,10 +476,13 @@ rec_get_converted_size_new( ...@@ -476,10 +476,13 @@ rec_get_converted_size_new(
len = dtuple_get_nth_field(dtuple, i)->len; len = dtuple_get_nth_field(dtuple, i)->len;
col = dict_field_get_col(field); 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) { if (len == UNIV_SQL_NULL) {
/* No length is stored for NULL fields. */ /* No length is stored for NULL fields. */
ut_ad(!(col->prtype & DATA_NOT_NULL));
continue; continue;
} }
...@@ -487,10 +490,17 @@ rec_get_converted_size_new( ...@@ -487,10 +490,17 @@ rec_get_converted_size_new(
if (field->fixed_len) { if (field->fixed_len) {
ut_ad(len == 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 } else if (len < 128
|| (col->len < 256 && col->mtype != DATA_BLOB)) { || (col->len < 256 && col->mtype != DATA_BLOB)) {
size++; size++;
} else { } 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 += 2;
} }
size += len; size += len;
...@@ -892,6 +902,11 @@ rec_convert_dtuple_to_rec_new( ...@@ -892,6 +902,11 @@ rec_convert_dtuple_to_rec_new(
len = dfield_get_len(field); len = dfield_get_len(field);
fixed_len = dict_index_get_nth_field(index, i)->fixed_len; 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 (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
if (len == UNIV_SQL_NULL) if (len == UNIV_SQL_NULL)
continue; continue;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment