summaryrefslogtreecommitdiff
path: root/sql/sql_table.cc
diff options
context:
space:
mode:
authorThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-01-30 15:32:51 +0530
committerThirunarayanan Balathandayuthapani <thiru@mariadb.com>2019-01-30 15:33:32 +0530
commitb8aef87221c46c82921377f18a6498a31f7e5367 (patch)
treea716ea5d4d13450d4a2edccc22069922bba63ffd /sql/sql_table.cc
parent97930df13c0e403940969ebb47398760b59f753c (diff)
downloadmariadb-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.cc35
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