MDEV-7367: Updating a virtual column corrupts table which crashes server

Analysis: MySQL table definition contains also virtual columns. Similarly,
index fielnr references MySQL table fields. However, InnoDB table definition
does not contain virtual columns. Therefore, when matching MySQL key fieldnr
we need to use actual column name to find out referenced InnoDB dictionary
column name.

Fix: Add new function to match MySQL index key columns to InnoDB dictionary.
This commit is contained in:
Jan Lindström 2015-03-30 18:53:10 +03:00
commit b53bcd438f
14 changed files with 753 additions and 14 deletions

View file

@ -1441,8 +1441,9 @@ innobase_create_index_field_def(
if a new clustered index is
not being created */
const KEY_PART_INFO* key_part, /*!< in: MySQL key definition */
index_field_t* index_field) /*!< out: index field
index_field_t* index_field, /*!< out: index field
definition for key_part */
const Field** fields) /*!< in: MySQL table fields */
{
const Field* field;
ibool is_unsigned;
@ -1459,6 +1460,7 @@ innobase_create_index_field_def(
ut_a(field);
index_field->col_no = key_part->fieldnr;
index_field->col_name = altered_table ? field->field_name : fields[key_part->fieldnr]->field_name;
col_type = get_innobase_type_from_mysql_type(&is_unsigned, field);
@ -1493,8 +1495,9 @@ innobase_create_index_def(
bool key_clustered, /*!< in: true if this is
the new clustered index */
index_def_t* index, /*!< out: index definition */
mem_heap_t* heap) /*!< in: heap where memory
mem_heap_t* heap, /*!< in: heap where memory
is allocated */
const Field** fields) /*!z in: MySQL table fields */
{
const KEY* key = &keys[key_number];
ulint i;
@ -1507,6 +1510,7 @@ innobase_create_index_def(
index->fields = static_cast<index_field_t*>(
mem_heap_alloc(heap, n_fields * sizeof *index->fields));
memset(index->fields, 0, n_fields * sizeof *index->fields);
index->ind_type = 0;
index->key_number = key_number;
@ -1544,7 +1548,7 @@ innobase_create_index_def(
for (i = 0; i < n_fields; i++) {
innobase_create_index_field_def(
altered_table, &key->key_part[i], &index->fields[i]);
altered_table, &key->key_part[i], &index->fields[i], fields);
}
DBUG_VOID_RETURN;
@ -1875,7 +1879,7 @@ innobase_create_key_defs(
/* Create the PRIMARY key index definition */
innobase_create_index_def(
altered_table, key_info, primary_key_number,
TRUE, TRUE, indexdef++, heap);
TRUE, TRUE, indexdef++, heap, (const Field **)altered_table->field);
created_clustered:
n_add = 1;
@ -1887,7 +1891,7 @@ created_clustered:
/* Copy the index definitions. */
innobase_create_index_def(
altered_table, key_info, i, TRUE, FALSE,
indexdef, heap);
indexdef, heap, (const Field **)altered_table->field);
if (indexdef->ind_type & DICT_FTS) {
n_fts_add++;
@ -1932,7 +1936,7 @@ created_clustered:
for (ulint i = 0; i < n_add; i++) {
innobase_create_index_def(
altered_table, key_info, add[i], FALSE, FALSE,
indexdef, heap);
indexdef, heap, (const Field **)altered_table->field);
if (indexdef->ind_type & DICT_FTS) {
n_fts_add++;
@ -1949,6 +1953,7 @@ created_clustered:
index->fields = static_cast<index_field_t*>(
mem_heap_alloc(heap, sizeof *index->fields));
memset(index->fields, 0, sizeof *index->fields);
index->n_fields = 1;
index->fields->col_no = fts_doc_id_col;
index->fields->prefix_len = 0;