Commit 76f09b53 authored by Marko Mäkelä's avatar Marko Mäkelä

row_build_index_entry_low(): Handle dropped columns correctly

row_build_index_entry_low(): Clean up the code, removing
redundant variables and conditions. For instantly dropped columns,
generate a dummy value that is NULL, the empty string, or a
fixed length of NUL bytes, depending on the type of the dropped column.

FIXME: For some reason, during the test gcol.innodb_virtual_debug_purge
we are returning NULL for indexes on virtual columns, meaning that
purge on the indexes is being skipped. Does this lead to missed purge,
or is it merely causing unnecessary memory allocation? Why are we not
evaluating the virtual column values before calling this function?
(And why not write all index keys (virtual columns or spatial index MBR)
directly to the undo log records?)
parent 0ab49a10
......@@ -199,7 +199,7 @@ row_build_index_entry_low(
{
dtuple_t* entry;
ulint entry_len;
ulint i;
ulint i = 0;
ulint num_v = 0;
entry_len = dict_index_get_n_fields(index);
......@@ -219,105 +219,89 @@ row_build_index_entry_low(
} else {
dtuple_set_n_fields_cmp(
entry, dict_index_get_n_unique_in_tree(index));
if (dict_index_is_spatial(index)) {
/* Set the MBR field */
if (!row_build_spatial_index_key(
index, ext,
dtuple_get_nth_field(entry, 0),
dtuple_get_nth_field(
row,
dict_index_get_nth_field(index, i)
->col->ind), flag, heap)) {
return NULL;
}
for (i = 0; i < entry_len + num_v; i++) {
const dict_field_t* ind_field = NULL;
const dict_col_t* col;
ulint col_no = 0;
dfield_t* dfield;
dfield_t* dfield2;
ulint len;
if (i >= entry_len) {
/* This is to insert new rows to cluster index */
ut_ad(dict_index_is_clust(index)
&& flag == ROW_BUILD_FOR_INSERT);
dfield = dtuple_get_nth_v_field(entry, i - entry_len);
col = &dict_table_get_nth_v_col(
index->table, i - entry_len)->m_col;
} else {
ind_field = dict_index_get_nth_field(index, i);
col = ind_field->col;
dfield = dtuple_get_nth_field(entry, i);
i = 1;
}
}
if (col->is_dropped()) {
for (; i < entry_len; i++) {
const dict_field_t& f = index->fields[i];
dfield_t* dfield = dtuple_get_nth_field(entry, i);
if (f.col->is_dropped()) {
ut_ad(index->is_primary());
ut_ad(index->is_instant());
ut_ad(!col->is_virtual());
dict_col_copy_type(col, &dfield->type);
if (col->is_nullable()) {
ut_ad(!f.col->is_virtual());
dict_col_copy_type(f.col, &dfield->type);
if (f.col->is_nullable()) {
dfield_set_null(dfield);
} else {
dfield_set_data(dfield, field_ref_zero,
col->len);
f.fixed_len);
}
continue;
} else {
col_no = dict_col_get_no(col);
}
compile_time_assert(DATA_MISSING == 0);
const dfield_t* dfield2;
if (col->is_virtual()) {
if (f.col->is_virtual()) {
const dict_v_col_t* v_col
= reinterpret_cast<const dict_v_col_t*>(col);
= reinterpret_cast<const dict_v_col_t*>(f.col);
ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row));
dfield2 = dtuple_get_nth_v_field(row, v_col->v_pos);
ut_ad(dfield_is_null(dfield2) ||
dfield_get_len(dfield2) == 0 || dfield2->data);
} else {
dfield2 = dtuple_get_nth_field(row, col_no);
ut_ad(dfield_get_type(dfield2)->mtype == DATA_MISSING
|| (!(dfield_get_type(dfield2)->prtype
& DATA_VIRTUAL)));
}
if (UNIV_UNLIKELY(dfield_get_type(dfield2)->mtype
ut_ad(!dfield_is_ext(dfield2));
if (UNIV_UNLIKELY(dfield2->type.mtype
== DATA_MISSING)) {
/* The field has not been initialized in the row.
This should be from trx_undo_rec_get_partial_row(). */
/* FIXME: why does this happen?
Should the column not be evaluated? */
ut_ad(flag == ROW_BUILD_FOR_PURGE);
return(NULL);
}
#ifdef UNIV_DEBUG
if (dfield_get_type(dfield2)->prtype & DATA_VIRTUAL
&& dict_index_is_clust(index)) {
ut_ad(flag == ROW_BUILD_FOR_INSERT);
}
#endif /* UNIV_DEBUG */
/* Special handle spatial index, set the first field
which is for store MBR. */
if (dict_index_is_spatial(index) && i == 0) {
if (!row_build_spatial_index_key(
index, ext, dfield, dfield2, flag, heap)) {
return NULL;
} else {
dfield2 = dtuple_get_nth_field(row, f.col->ind);
if (UNIV_UNLIKELY(dfield2->type.mtype
== DATA_MISSING)) {
/* The field has not been initialized in
the row. This should be from
trx_undo_rec_get_partial_row(). */
return(NULL);
}
continue;
ut_ad(!(dfield2->type.prtype & DATA_VIRTUAL));
}
len = dfield_get_len(dfield2);
compile_time_assert(DATA_MISSING == 0);
dfield_copy(dfield, dfield2);
*dfield = *dfield2;
if (dfield_is_null(dfield)) {
continue;
}
if ((!ind_field || ind_field->prefix_len == 0)
ulint len = dfield_get_len(dfield);
if (f.prefix_len == 0
&& (!dfield_is_ext(dfield)
|| dict_index_is_clust(index))) {
/* The dfield_copy() above suffices for
columns that are stored in-page, or for
clustered index record columns that are not
part of a column prefix in the PRIMARY KEY,
or for virtaul columns in cluster index record. */
part of a column prefix in the PRIMARY KEY. */
continue;
}
......@@ -328,11 +312,11 @@ row_build_index_entry_low(
index record with an off-page column is when it is a
column prefix index. If atomic_blobs, also fully
indexed long columns may be stored off-page. */
ut_ad(col->ord_part);
ut_ad(f.col->ord_part);
if (ext) {
/* See if the column is stored externally. */
const byte* buf = row_ext_lookup(ext, col_no,
const byte* buf = row_ext_lookup(ext, f.col->ind,
&len);
if (UNIV_LIKELY_NULL(buf)) {
if (UNIV_UNLIKELY(buf == field_ref_zero)) {
......@@ -341,7 +325,7 @@ row_build_index_entry_low(
dfield_set_data(dfield, buf, len);
}
if (ind_field->prefix_len == 0) {
if (f.prefix_len == 0) {
/* If ROW_FORMAT=DYNAMIC or
ROW_FORMAT=COMPRESSED, we can have a
secondary index on an entire column
......@@ -368,16 +352,36 @@ row_build_index_entry_low(
}
/* If a column prefix index, take only the prefix. */
if (ind_field->prefix_len) {
if (f.prefix_len) {
len = dtype_get_at_most_n_mbchars(
col->prtype, col->mbminlen, col->mbmaxlen,
ind_field->prefix_len, len,
f.col->prtype,
f.col->mbminlen, f.col->mbmaxlen,
f.prefix_len, len,
static_cast<char*>(dfield_get_data(dfield)));
dfield_set_len(dfield, len);
}
}
return(entry);
for (i = num_v; i--; ) {
ut_ad(index->is_primary());
ut_ad(flag == ROW_BUILD_FOR_INSERT);
dfield_t* dfield = dtuple_get_nth_v_field(entry, i);
const dict_v_col_t* v_col = dict_table_get_nth_v_col(
index->table, i);
ut_ad(!v_col->m_col.is_dropped());
ut_ad(v_col->v_pos < dtuple_get_n_v_fields(row));
const dfield_t* dfield2 = dtuple_get_nth_v_field(
row, v_col->v_pos);
ut_ad(dfield_is_null(dfield2) ||
dfield_get_len(dfield2) == 0 || dfield2->data);
if (UNIV_UNLIKELY(dfield2->type.mtype == DATA_MISSING)) {
/* FIXME: why does this happen? */
return(NULL);
}
*dfield = *dfield2;
}
return entry;
}
/** An inverse function to row_build_index_entry. Builds a row from a
......
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