List:Commits« Previous MessageNext Message »
From:Dmitry Shulga Date:August 30 2011 4:29am
Subject:bzr push into mysql-trunk branch (Dmitry.Shulga:3418 to 3419) Bug#11748057
View as plain text  
 3419 Dmitry Shulga	2011-08-30
      Fixed bug#11748057 - ALTER TABLE statement doesn't identify correct
      column name.
      
      The problem was that execution of an ALTER TABLE statement that tried in the
      same statement to ADD a column into a table AFTER some specified column (e.g.
      c2) and MODIFY this column by moving it resulted in unwarranted failure
      with a message like ERROR 1054 (42S22): Unknown column 'c2' in 't1'.
      
      For example, if a user tries to execute the following statement:
      ALTER TABLE t1 ADD c3 INT AFTER c2,
      MODIFY c2 INT AFTER c1;
      then statement execution will fail with error message:
      ERROR 1054 (42S22): Unknown column 'c2' in 't1'.
      
      What happened was that during preparing of description for new
      version of the table being altered in mysql_prepare_alter_table() we
      improperly handled existing columns which changed their position.
      Such columns were initially omitted from the list of columns for
      new version of table and thus when ADD COLUMN ... AFTER ... clauses
      were processed they were not found in some cases. As a result user
      got "Unknown column" error.
      
      This fix solves the problem by ensuring that modified columns which
      change their position are not omitted but added to the list of
      columns for the new version of table prior to processing of ADD COLUMN
      clauses.
     @ mysql-test/r/alter_table.result
        Added testcase result for bug#11748057.
     @ mysql-test/t/alter_table.test
        Added testcase for bug#11748057.

    modified:
      mysql-test/r/alter_table.result
      mysql-test/t/alter_table.test
      sql/sql_table.cc
 3418 Vasil Dimov	2011-08-29
      Fix compilation warnings when compiling with UNIV_COMPILE_TEST_FUNCS.

    modified:
      storage/innobase/dict/dict0stats.c
      storage/innobase/row/row0row.c
=== modified file 'mysql-test/r/alter_table.result'
--- a/mysql-test/r/alter_table.result	2011-07-07 10:25:51 +0000
+++ b/mysql-test/r/alter_table.result	2011-08-30 04:28:18 +0000
@@ -1461,3 +1461,17 @@ ALTER TABLE t1 FORCE;
 affected rows: 2
 info: Records: 2  Duplicates: 0  Warnings: 0
 DROP TABLE t1;
+# Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't
+#                                         identify correct column name.
+#
+CREATE TABLE t1 (c1 int unsigned , c2 char(100) not null default '');
+ALTER TABLE t1 ADD c3 char(16) NOT NULL DEFAULT '' AFTER c2,
+MODIFY c2 char(100) NOT NULL DEFAULT '' AFTER c1;
+SHOW CREATE TABLE t1;
+Table	Create Table
+t1	CREATE TABLE `t1` (
+  `c1` int(10) unsigned DEFAULT NULL,
+  `c2` char(100) NOT NULL DEFAULT '',
+  `c3` char(16) NOT NULL DEFAULT ''
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE t1;

=== modified file 'mysql-test/t/alter_table.test'
--- a/mysql-test/t/alter_table.test	2011-07-07 10:25:51 +0000
+++ b/mysql-test/t/alter_table.test	2011-08-30 04:28:18 +0000
@@ -1244,3 +1244,14 @@ ALTER TABLE t1 FORCE;
 --disable_info
 
 DROP TABLE t1;
+
+--echo # Bug#11748057 (formerly known as 34972): ALTER TABLE statement doesn't
+--echo #                                         identify correct column name.
+--echo #
+
+CREATE TABLE t1 (c1 int unsigned , c2 char(100) not null default '');
+ALTER TABLE t1 ADD c3 char(16) NOT NULL DEFAULT '' AFTER c2,
+               MODIFY c2 char(100) NOT NULL DEFAULT '' AFTER c1;
+SHOW CREATE TABLE t1;
+DROP TABLE t1;
+

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	2011-08-29 06:53:25 +0000
+++ b/sql/sql_table.cc	2011-08-30 04:28:18 +0000
@@ -5614,10 +5614,22 @@ mysql_prepare_alter_table(THD *thd, TABL
     if (def)
     {						// Field is changed
       def->field=field;
+      /*
+        Add column being updated to the list of new columns.
+        Note that columns with AFTER clauses are added to the end
+        of the list for now. Their positions will be corrected later.
+      */
+      new_create_list.push_back(def);
       if (!def->after)
       {
-	new_create_list.push_back(def);
-	def_it.remove();
+        /*
+          If this ALTER TABLE doesn't have an AFTER clause for the modified
+          column then remove this column from the list of columns to be
+          processed. So later we can iterate over the columns remaining
+          in this list and process modified columns with AFTER clause or
+          add new columns.
+        */
+        def_it.remove();
       }
     }
     else
@@ -5677,25 +5689,43 @@ mysql_prepare_alter_table(THD *thd, TABL
     }
     if (!def->after)
       new_create_list.push_back(def);
-    else if (def->after == first_keyword)
-    {
-      new_create_list.push_front(def);
-    }
     else
     {
       Create_field *find;
-      find_it.rewind();
-      while ((find=find_it++))			// Add new columns
+      if (def->change)
       {
-	if (!my_strcasecmp(system_charset_info,def->after, find->field_name))
-	  break;
+        find_it.rewind();
+        /*
+          For columns being modified with AFTER clause we should first remove
+          these columns from the list and then add them back at their correct
+          positions.
+        */
+        while ((find=find_it++))
+        {
+          if (!my_strcasecmp(system_charset_info, def->field_name, find->field_name))
+          {
+            find_it.remove();
+            break;
+          }
+        }
       }
-      if (!find)
+      if (def->after == first_keyword)
+        new_create_list.push_front(def);
+      else
       {
-	my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
-        goto err;
+        find_it.rewind();
+        while ((find=find_it++))
+        {
+          if (!my_strcasecmp(system_charset_info, def->after, find->field_name))
+            break;
+        }
+        if (!find)
+        {
+          my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table->s->table_name.str);
+          goto err;
+        }
+        find_it.after(def);			// Put column after this
       }
-      find_it.after(def);			// Put element after this
     }
   }
   if (alter_info->alter_list.elements)

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-trunk branch (Dmitry.Shulga:3418 to 3419) Bug#11748057Dmitry Shulga30 Aug