diff options
author | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-01-30 15:32:51 +0530 |
---|---|---|
committer | Thirunarayanan Balathandayuthapani <thiru@mariadb.com> | 2019-01-30 15:33:32 +0530 |
commit | b8aef87221c46c82921377f18a6498a31f7e5367 (patch) | |
tree | a716ea5d4d13450d4a2edccc22069922bba63ffd /sql/sql_table.cc | |
parent | 97930df13c0e403940969ebb47398760b59f753c (diff) | |
download | mariadb-git-b8aef87221c46c82921377f18a6498a31f7e5367.tar.gz |
MDEV-16849 Extending indexed VARCHAR column should be instantaneous
Analysis:
========
Increasing the length of the indexed varchar column is not an instant operation for
innodb.
Fix:
===
- Introduce the new handler flag 'Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH' to
indicate the index length differs due to change of column length changes.
- InnoDB makes the ALTER_COLUMN_INDEX_LENGTH flag as instant operation.
This is a port of Mysql fix.
commit 913071c0b16cc03e703308250d795bc381627e37
Author: Nisha Gopalakrishnan <nisha.gopalakrishnan@oracle.com>
Date: Wed May 30 14:54:46 2018 +0530
BUG#26848813: INDEXED COLUMN CAN'T BE CHANGED FROM VARCHAR(15)
TO VARCHAR(40) INSTANTANEOUSLY
Diffstat (limited to 'sql/sql_table.cc')
-rw-r--r-- | sql/sql_table.cc | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 1b426f80a88..19100aafd51 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -6303,7 +6303,7 @@ static bool fill_alter_inplace_info(THD *thd, bool varchar, Alter_inplace_info *ha_alter_info) { - Field **f_ptr, *field; + Field **f_ptr, *field, *old_field; List_iterator_fast<Create_field> new_field_it; Create_field *new_field; KEY_PART_INFO *key_part, *new_part; @@ -6629,6 +6629,7 @@ static bool fill_alter_inplace_info(THD *thd, Go through keys and check if the original ones are compatible with new table. */ + uint old_field_len= 0; KEY *table_key; KEY *table_key_end= table->key_info + table->s->keys; KEY *new_key; @@ -6693,17 +6694,35 @@ static bool fill_alter_inplace_info(THD *thd, key_part < end; key_part++, new_part++) { + new_field= get_field_by_index(alter_info, new_part->fieldnr); + old_field= table->field[key_part->fieldnr - 1]; /* + If there is a change in index length due to column expansion + like varchar(X) changed to varchar(X + N) and has a compatible + packed data representation, we mark it for fast/INPLACE change + in index definition. InnoDB supports INPLACE for this cases + Key definition has changed if we are using a different field or - if the used key part length is different. It makes sense to - check lengths first as in case when fields differ it is likely - that lengths differ too and checking fields is more expensive - in general case. + if the user key part length is different. */ - if (key_part->length != new_part->length) - goto index_changed; + old_field_len= old_field->pack_length(); - new_field= get_field_by_index(alter_info, new_part->fieldnr); + if (old_field->type() == MYSQL_TYPE_VARCHAR) + { + old_field_len= (old_field->pack_length() + - ((Field_varstring*) old_field)->length_bytes); + } + + if (key_part->length == old_field_len && + key_part->length < new_part->length && + (key_part->field->is_equal((Create_field*) new_field) + == IS_EQUAL_PACK_LENGTH)) + { + ha_alter_info->handler_flags |= + Alter_inplace_info::ALTER_COLUMN_INDEX_LENGTH; + } + else if (key_part->length != new_part->length) + goto index_changed; /* For prefix keys KEY_PART_INFO::field points to cloned Field |