List:Commits« Previous MessageNext Message »
From:Annamalai Gurusami Date:April 17 2012 11:24am
Subject:bzr push into mysql-5.5 branch (annamalai.gurusami:3788 to 3789) Bug#12902967
View as plain text  
 3789 Annamalai Gurusami	2012-04-17
      Bug #12902967 	CREATING SELF REFERENCING FK ON SAME INDEX 
      UNHANDLED, CONFUSING ERROR
      
      The main confusion with the error message is that "it 
      implies that your data dictionary may now be out of 
      sync".  This patch will remove the unwanted and the 
      misleading error message by not doing an unnecessary 
      operation in the error handling code.  
      
      rb://980 approved by: Dmitry Lenev

    added:
      mysql-test/suite/innodb/r/innodb_bug12902967.result
      mysql-test/suite/innodb/t/innodb_bug12902967.test
    modified:
      sql/sql_table.cc
 3788 Georgi Kodinov	2012-04-17 [merge]
      empty merge of a version bump in mysql-5.1

=== added file 'mysql-test/suite/innodb/r/innodb_bug12902967.result'
--- a/mysql-test/suite/innodb/r/innodb_bug12902967.result	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/r/innodb_bug12902967.result	revid:annamalai.gurusami@stripped
@@ -0,0 +1,6 @@
+create table t1 (f1 integer primary key) engine innodb;
+alter table t1 add constraint c1 foreign key (f1) references t1(f1);
+ERROR HY000: Error on rename of '#sql-temporary' to './test/t1' (errno: 150)
+InnoDB: which are not compatible with the new table definition.
+InnoDB: has or is referenced in foreign key constraints
+drop table t1;

=== added file 'mysql-test/suite/innodb/t/innodb_bug12902967.test'
--- a/mysql-test/suite/innodb/t/innodb_bug12902967.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/suite/innodb/t/innodb_bug12902967.test	revid:annamalai.gurusami@stripped
@@ -0,0 +1,42 @@
+# Bug 12902967: Creating self referencing fk on same index unhandled,
+# confusing error
+#
+# Creating a self referencing foreign key on the same
+# column/index is an unhandled exception, it should throw a sensible
+# error but instead implies that your data dictionary may now be out
+# of sync:
+
+--source include/have_innodb.inc
+
+let error_log= $MYSQLTEST_VARDIR/log/mysqld.1.err;
+--remove_file $error_log
+--source include/restart_mysqld.inc
+
+create table t1 (f1 integer primary key) engine innodb;
+
+# The below statement should produce error message in error log.
+# This error message should mention problem with foreign keys
+# rather than with data dictionary.
+--replace_regex /'\.\/test\/#sql-[0-9a-f_]*'/'#sql-temporary'/
+--error ER_ERROR_ON_RENAME
+alter table t1 add constraint c1 foreign key (f1) references t1(f1);
+
+perl;
+
+$file = "$ENV{'error_log'}";
+open ( FILE, $file) || die "can't open file! ($file)\n";
+@lines = <FILE>;
+close (FILE);
+$count = 0; 
+foreach $line (reverse @lines) {
+    if ($line =~ "^InnoDB:") { 
+       ++$count; 
+       print "$line"; 
+       if ($count == 2) {
+          break;
+       }
+    }
+}
+EOF
+
+drop table t1;

=== modified file 'sql/sql_table.cc'
--- a/sql/sql_table.cc	revid:georgi.kodinov@stripped
+++ b/sql/sql_table.cc	revid:annamalai.gurusami@stripped
@@ -246,10 +246,17 @@ uint explain_filename(THD* thd,
       {
         part_name_len= tmp_p - part_name - 1;
         subpart_name= tmp_p + 3;
+	tmp_p+= 3;
+      }
+      else if ((tmp_p[1] == 'Q' || tmp_p[1] == 'q') &&
+               (tmp_p[2] == 'L' || tmp_p[2] == 'l') &&
+                tmp_p[3] == '-')
+      {
+        name_type= TEMP;
+        tmp_p+= 4; /* sql- prefix found */
       }
       else
         res= 2;
-      tmp_p+= 3;
       break;
     case 'T':
     case 't':
@@ -6718,21 +6725,47 @@ bool mysql_alter_table(THD *thd,char *ne
     (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
   }
   else if (mysql_rename_table(new_db_type, new_db, tmp_name, new_db,
-                              new_alias, FN_FROM_IS_TMP) ||
-           ((new_name != table_name || new_db != db) && // we also do rename
-           (need_copy_table != ALTER_TABLE_METADATA_ONLY ||
-            mysql_rename_table(save_old_db_type, db, table_name, new_db,
-                               new_alias, NO_FRM_RENAME)) &&
-           Table_triggers_list::change_table_name(thd, db, alias, table_name,
-                                                  new_db, new_alias)))
+                              new_alias, FN_FROM_IS_TMP))
   {
     /* Try to get everything back. */
-    error=1;
-    (void) quick_rm_table(new_db_type,new_db,new_alias, 0);
+    error= 1;
     (void) quick_rm_table(new_db_type, new_db, tmp_name, FN_IS_TMP);
     (void) mysql_rename_table(old_db_type, db, old_name, db, alias,
                             FN_FROM_IS_TMP);
   }
+  else if (new_name != table_name || new_db != db)
+  {
+    if (need_copy_table == ALTER_TABLE_METADATA_ONLY &&
+        mysql_rename_table(save_old_db_type, db, table_name, new_db,
+                           new_alias, NO_FRM_RENAME))
+    {
+      /* Try to get everything back. */
+      error= 1;
+      (void) quick_rm_table(new_db_type, new_db, new_alias, 0);
+      (void) mysql_rename_table(old_db_type, db, old_name, db, alias,
+                                FN_FROM_IS_TMP);
+    }
+    else if (Table_triggers_list::change_table_name(thd, db, alias, 
+                                                    table_name, new_db, 
+                                                    new_alias))
+    {
+      /* Try to get everything back. */
+      error= 1;
+      (void) quick_rm_table(new_db_type, new_db, new_alias, 0);
+      (void) mysql_rename_table(old_db_type, db, old_name, db,
+                                alias, FN_FROM_IS_TMP);
+      /*
+        If we were performing "fast"/in-place ALTER TABLE we also need
+        to restore old name of table in storage engine as a separate
+        step, as the above rename affects .FRM only.
+      */
+      if (need_copy_table == ALTER_TABLE_METADATA_ONLY)
+      {
+        (void) mysql_rename_table(save_old_db_type, new_db, new_alias,
+                                  db, table_name, NO_FRM_RENAME); 
+      }
+    }
+  }
 
   if (! error)
     (void) quick_rm_table(old_db_type, db, old_name, FN_IS_TMP);

No bundle (reason: useless for push emails).
Thread
bzr push into mysql-5.5 branch (annamalai.gurusami:3788 to 3789) Bug#12902967Annamalai Gurusami20 Apr