diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 586cd5477a7..0e691611f02 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -2317,4 +2317,37 @@ ref NULL rows 10 Extra Using index 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 diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 75fff9656e2..88ca8d42e3d 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -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; +--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 diff --git a/sql/sql_table.cc b/sql/sql_table.cc index eb88b1e70a5..ad72cab664e 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -5566,6 +5566,45 @@ err: 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_it(alter_info->key_list); + List_iterator 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 @@ -5654,6 +5693,7 @@ compare_tables(TABLE *table, */ Alter_info tmp_alter_info(*alter_info, thd->mem_root); uint db_options= 0; /* not used */ + /* Create the prepared information. */ if (mysql_prepare_create_table(thd, create_info, &tmp_alter_info, @@ -6851,10 +6891,14 @@ view_err: */ 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)) goto err; - need_copy_table= alter_info->change_level; + if (need_copy_table == ALTER_TABLE_METADATA_ONLY) + need_copy_table= alter_info->change_level; set_table_default_charset(thd, create_info, db);