diff options
author | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2011-03-08 09:41:57 +0100 |
---|---|---|
committer | Jon Olav Hauglid <jon.hauglid@oracle.com> | 2011-03-08 09:41:57 +0100 |
commit | 0db0e64f33bda17852d9de57aa5a1d376af95db2 (patch) | |
tree | fb3ca01906c1101545f56910a7c3783185e1958e | |
parent | 5e32755e4cd7d1f8b6c3fd667540f34dacc4c3d2 (diff) | |
download | mariadb-git-0db0e64f33bda17852d9de57aa5a1d376af95db2.tar.gz |
Bug #11755431 (former 47205)
MAP 'REPAIR TABLE' TO RECREATE +ANALYZE FOR ENGINES NOT
SUPPORTING NATIVE REPAIR
Executing 'mysqlcheck --check-upgrade --auto-repair ...' will first issue
'CHECK TABLE FOR UPGRADE' 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) do not support 'REPAIR TABLE'.
This caused any such tables to be left incompatible. As a result such tables were
not properly fixed by the mysql_upgrade tool.
This patch fixes the problem by first changing 'CHECK TABLE FOR UPGRADE' 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.
This patch also fixes 'ALTER TABLE ... FORCE' to actually rebuild the table.
This change should be reflected in the documentation. Before this patch,
'ALTER TABLE ... FORCE' was unused (See Bug#11746162)
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_CAN_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_CAN_REPAIR flag).
sql/sql_lex.h:
Remove unused ALTER_FORCE flag.
sql/sql_yacc.yy:
Make sure ALTER TABLE ... FORCE recreates the table
by setting the ALTER_RECREATE flag as the ALTER_FORCE
flag was unused.
storage/archive/ha_archive.h:
Added new HA_CAN_REPAIR flag to Archive
storage/csv/ha_tina.h:
Added new HA_CAN_REPAIR flag to CSV
storage/federated/ha_federated.h:
Added new HA_CAN_REPAIR flag to Federated
storage/myisam/ha_myisam.cc:
Added new HA_CAN_REPAIR flag to MyISAM
-rw-r--r-- | client/mysqlcheck.c | 54 | ||||
-rw-r--r-- | mysql-test/r/mysqlcheck.result | 90 | ||||
-rw-r--r-- | mysql-test/std_data/bug47205.frm | bin | 0 -> 8554 bytes | |||
-rw-r--r-- | mysql-test/t/mysqlcheck.test | 108 | ||||
-rw-r--r-- | sql/handler.cc | 10 | ||||
-rw-r--r-- | sql/handler.h | 11 | ||||
-rw-r--r-- | sql/share/errmsg-utf8.txt | 5 | ||||
-rw-r--r-- | sql/sql_admin.cc | 8 | ||||
-rw-r--r-- | sql/sql_lex.h | 27 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 | ||||
-rw-r--r-- | storage/archive/ha_archive.h | 2 | ||||
-rw-r--r-- | storage/csv/ha_tina.h | 3 | ||||
-rw-r--r-- | storage/federated/ha_federated.h | 3 | ||||
-rw-r--r-- | storage/myisam/ha_myisam.cc | 2 |
14 files changed, 268 insertions, 57 deletions
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index f38d674ae8d..78a1ec7d87d 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -42,7 +42,7 @@ static char *opt_password = 0, *current_user = 0, *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 @@ -626,6 +626,27 @@ static int fix_database_storage_name(const char *name) return rc; } +static int rebuild_table(char *name) +{ + char *query, *ptr; + int rc= 0; + query= (char*)my_malloc(sizeof(char) * (12 + fixed_name_length(name) + 6 + 1), + MYF(MY_WME)); + if (!query) + return 1; + ptr= strmov(query, "ALTER TABLE "); + ptr= fix_table_name(ptr, name); + ptr= strxmov(ptr, " FORCE", NullS); + if (mysql_real_query(sock, query, (uint)(ptr - query))) + { + fprintf(stderr, "Failed to %s\n", query); + fprintf(stderr, "Error: %s\n", mysql_error(sock)); + rc= 1; + } + my_free(query); + return rc; +} + static int process_one_db(char *database) { if (what_to_do == DO_UPGRADE) @@ -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; } @@ -769,7 +796,11 @@ 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 && strstr(row[3], "ALTER TABLE") != NULL) + table_rebuild=1; + } } else printf("%-9s: %s", row[2], row[3]); @@ -778,7 +809,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 +912,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 +931,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 +939,16 @@ int main(int argc, char **argv) char *name= (char*) dynamic_array_ptr(&tables4repair, i); handle_request_for_tables(name, fixed_name_length(name)); } + for (i = 0; i < tables4rebuild.elements ; i++) + rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i)); } 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); diff --git a/mysql-test/r/mysqlcheck.result b/mysql-test/r/mysqlcheck.result index ef46eba5ccb..42fb1945d8b 100644 --- a/mysql-test/r/mysqlcheck.result +++ b/mysql-test/r/mysqlcheck.result @@ -109,7 +109,7 @@ mysql.time_zone_name Table is already up to date mysql.time_zone_transition Table is already up to date mysql.time_zone_transition_type Table is already up to date mysql.user Table is already up to date -create table t1 (a int); +create table t1 (a int) engine=myisam; create view v1 as select * from t1; test.t1 OK test.t1 Table is already up to date @@ -117,14 +117,14 @@ test.t1 OK test.t1 Table is already up to date drop view v1; drop table t1; -create table `t``1`(a int); -create table `t 1`(a int); +create table `t``1`(a int) engine=myisam; +create table `t 1`(a int) engine=myisam; test.t 1 OK test.t`1 OK drop table `t``1`, `t 1`; create database d_bug25347; use d_bug25347; -create table t_bug25347 (a int); +create table t_bug25347 (a int) engine=myisam; create view v_bug25347 as select * from t_bug25347; insert into t_bug25347 values (1),(2),(3); flush tables; @@ -164,15 +164,15 @@ Table Op Msg_type Msg_text test.v1 check status OK information_schema.routines check note The storage engine for the table doesn't support check drop view v1; -CREATE TABLE t1(a INT); -CREATE TABLE t2(a INT); +CREATE TABLE t1(a INT) engine=myisam; +CREATE TABLE t2(a INT) engine=myisam; test.t1 Error : Incorrect information in file: './test/t1.frm' error : Corrupt test.t2 OK DROP TABLE t1, t2; End of 5.0 tests -create table t1(a int); +create table t1(a int) engine=myisam; create view v1 as select * from t1; show tables; Tables_in_test @@ -192,7 +192,7 @@ v-1 drop view v1, `v-1`; drop table t1; SET NAMES utf8; -CREATE TABLE `#mysql50#@` (a INT); +CREATE TABLE `#mysql50#@` (a INT) engine=myisam; SHOW TABLES; Tables_in_test #mysql50#@ @@ -203,7 +203,7 @@ SHOW TABLES; Tables_in_test @ DROP TABLE `@`; -CREATE TABLE `я` (a INT); +CREATE TABLE `я` (a INT) engine=myisam; SET NAMES DEFAULT; mysqlcheck --default-character-set="latin1" --databases test test.? @@ -216,8 +216,8 @@ DROP TABLE `я`; SET NAMES DEFAULT; CREATE DATABASE `#mysql50#a@b`; USE `#mysql50#a@b`; -CREATE TABLE `#mysql50#c@d` (a INT); -CREATE TABLE t1 (a INT); +CREATE TABLE `#mysql50#c@d` (a INT) engine=myisam; +CREATE TABLE t1 (a INT) engine=myisam; SELECT * FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_SCHEMA="#mysql50#a@b" ORDER BY trigger_name; TRIGGER_CATALOG TRIGGER_SCHEMA TRIGGER_NAME EVENT_MANIPULATION EVENT_OBJECT_CATALOG EVENT_OBJECT_SCHEMA EVENT_OBJECT_TABLE ACTION_ORDER ACTION_CONDITION ACTION_STATEMENT ACTION_ORIENTATION ACTION_TIMING ACTION_REFERENCE_OLD_TABLE ACTION_REFERENCE_NEW_TABLE ACTION_REFERENCE_OLD_ROW ACTION_REFERENCE_NEW_ROW CREATED SQL_MODE DEFINER CHARACTER_SET_CLIENT COLLATION_CONNECTION DATABASE_COLLATION @@ -246,12 +246,12 @@ USE test; # Bug #31821: --all-in-1 and --fix-table-names don't work together # drop table if exists `#mysql50#t1-1`; -create table `#mysql50#t1-1` (a int); +create table `#mysql50#t1-1` (a int) engine=myisam; show tables like 't1-1'; Tables_in_test (t1-1) t1-1 drop table `t1-1`; -create table `#mysql50#t1-1` (a int); +create table `#mysql50#t1-1` (a int) engine=myisam; show tables like 't1-1'; Tables_in_test (t1-1) t1-1 @@ -260,3 +260,67 @@ 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: Check that ALTER TABLE ... rebuilds the table +CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb; +INSERT INTO bug47205 VALUES ("foobar"); +FLUSH TABLE bug47205; +# Replace the FRM with a 5.0 FRM that will require upgrade +# 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! +# ALTER TABLE ... FORCE should rebuild the table +# and therefore output "affected rows: 1" +ALTER TABLE bug47205 FORCE; +affected rows: 1 +info: Records: 1 Duplicates: 0 Warnings: 0 +# 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: InnoDB - REPAIR not supported +CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY) +DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb; +FLUSH TABLE bug47205; +# Replace the FRM with a 5.0 FRM that will require upgrade +# 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! +# Running mysqlcheck to check and upgrade +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 3: MyISAM - REPAIR supported +# Use an old FRM that will require upgrade +# 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! +# Running mysqlcheck to check and upgrade +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; diff --git a/mysql-test/std_data/bug47205.frm b/mysql-test/std_data/bug47205.frm Binary files differnew file mode 100644 index 00000000000..6d53b221d28 --- /dev/null +++ b/mysql-test/std_data/bug47205.frm diff --git a/mysql-test/t/mysqlcheck.test b/mysql-test/t/mysqlcheck.test index dd113cb4e74..8f93ac7b864 100644 --- a/mysql-test/t/mysqlcheck.test +++ b/mysql-test/t/mysqlcheck.test @@ -2,6 +2,8 @@ # Embedded server doesn't support external clients --source include/not_embedded.inc +--source include/have_innodb.inc + # check that CSV engine was compiled in, as the result of the test # depends on the presence of the log tables (which are CSV-based). --source include/have_csv.inc @@ -34,7 +36,7 @@ drop database if exists client_test_db; # # Bug #16502: mysqlcheck tries to check views # -create table t1 (a int); +create table t1 (a int) engine=myisam; create view v1 as select * from t1; --replace_result 'Table is already up to date' OK --exec $MYSQL_CHECK --analyze --databases test @@ -48,8 +50,8 @@ drop table t1; # # Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks # -create table `t``1`(a int); -create table `t 1`(a int); +create table `t``1`(a int) engine=myisam; +create table `t 1`(a int) engine=myisam; --replace_result 'Table is already up to date' OK --exec $MYSQL_CHECK --databases test drop table `t``1`, `t 1`; @@ -59,7 +61,7 @@ drop table `t``1`, `t 1`; # create database d_bug25347; use d_bug25347; -create table t_bug25347 (a int); +create table t_bug25347 (a int) engine=myisam; create view v_bug25347 as select * from t_bug25347; insert into t_bug25347 values (1),(2),(3); flush tables; @@ -91,8 +93,8 @@ drop view v1; # Bug#37527: mysqlcheck fails to report entire database # when frm file corruption # -CREATE TABLE t1(a INT); -CREATE TABLE t2(a INT); +CREATE TABLE t1(a INT) engine=myisam; +CREATE TABLE t2(a INT) engine=myisam; # backup then null t1.frm --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t1.frm.bak --remove_file $MYSQLD_DATADIR/test/t1.frm @@ -112,7 +114,7 @@ DROP TABLE t1, t2; # # Bug #30679: 5.1 name encoding not performed for views during upgrade # -create table t1(a int); +create table t1(a int) engine=myisam; create view v1 as select * from t1; show tables; let $MYSQLD_DATADIR= `select @@datadir`; @@ -131,7 +133,7 @@ drop table t1; # triggers # SET NAMES utf8; -CREATE TABLE `#mysql50#@` (a INT); +CREATE TABLE `#mysql50#@` (a INT) engine=myisam; SHOW TABLES; SET NAMES DEFAULT; --echo mysqlcheck --fix-table-names --databases test @@ -140,7 +142,7 @@ SET NAMES utf8; SHOW TABLES; DROP TABLE `@`; -CREATE TABLE `я` (a INT); +CREATE TABLE `я` (a INT) engine=myisam; SET NAMES DEFAULT; --echo mysqlcheck --default-character-set="latin1" --databases test # Error returned depends on platform, replace it with "Table doesn't exist" @@ -154,8 +156,8 @@ SET NAMES DEFAULT; CREATE DATABASE `#mysql50#a@b`; USE `#mysql50#a@b`; -CREATE TABLE `#mysql50#c@d` (a INT); -CREATE TABLE t1 (a INT); +CREATE TABLE `#mysql50#c@d` (a INT) engine=myisam; +CREATE TABLE t1 (a INT) engine=myisam; # Create 5.0 like triggers let $MYSQLTEST_VARDIR= `select @@datadir`; @@ -207,12 +209,12 @@ USE test; drop table if exists `#mysql50#t1-1`; --enable_warnings -create table `#mysql50#t1-1` (a int); +create table `#mysql50#t1-1` (a int) engine=myisam; --exec $MYSQL_CHECK --all-in-1 --fix-table-names --databases test show tables like 't1-1'; drop table `t1-1`; -create table `#mysql50#t1-1` (a int); +create table `#mysql50#t1-1` (a int) engine=myisam; --exec $MYSQL_CHECK --all-in-1 --fix-table-names test "#mysql50#t1-1" show tables like 't1-1'; drop table `t1-1`; @@ -229,3 +231,83 @@ 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: Check that ALTER TABLE ... rebuilds the table + +CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY) + DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb; + +INSERT INTO bug47205 VALUES ("foobar"); +FLUSH TABLE bug47205; + +--echo # Replace the FRM with a 5.0 FRM that will require upgrade +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; + +--echo # ALTER TABLE ... FORCE should rebuild the table +--echo # and therefore output "affected rows: 1" +--enable_info +ALTER TABLE bug47205 FORCE; +--disable_info + +--echo # Table should now be ok +CHECK TABLE bug47205 FOR UPGRADE; + +DROP TABLE bug47205; + +--echo # +--echo # Test 2: InnoDB - REPAIR not supported + +CREATE TABLE bug47205(a VARCHAR(20) PRIMARY KEY) + DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci engine=innodb; + +FLUSH TABLE bug47205; + +--echo # Replace the FRM with a 5.0 FRM that will require upgrade +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; + +--echo # Running mysqlcheck to check and upgrade +--exec $MYSQL_CHECK --check-upgrade --auto-repair test + +--echo # Table should now be ok +CHECK TABLE bug47205 FOR UPGRADE; + +DROP TABLE bug47205; + +--echo # +--echo # Test 3: MyISAM - REPAIR supported + +--echo # Use an old FRM that will require upgrade +--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; + +--echo # Running mysqlcheck to check and upgrade +--exec $MYSQL_CHECK --check-upgrade --auto-repair test + +--echo # Table should now be ok +CHECK TABLE bug47205 FOR UPGRADE; + +DROP TABLE bug47205; diff --git a/sql/handler.cc b/sql/handler.cc index 9ca1f3a20f8..fefc0553c88 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3214,9 +3214,13 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) mark_trx_read_write(); - if ((result= repair(thd, check_opt))) - return result; - return update_frm_version(table); + result= repair(thd, check_opt); + DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED || + ha_table_flags() & HA_CAN_REPAIR); + + if (result == HA_ADMIN_OK) + result= update_frm_version(table); + return result; } diff --git a/sql/handler.h b/sql/handler.h index 3cd4acee80d..ca72640f887 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -153,6 +153,12 @@ ordered. */ #define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36) +/* + Engine supports REPAIR TABLE. Used by CHECK TABLE FOR UPGRADE if an + incompatible table is detected. If this flag is set, CHECK TABLE FOR UPGRADE + will report ER_TABLE_NEEDS_UPGRADE, otherwise ER_TABLE_NEED_REBUILD. +*/ +#define HA_CAN_REPAIR (LL(1) << 37) /* Set of all binlog flags. Currently only contain the capabilities @@ -2010,7 +2016,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_CAN_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, diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt index 998e88704d8..0d315fe1441 100644 --- a/sql/share/errmsg-utf8.txt +++ b/sql/share/errmsg-utf8.txt @@ -6397,3 +6397,8 @@ 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'." + +# When translating this error message make sure to include "ALTER TABLE" in the +# message as mysqlcheck parses the error message looking for ALTER TABLE. +ER_TABLE_NEEDS_REBUILD + eng "Table rebuild required. Please do \"ALTER TABLE `%-.32s` FORCE\" or dump/reload to fix it!" diff --git a/sql/sql_admin.cc b/sql/sql_admin.cc index eb6853751ee..dea8d38938c 100644 --- a/sql/sql_admin.cc +++ b/sql/sql_admin.cc @@ -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_CAN_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; diff --git a/sql/sql_lex.h b/sql/sql_lex.h index a9abe174d6e..e6b5f23f17e 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -944,20 +944,19 @@ inline bool st_select_lex_unit::is_union () #define ALTER_CHANGE_COLUMN_DEFAULT (1L << 8) #define ALTER_KEYS_ONOFF (1L << 9) #define ALTER_CONVERT (1L << 10) -#define ALTER_FORCE (1L << 11) -#define ALTER_RECREATE (1L << 12) -#define ALTER_ADD_PARTITION (1L << 13) -#define ALTER_DROP_PARTITION (1L << 14) -#define ALTER_COALESCE_PARTITION (1L << 15) -#define ALTER_REORGANIZE_PARTITION (1L << 16) -#define ALTER_PARTITION (1L << 17) -#define ALTER_ADMIN_PARTITION (1L << 18) -#define ALTER_TABLE_REORG (1L << 19) -#define ALTER_REBUILD_PARTITION (1L << 20) -#define ALTER_ALL_PARTITION (1L << 21) -#define ALTER_REMOVE_PARTITIONING (1L << 22) -#define ALTER_FOREIGN_KEY (1L << 23) -#define ALTER_TRUNCATE_PARTITION (1L << 24) +#define ALTER_RECREATE (1L << 11) +#define ALTER_ADD_PARTITION (1L << 12) +#define ALTER_DROP_PARTITION (1L << 13) +#define ALTER_COALESCE_PARTITION (1L << 14) +#define ALTER_REORGANIZE_PARTITION (1L << 15) +#define ALTER_PARTITION (1L << 16) +#define ALTER_ADMIN_PARTITION (1L << 17) +#define ALTER_TABLE_REORG (1L << 18) +#define ALTER_REBUILD_PARTITION (1L << 19) +#define ALTER_ALL_PARTITION (1L << 20) +#define ALTER_REMOVE_PARTITIONING (1L << 21) +#define ALTER_FOREIGN_KEY (1L << 22) +#define ALTER_TRUNCATE_PARTITION (1L << 23) enum enum_alter_table_change_level { diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 02e0d347ef7..13a1b8029f2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -6747,7 +6747,7 @@ alter_list_item: } | FORCE_SYM { - Lex->alter_info.flags|= ALTER_FORCE; + Lex->alter_info.flags|= ALTER_RECREATE; } | alter_order_clause { diff --git a/storage/archive/ha_archive.h b/storage/archive/ha_archive.h index fec41c12b81..a56cc3dd799 100644 --- a/storage/archive/ha_archive.h +++ b/storage/archive/ha_archive.h @@ -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_CAN_REPAIR | HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY); } ulong index_flags(uint idx, uint part, bool all_parts) const diff --git a/storage/csv/ha_tina.h b/storage/csv/ha_tina.h index 845b50e3869..9fcaf2519c6 100644 --- a/storage/csv/ha_tina.h +++ b/storage/csv/ha_tina.h @@ -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_CAN_REPAIR); } ulong index_flags(uint idx, uint part, bool all_parts) const { diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index e39bac525b5..6614b389b1f 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -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_CAN_REPAIR); } /* This is a bitmap of flags that says how the storage engine diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc index c7b6b2239ce..16457088f9c 100644 --- a/storage/myisam/ha_myisam.cc +++ b/storage/myisam/ha_myisam.cc @@ -639,7 +639,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) 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_CAN_REPAIR), can_enable_indexes(1) {} |