MySQL Lists are EOL. Please join:

List:Commits« Previous MessageNext Message »
From:Georgi Kodinov Date:March 17 2010 2:20pm
Subject:bzr commit into mysql-5.1-bugteam branch (joro:3405) Bug#49838
View as plain text  
#At file:///Users/kgeorge/mysql/work/B49838-5.1-bugteam/ based on revid:davi.arnaut@stripped

 3405 Georgi Kodinov	2010-03-17
      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.

    modified:
      mysql-test/r/innodb_mysql.result
      mysql-test/t/innodb_mysql.test
      sql/sql_table.cc
=== modified file 'mysql-test/r/innodb_mysql.result'
--- a/mysql-test/r/innodb_mysql.result	2010-03-05 19:45:55 +0000
+++ b/mysql-test/r/innodb_mysql.result	2010-03-17 14:18:46 +0000
@@ -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

=== modified file 'mysql-test/t/innodb_mysql.test'
--- a/mysql-test/t/innodb_mysql.test	2010-03-05 19:45:55 +0000
+++ b/mysql-test/t/innodb_mysql.test	2010-03-17 14:18:46 +0000
@@ -575,5 +575,18 @@ INSERT INTO t1 VALUES (1,1,1,1,1,1), (2,
 
 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

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2010-02-28 17:29:19 +0000
+++ b/sql/sql_table.cc	2010-03-17 14:18:46 +0000
@@ -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> 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
@@ -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);
 


Attachment: [text/bzr-bundle] bzr/joro@sun.com-20100317141846-es0qyf5zcqb0hu1c.bundle
Thread
bzr commit into mysql-5.1-bugteam branch (joro:3405) Bug#49838Georgi Kodinov17 Mar