List:Commits« Previous MessageNext Message »
From:Dmitry Lenev Date:April 13 2011 6:17am
Subject:bzr push into mysql-5.5 branch (Dmitry.Lenev:3438 to 3439) Bug#11938039
View as plain text  
 3439 Dmitry Lenev	2011-04-13
      Bug#11938039 "RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME 
      CLAUSE FAILS OR ABORTS SERVER".
       
      Attempt to re-execute prepared ALTER TABLE statement which 
      involves .FRM-only changes and also have RENAME clause led
      to unwarranted 'Table doesn't exist' error in production
      builds and assertion failure for debug builds.
       
      This problem stemmed from the fact that for such ALTER TABLE
      mysql_alter_table() code changed table list element for table 
      to be altered when it tried to re-open table under new name. 
      Since this change was not reverted back before next 
      re-execution, it made this statement re-execution unsafe.
       
      This fix addresses this problem by avoiding changing table list
      element from the main table list in such a situation. Instead 
      temporary TABLE_LIST object is used.
     @ mysql-test/r/alter_table.result
        Added test case for bug#11938039 "RE-EXECUTION OF FRM-ONLY
        ALTER TABLE WITH RENAME CLAUSE FAILS OR ABORTS SERVER".
     @ mysql-test/t/alter_table.test
        Added test case for bug#11938039 "RE-EXECUTION OF FRM-ONLY
        ALTER TABLE WITH RENAME CLAUSE FAILS OR ABORTS SERVER".
     @ sql/sql_table.cc
        Changed mysql_alter_table() not to modify table list element
        for the table being altered while re-opening table after
        .FRM-only changes. Doing this made .FRM-only ALTER TABLE 
        which also had RENAME clause unsafe for re-execution.

    modified:
      mysql-test/r/alter_table.result
      mysql-test/t/alter_table.test
      sql/sql_table.cc
 3438 Sven Sandberg	2011-04-12 [merge]
      null merge

=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2011-02-21 11:30:08 +0000
+++ b/mysql-test/r/alter_table.result	2011-04-13 06:16:40 +0000
@@ -1391,3 +1391,16 @@ CREATE DATABASE db1 CHARACTER SET utf8;
 CREATE TABLE db1.t1 (bar TINYTEXT, KEY (bar(100)));
 ALTER TABLE db1.t1 ADD baz INT;
 DROP DATABASE db1;
+#
+# Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
+#              CLAUSE FAILS OR ABORTS SERVER.
+#
+drop table if exists t1;
+create table t1 (a int);
+prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
+execute stmt1;
+rename table t2 to t1;
+# The below statement should succeed and not emit error or abort server.
+execute stmt1;
+deallocate prepare stmt1;
+drop table t2;

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2011-02-21 11:30:08 +0000
+++ b/mysql-test/t/alter_table.test	2011-04-13 06:16:40 +0000
@@ -1159,3 +1159,20 @@ CREATE TABLE db1.t1 (bar TINYTEXT, KEY (
 ALTER TABLE db1.t1 ADD baz INT;
 
 DROP DATABASE db1;
+
+
+--echo #
+--echo # Bug#11938039 RE-EXECUTION OF FRM-ONLY ALTER TABLE WITH RENAME
+--echo #              CLAUSE FAILS OR ABORTS SERVER.
+--echo #
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (a int);
+prepare stmt1 from 'alter table t1 alter column a set default 1, rename to t2';
+execute stmt1;
+rename table t2 to t1;
+--echo # The below statement should succeed and not emit error or abort server.
+execute stmt1;
+deallocate prepare stmt1;
+drop table t2;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-03-25 14:03:44 +0000
+++ b/sql/sql_table.cc	2011-04-13 06:16:40 +0000
@@ -6660,15 +6660,15 @@ bool mysql_alter_table(THD *thd,char *ne
       NO need to tamper with MERGE tables. The real open is done later.
     */
     Open_table_context ot_ctx(thd, MYSQL_OPEN_REOPEN);
-    TABLE *t_table;
+    TABLE_LIST temp_table_list;
+    TABLE_LIST *t_table_list;
     if (new_name != table_name || new_db != db)
     {
-      table_list->alias= new_name;
-      table_list->table_name= new_name;
-      table_list->table_name_length= strlen(new_name);
-      table_list->db= new_db;
-      table_list->db_length= strlen(new_db);
-      table_list->mdl_request.ticket= target_mdl_request.ticket;
+      temp_table_list.init_one_table(new_db, strlen(new_db),
+                                     new_name, strlen(new_name),
+                                     new_name, TL_READ_NO_INSERT);
+      temp_table_list.mdl_request.ticket= target_mdl_request.ticket;
+      t_table_list= &temp_table_list;
     }
     else
     {
@@ -6678,20 +6678,21 @@ bool mysql_alter_table(THD *thd,char *ne
         to request the lock.
       */
       table_list->mdl_request.ticket= mdl_ticket;
+      t_table_list= table_list;
     }
-    if (open_table(thd, table_list, thd->mem_root, &ot_ctx))
+    if (open_table(thd, t_table_list, thd->mem_root, &ot_ctx))
     {
       goto err_with_mdl;
     }
-    t_table= table_list->table;
 
     /* Tell the handler that a new frm file is in place. */
-    error= t_table->file->ha_create_handler_files(path, NULL, CHF_INDEX_FLAG,
-                                               create_info);
+    error= t_table_list->table->file->ha_create_handler_files(path, NULL,
+                                                              CHF_INDEX_FLAG,
+                                                              create_info);
 
-    DBUG_ASSERT(thd->open_tables == t_table);
+    DBUG_ASSERT(thd->open_tables == t_table_list->table);
     close_thread_table(thd, &thd->open_tables);
-    table_list->table= 0;
+    t_table_list->table= NULL;
 
     if (error)
       goto err_with_mdl;

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5 branch (Dmitry.Lenev:3438 to 3439) Bug#11938039Dmitry Lenev13 Apr