List:Commits« Previous MessageNext Message »
From:Jon Olav Hauglid Date:February 28 2011 4:31pm
Subject:bzr commit into mysql-5.5 branch (jon.hauglid:3357) Bug#11755431
View as plain text  
#At file:///export/home/x/mysql-5.5-bug11755431/ based on revid:tor.didriksen@stripped

 3357 Jon Olav Hauglid	2011-02-28
      Bug #11755431 (former 47205)
      MAP 'REPAIR TABLE' TO RECREATE +ANALYZE FOR ENGINES NOT
      SUPPORTING NATIVE REPAIR
      
      This is a draft patch.
      
      Executing 'mysqlcheck --check --auto-repair ...' will first issue
      'CHECK TABLE FOR UPDATE' for all tables in the database in order to check if the
      tables are compatible with the current version of MySQL. Any tables that are
      found incompatible are then upgraded using 'REPAIR TABLE'.
      
      The problem was that some engines (e.g. InnoDB) does not support 'REPAIR TABLE'.
      This caused any such tables to be left incompatible. This could in turn cause
      problems for mysql_upgrade.
      
      This patch fixes the problem by first changing 'CHECK TABLE FOR UPDATE' to return
      a different error message if the engine does not support REPAIR. Instead of
      "Table upgrade required. Please do "REPAIR TABLE ..." it will report
      "Table rebuild required. Please do "ALTER TABLE ... FORCE ..."
      
      Second, the patch changes mysqlcheck to do 'ALTER TABLE ... FORCE' instead of
      'REPAIR TABLE' in these cases.
      
      Test case added to mysqlcheck.test
     @ client/mysqlcheck.c
        Changed mysqlcheck to do 'ALTER TABLE ... FORCE' if
        'CHECK TABLE FOR UPGRADE' reports ER_TABLE_NEEDS_REBUILD
        and not ER_TABLE_NEEDS_UPGRADE.
     @ mysql-test/r/mysqlcheck.result
        Added regression test.
     @ mysql-test/std_data/bug47205.frm
        InnoDB 5.0 FRM which contains a varchar primary key using
        utf8_general_ci. This is an incompatible FRM for 5.5.
     @ mysql-test/t/mysqlcheck.test
        Added regression test.
     @ sql/handler.h
        Added new HA_SUPPORTS_REPAIR flag.
     @ sql/share/errmsg-utf8.txt
        Added new error message ER_TABLE_NEEDS_REBUILD
     @ sql/sql_admin.cc
        Changed 'CHECK TABLE FOR UPDATE' to give ER_TABLE_NEEDS_REBUILD
        instead of ER_TABLE_NEEDS_UPGRADE if the engine does not support
        REPAIR (as indicated by the new HA_SUPPORTS_REPAIR flag).
     @ storage/archive/ha_archive.h
        Added new HA_SUPPORTS_REPAIR flag to Archive
     @ storage/csv/ha_tina.h
        Added new HA_SUPPORTS_REPAIR flag to CSV
     @ storage/federated/ha_federated.h
        Added new HA_SUPPORTS_REPAIR flag to Federated
     @ storage/myisam/ha_myisam.cc
        Added new HA_SUPPORTS_REPAIR flag to MyISAM

    added:
      mysql-test/std_data/bug47205.frm
    modified:
      client/mysqlcheck.c
      mysql-test/r/mysqlcheck.result
      mysql-test/t/mysqlcheck.test
      sql/handler.h
      sql/share/errmsg-utf8.txt
      sql/sql_admin.cc
      storage/archive/ha_archive.h
      storage/csv/ha_tina.h
      storage/federated/ha_federated.h
      storage/myisam/ha_myisam.cc
=== modified file 'client/mysqlcheck.c'
--- a/client/mysqlcheck.c	2011-01-16 03:59:05 +0000
+++ b/client/mysqlcheck.c	2011-02-28 16:31:23 +0000
@@ -42,13 +42,13 @@ static char *opt_password = 0, *current_
 	    *default_charset= 0, *current_host= 0;
 static char *opt_plugin_dir= 0, *opt_default_auth= 0;
 static int first_error = 0;
-DYNAMIC_ARRAY tables4repair;
+DYNAMIC_ARRAY tables4repair, tables4rebuild;
 #ifdef HAVE_SMEM
 static char *shared_memory_base_name=0;
 #endif
 static uint opt_protocol=0;
 
-enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE };
+enum operations { DO_CHECK=1, DO_REPAIR, DO_ANALYZE, DO_OPTIMIZE, DO_UPGRADE, DO_REBUILD };
 
 static struct my_option my_long_options[] =
 {
@@ -626,6 +626,25 @@ static int fix_database_storage_name(con
   return rc;
 }
 
+static int rebuild_table(const char *full_name)
+{
+  char qbuf[100 + NAME_LEN*4];
+  int rc= 0;
+  const char *name= strchr(full_name, '.');
+  if (name == NULL)
+    return 1;
+  sprintf(qbuf, "ALTER TABLE `%s` FORCE", name + 1);
+  if (mysql_query(sock, qbuf))
+  {
+    fprintf(stderr, "Failed to %s\n", qbuf);
+    fprintf(stderr, "Error: %s\n", mysql_error(sock));
+    rc= 1;
+  }
+  if (verbose)
+    printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
+  return rc;
+}
+
 static int process_one_db(char *database)
 {
   if (what_to_do == DO_UPGRADE)
@@ -695,6 +714,8 @@ static int handle_request_for_tables(cha
     if (opt_extended)           end = strmov(end, " EXTENDED");
     if (opt_frm)                end = strmov(end, " USE_FRM");
     break;
+  case DO_REBUILD:
+    return rebuild_table(tables);
   case DO_ANALYZE:
     op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
     break;
@@ -739,7 +760,7 @@ static void print_result()
   MYSQL_ROW row;
   char prev[NAME_LEN*2+2];
   uint i;
-  my_bool found_error=0;
+  my_bool found_error=0, table_rebuild=0;
 
   res = mysql_use_result(sock);
 
@@ -758,8 +779,14 @@ static void print_result()
       */
       if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
 	  strcmp(row[3],"OK"))
-	insert_dynamic(&tables4repair, (uchar*) prev);
+      {
+        if (table_rebuild)
+          insert_dynamic(&tables4rebuild, (uchar*) prev);
+        else
+          insert_dynamic(&tables4repair, (uchar*) prev);
+      }
       found_error=0;
+      table_rebuild=0;
       if (opt_silent)
 	continue;
     }
@@ -770,6 +797,8 @@ static void print_result()
       printf("%s\n%-9s: %s", row[0], row[2], row[3]);
       if (strcmp(row[2],"note"))
 	found_error=1;
+      if (opt_auto_repair && strncmp(row[3], "Table rebuild", 13) == 0)
+        table_rebuild=1;
     }
     else
       printf("%-9s: %s", row[2], row[3]);
@@ -778,7 +807,12 @@ static void print_result()
   }
   /* add the last table to be repaired to the list */
   if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
-    insert_dynamic(&tables4repair, (uchar*) prev);
+  {
+    if (table_rebuild)
+      insert_dynamic(&tables4rebuild, (uchar*) prev);
+    else
+      insert_dynamic(&tables4repair, (uchar*) prev);
+  }
   mysql_free_result(res);
 }
 
@@ -876,7 +910,8 @@ int main(int argc, char **argv)
   }
 
   if (opt_auto_repair &&
-      my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64))
+      (my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,64) ||
+       my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,64)))
   {
     first_error = 1;
     goto end;
@@ -894,7 +929,7 @@ int main(int argc, char **argv)
   {
     uint i;
 
-    if (!opt_silent && tables4repair.elements)
+    if (!opt_silent && (tables4repair.elements || tables4rebuild.elements))
       puts("\nRepairing tables");
     what_to_do = DO_REPAIR;
     for (i = 0; i < tables4repair.elements ; i++)
@@ -902,11 +937,20 @@ int main(int argc, char **argv)
       char *name= (char*) dynamic_array_ptr(&tables4repair, i);
       handle_request_for_tables(name, fixed_name_length(name));
     }
+    what_to_do = DO_REBUILD;
+    for (i = 0; i < tables4rebuild.elements ; i++)
+    {
+      char *name= (char*) dynamic_array_ptr(&tables4rebuild, i);
+      handle_request_for_tables(name, fixed_name_length(name));
+    }
   }
  end:
   dbDisconnect(current_host);
   if (opt_auto_repair)
+  {
     delete_dynamic(&tables4repair);
+    delete_dynamic(&tables4rebuild);
+  }
   my_free(opt_password);
 #ifdef HAVE_SMEM
   my_free(shared_memory_base_name);

=== modified file 'mysql-test/r/mysqlcheck.result'
--- a/mysql-test/r/mysqlcheck.result	2010-12-17 11:11:34 +0000
+++ b/mysql-test/r/mysqlcheck.result	2011-02-28 16:31:23 +0000
@@ -260,3 +260,41 @@ End of 5.1 tests
 #
 # Bug #35269: mysqlcheck behaves different depending on order of parameters
 #
+#
+# Bug#11755431 47205: MAP 'REPAIR TABLE' TO RECREATE +ANALYZE FOR
+#              ENGINES NOT SUPPORTING NATIVE
+#
+DROP TABLE IF EXISTS bug47205;
+#
+# Test 1: InnoDB - REPAIR not supported
+CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY)
+DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb;
+# Should indicate that ALTER TABLE .. FORCE is needed
+CHECK TABLE bug47205 FOR UPGRADE;
+Table	Op	Msg_type	Msg_text
+test.bug47205	check	error	Table rebuild required. Please do "ALTER TABLE `bug47205` FORCE" or dump/reload to fix it!
+test.bug47205
+error    : Table rebuild required. Please do "ALTER TABLE `bug47205` FORCE" or dump/reload to fix it!
+
+Repairing tables
+# Table should now be ok
+CHECK TABLE bug47205 FOR UPGRADE;
+Table	Op	Msg_type	Msg_text
+test.bug47205	check	status	OK
+DROP TABLE bug47205;
+#
+# Test 2: MyISAM - REPAIR supported
+# Should indicate that REPAIR TABLE is needed
+CHECK TABLE bug47205 FOR UPGRADE;
+Table	Op	Msg_type	Msg_text
+test.bug47205	check	error	Table upgrade required. Please do "REPAIR TABLE `bug47205`" or dump/reload to fix it!
+test.bug47205
+error    : Table upgrade required. Please do "REPAIR TABLE `bug47205`" or dump/reload to fix it!
+
+Repairing tables
+test.bug47205                                      OK
+# Table should now be ok
+CHECK TABLE bug47205 FOR UPGRADE;
+Table	Op	Msg_type	Msg_text
+test.bug47205	check	status	OK
+DROP TABLE bug47205;

=== added file 'mysql-test/std_data/bug47205.frm'
Binary files a/mysql-test/std_data/bug47205.frm	1970-01-01 00:00:00 +0000 and b/mysql-test/std_data/bug47205.frm	2011-02-28 16:31:23 +0000 differ

=== modified file 'mysql-test/t/mysqlcheck.test'
--- a/mysql-test/t/mysqlcheck.test	2010-10-08 07:09:47 +0000
+++ b/mysql-test/t/mysqlcheck.test	2011-02-28 16:31:23 +0000
@@ -229,3 +229,49 @@ drop table `t1-1`;
 --error 1
 --exec $MYSQL_CHECK -aoc test "#mysql50#t1-1"
 
+
+--echo #
+--echo # Bug#11755431 47205: MAP 'REPAIR TABLE' TO RECREATE +ANALYZE FOR
+--echo #              ENGINES NOT SUPPORTING NATIVE
+--echo #
+
+--disable_warnings
+DROP TABLE IF EXISTS bug47205;
+--enable_warnings
+
+--echo #
+--echo # Test 1: InnoDB - REPAIR not supported
+
+CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY)
+  DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+--remove_file $MYSQLD_DATADIR/test/bug47205.frm
+--copy_file std_data/bug47205.frm $MYSQLD_DATADIR/test/bug47205.frm
+
+--echo # Should indicate that ALTER TABLE .. FORCE is needed
+CHECK TABLE bug47205 FOR UPGRADE;
+
+--exec $MYSQL_CHECK --check --auto-repair test
+
+--echo # Table should now be ok
+CHECK TABLE bug47205 FOR UPGRADE;
+
+DROP TABLE bug47205;
+
+--echo #
+--echo # Test 2: MyISAM - REPAIR supported
+
+--copy_file std_data/bug36055.frm $MYSQLD_DATADIR/test/bug47205.frm
+--copy_file std_data/bug36055.MYD $MYSQLD_DATADIR/test/bug47205.MYD
+--copy_file std_data/bug36055.MYI $MYSQLD_DATADIR/test/bug47205.MYI
+
+--echo # Should indicate that REPAIR TABLE is needed
+CHECK TABLE bug47205 FOR UPGRADE;
+
+--exec $MYSQL_CHECK --check --auto-repair test
+
+--echo # Table should now be ok
+CHECK TABLE bug47205 FOR UPGRADE;
+
+DROP TABLE bug47205;

=== modified file 'sql/handler.h'
--- a/sql/handler.h	2011-01-26 13:23:29 +0000
+++ b/sql/handler.h	2011-02-28 16:31:23 +0000
@@ -153,6 +153,7 @@
     ordered.
 */
 #define HA_DUPLICATE_KEY_NOT_IN_ORDER    (LL(1) << 36)
+#define HA_SUPPORTS_REPAIR               (LL(1) << 37)
 
 /*
   Set of all binlog flags. Currently only contain the capabilities
@@ -2010,7 +2011,10 @@ private:
      upon the table.
   */
   virtual int repair(THD* thd, HA_CHECK_OPT* check_opt)
-  { return HA_ADMIN_NOT_IMPLEMENTED; }
+  {
+    DBUG_ASSERT(!(ha_table_flags() & HA_SUPPORTS_REPAIR));
+    return HA_ADMIN_NOT_IMPLEMENTED;
+  }
   virtual void start_bulk_insert(ha_rows rows) {}
   virtual int end_bulk_insert() { return 0; }
   virtual int index_read(uchar * buf, const uchar * key, uint key_len,

=== modified file 'sql/share/errmsg-utf8.txt'
--- a/sql/share/errmsg-utf8.txt	2011-02-21 15:49:03 +0000
+++ b/sql/share/errmsg-utf8.txt	2011-02-28 16:31:23 +0000
@@ -6397,3 +6397,6 @@ ER_STMT_CACHE_FULL
 
 ER_MULTI_UPDATE_KEY_CONFLICT
   eng "Primary key/partition key update is not allowed since the table is updated both as '%-.192s' and '%-.192s'."
+
+ER_TABLE_NEEDS_REBUILD
+        eng "Table rebuild required. Please do \"ALTER TABLE `%-.32s` FORCE\" or dump/reload to fix it!"

=== modified file 'sql/sql_admin.cc'
--- a/sql/sql_admin.cc	2011-01-10 13:12:23 +0000
+++ b/sql/sql_admin.cc	2011-02-28 16:31:23 +0000
@@ -771,8 +771,12 @@ send_result_message:
       size_t length;
 
       protocol->store(STRING_WITH_LEN("error"), system_charset_info);
-      length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE),
-                         table->table_name);
+      if (table->table->file->ha_table_flags() & HA_SUPPORTS_REPAIR)
+        length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE),
+                           table->table_name);
+      else
+        length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_REBUILD),
+                           table->table_name);
       protocol->store(buf, length, system_charset_info);
       fatal_error=1;
       break;

=== modified file 'storage/archive/ha_archive.h'
--- a/storage/archive/ha_archive.h	2010-10-06 14:34:28 +0000
+++ b/storage/archive/ha_archive.h	2011-02-28 16:31:23 +0000
@@ -90,7 +90,7 @@ public:
     return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
             HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
             HA_STATS_RECORDS_IS_EXACT |
-            HA_HAS_RECORDS |
+            HA_HAS_RECORDS | HA_SUPPORTS_REPAIR |
             HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
   }
   ulong index_flags(uint idx, uint part, bool all_parts) const

=== modified file 'storage/csv/ha_tina.h'
--- a/storage/csv/ha_tina.h	2010-07-08 21:20:08 +0000
+++ b/storage/csv/ha_tina.h	2011-02-28 16:31:23 +0000
@@ -106,7 +106,8 @@ public:
   ulonglong table_flags() const
   {
     return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT |
-            HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE);
+            HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
+            HA_SUPPORTS_REPAIR);
   }
   ulong index_flags(uint idx, uint part, bool all_parts) const
   {

=== modified file 'storage/federated/ha_federated.h'
--- a/storage/federated/ha_federated.h	2010-10-06 14:34:28 +0000
+++ b/storage/federated/ha_federated.h	2011-02-28 16:31:23 +0000
@@ -149,7 +149,8 @@ public:
             HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
             HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
             HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ |
-            HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY);
+            HA_PARTIAL_COLUMN_READ | HA_NULL_IN_KEY |
+            HA_SUPPORTS_REPAIR);
   }
   /*
     This is a bitmap of flags that says how the storage engine

=== modified file 'storage/myisam/ha_myisam.cc'
--- a/storage/myisam/ha_myisam.cc	2011-01-11 09:07:37 +0000
+++ b/storage/myisam/ha_myisam.cc	2011-02-28 16:31:23 +0000
@@ -639,7 +639,7 @@ ha_myisam::ha_myisam(handlerton *hton, T
                   HA_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
                   HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
                   HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS |
-                  HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT),
+                  HA_HAS_RECORDS | HA_STATS_RECORDS_IS_EXACT | HA_SUPPORTS_REPAIR),
    can_enable_indexes(1)
 {}
 


Attachment: [text/bzr-bundle] bzr/jon.hauglid@oracle.com-20110228163123-oh6y1jbe52aoocrc.bundle
Thread
bzr commit into mysql-5.5 branch (jon.hauglid:3357) Bug#11755431Jon Olav Hauglid28 Feb