Commit d32f6b13 authored by Georgi Kodinov's avatar Georgi Kodinov

Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may corrupt

   definition at engine

If a single ALTER TABLE contains both DROP INDEX and ADD INDEX using 
the same index name (a.k.a. index modification) we need to disable 
in-place alter table because we can't ask the storage engine to have 
two copies of the index with the same name even temporarily (if we 
first do the ADD INDEX and then DROP INDEX) and we can't modify 
indexes that are needed by e.g. foreign keys if we first do 
DROP INDEX and then ADD INDEX.
Fixed the problem by disabling in-place ALTER TABLE for these cases.
parent ea09256c
...@@ -2317,4 +2317,37 @@ ref NULL ...@@ -2317,4 +2317,37 @@ ref NULL
rows 10 rows 10
Extra Using index Extra Using index
DROP TABLE t1; DROP TABLE t1;
#
# Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may
# corrupt definition at engine
#
CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, KEY k (a,b))
ENGINE=InnoDB;
ALTER TABLE t1 DROP INDEX k, ADD UNIQUE INDEX k (a,b);
SHOW INDEXES FROM t1;;
Table t1
Non_unique 0
Key_name k
Seq_in_index 1
Column_name a
Collation A
Cardinality 0
Sub_part NULL
Packed NULL
Null
Index_type BTREE
Comment
Table t1
Non_unique 0
Key_name k
Seq_in_index 2
Column_name b
Collation A
Cardinality 0
Sub_part NULL
Packed NULL
Null
Index_type BTREE
Comment
DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
...@@ -575,5 +575,18 @@ INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3), ...@@ -575,5 +575,18 @@ INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,2,2,2,2,2), (3,3,3,3,3,3),
DROP TABLE t1; DROP TABLE t1;
--echo #
--echo # Bug #49838: DROP INDEX and ADD UNIQUE INDEX for same index may
--echo # corrupt definition at engine
--echo #
CREATE TABLE t1 (a INT NOT NULL, b INT NOT NULL, KEY k (a,b))
ENGINE=InnoDB;
ALTER TABLE t1 DROP INDEX k, ADD UNIQUE INDEX k (a,b);
--query_vertical SHOW INDEXES FROM t1;
DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
...@@ -5566,6 +5566,45 @@ mysql_discard_or_import_tablespace(THD *thd, ...@@ -5566,6 +5566,45 @@ mysql_discard_or_import_tablespace(THD *thd,
DBUG_RETURN(-1); DBUG_RETURN(-1);
} }
/**
@brief Check if both DROP and CREATE are present for an index in ALTER TABLE
@details Checks if any index is being modified (present as both DROP INDEX
and ADD INDEX) in the current ALTER TABLE statement. Needed for disabling
online ALTER TABLE.
@param table The table being altered
@param alter_info The ALTER TABLE structure
@return presence of index being altered
@retval FALSE No such index
@retval TRUE Have at least 1 index modified
*/
static bool
is_index_maintenance_unique (TABLE *table, Alter_info *alter_info)
{
List_iterator<Key> key_it(alter_info->key_list);
List_iterator<Alter_drop> drop_it(alter_info->drop_list);
Key *key;
while ((key= key_it++))
{
if (key->name)
{
Alter_drop *drop;
drop_it.rewind();
while ((drop= drop_it++))
{
if (drop->type == Alter_drop::KEY &&
!my_strcasecmp(system_charset_info, key->name, drop->name))
return TRUE;
}
}
}
return FALSE;
}
/* /*
SYNOPSIS SYNOPSIS
...@@ -5654,6 +5693,7 @@ compare_tables(TABLE *table, ...@@ -5654,6 +5693,7 @@ compare_tables(TABLE *table,
*/ */
Alter_info tmp_alter_info(*alter_info, thd->mem_root); Alter_info tmp_alter_info(*alter_info, thd->mem_root);
uint db_options= 0; /* not used */ uint db_options= 0; /* not used */
/* Create the prepared information. */ /* Create the prepared information. */
if (mysql_prepare_create_table(thd, create_info, if (mysql_prepare_create_table(thd, create_info,
&tmp_alter_info, &tmp_alter_info,
...@@ -6851,9 +6891,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, ...@@ -6851,9 +6891,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
*/ */
new_db_type= create_info->db_type; new_db_type= create_info->db_type;
if (is_index_maintenance_unique (table, alter_info))
need_copy_table= ALTER_TABLE_DATA_CHANGED;
if (mysql_prepare_alter_table(thd, table, create_info, alter_info)) if (mysql_prepare_alter_table(thd, table, create_info, alter_info))
goto err; goto err;
if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
need_copy_table= alter_info->change_level; need_copy_table= alter_info->change_level;
set_table_default_charset(thd, create_info, db); set_table_default_charset(thd, create_info, db);
......
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