Commit 0db0e64f authored by Jon Olav Hauglid's avatar Jon Olav Hauglid

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
parent 5e32755e
...@@ -42,7 +42,7 @@ static char *opt_password = 0, *current_user = 0, ...@@ -42,7 +42,7 @@ static char *opt_password = 0, *current_user = 0,
*default_charset= 0, *current_host= 0; *default_charset= 0, *current_host= 0;
static char *opt_plugin_dir= 0, *opt_default_auth= 0; static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static int first_error = 0; static int first_error = 0;
DYNAMIC_ARRAY tables4repair; DYNAMIC_ARRAY tables4repair, tables4rebuild;
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
static char *shared_memory_base_name=0; static char *shared_memory_base_name=0;
#endif #endif
...@@ -626,6 +626,27 @@ static int fix_database_storage_name(const char *name) ...@@ -626,6 +626,27 @@ static int fix_database_storage_name(const char *name)
return rc; 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) static int process_one_db(char *database)
{ {
if (what_to_do == DO_UPGRADE) if (what_to_do == DO_UPGRADE)
...@@ -739,7 +760,7 @@ static void print_result() ...@@ -739,7 +760,7 @@ static void print_result()
MYSQL_ROW row; MYSQL_ROW row;
char prev[NAME_LEN*2+2]; char prev[NAME_LEN*2+2];
uint i; uint i;
my_bool found_error=0; my_bool found_error=0, table_rebuild=0;
res = mysql_use_result(sock); res = mysql_use_result(sock);
...@@ -758,8 +779,14 @@ static void print_result() ...@@ -758,8 +779,14 @@ static void print_result()
*/ */
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR && if (found_error && opt_auto_repair && what_to_do != DO_REPAIR &&
strcmp(row[3],"OK")) strcmp(row[3],"OK"))
{
if (table_rebuild)
insert_dynamic(&tables4rebuild, (uchar*) prev);
else
insert_dynamic(&tables4repair, (uchar*) prev); insert_dynamic(&tables4repair, (uchar*) prev);
}
found_error=0; found_error=0;
table_rebuild=0;
if (opt_silent) if (opt_silent)
continue; continue;
} }
...@@ -769,7 +796,11 @@ static void print_result() ...@@ -769,7 +796,11 @@ static void print_result()
{ {
printf("%s\n%-9s: %s", row[0], row[2], row[3]); printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (strcmp(row[2],"note")) if (strcmp(row[2],"note"))
{
found_error=1; found_error=1;
if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL)
table_rebuild=1;
}
} }
else else
printf("%-9s: %s", row[2], row[3]); printf("%-9s: %s", row[2], row[3]);
...@@ -778,7 +809,12 @@ static void print_result() ...@@ -778,7 +809,12 @@ static void print_result()
} }
/* add the last table to be repaired to the list */ /* add the last table to be repaired to the list */
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR) if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
{
if (table_rebuild)
insert_dynamic(&tables4rebuild, (uchar*) prev);
else
insert_dynamic(&tables4repair, (uchar*) prev); insert_dynamic(&tables4repair, (uchar*) prev);
}
mysql_free_result(res); mysql_free_result(res);
} }
...@@ -876,7 +912,8 @@ int main(int argc, char **argv) ...@@ -876,7 +912,8 @@ int main(int argc, char **argv)
} }
if (opt_auto_repair && 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; first_error = 1;
goto end; goto end;
...@@ -894,7 +931,7 @@ int main(int argc, char **argv) ...@@ -894,7 +931,7 @@ int main(int argc, char **argv)
{ {
uint i; uint i;
if (!opt_silent && tables4repair.elements) if (!opt_silent && (tables4repair.elements || tables4rebuild.elements))
puts("\nRepairing tables"); puts("\nRepairing tables");
what_to_do = DO_REPAIR; what_to_do = DO_REPAIR;
for (i = 0; i < tables4repair.elements ; i++) for (i = 0; i < tables4repair.elements ; i++)
...@@ -902,11 +939,16 @@ int main(int argc, char **argv) ...@@ -902,11 +939,16 @@ int main(int argc, char **argv)
char *name= (char*) dynamic_array_ptr(&tables4repair, i); char *name= (char*) dynamic_array_ptr(&tables4repair, i);
handle_request_for_tables(name, fixed_name_length(name)); 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: end:
dbDisconnect(current_host); dbDisconnect(current_host);
if (opt_auto_repair) if (opt_auto_repair)
{
delete_dynamic(&tables4repair); delete_dynamic(&tables4repair);
delete_dynamic(&tables4rebuild);
}
my_free(opt_password); my_free(opt_password);
#ifdef HAVE_SMEM #ifdef HAVE_SMEM
my_free(shared_memory_base_name); my_free(shared_memory_base_name);
......
...@@ -109,7 +109,7 @@ mysql.time_zone_name Table is already up to date ...@@ -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 Table is already up to date
mysql.time_zone_transition_type 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 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; create view v1 as select * from t1;
test.t1 OK test.t1 OK
test.t1 Table is already up to date test.t1 Table is already up to date
...@@ -117,14 +117,14 @@ test.t1 OK ...@@ -117,14 +117,14 @@ test.t1 OK
test.t1 Table is already up to date test.t1 Table is already up to date
drop view v1; drop view v1;
drop table t1; drop table t1;
create table `t``1`(a int); create table `t``1`(a int) engine=myisam;
create table `t 1`(a int); create table `t 1`(a int) engine=myisam;
test.t 1 OK test.t 1 OK
test.t`1 OK test.t`1 OK
drop table `t``1`, `t 1`; drop table `t``1`, `t 1`;
create database d_bug25347; create database d_bug25347;
use 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; create view v_bug25347 as select * from t_bug25347;
insert into t_bug25347 values (1),(2),(3); insert into t_bug25347 values (1),(2),(3);
flush tables; flush tables;
...@@ -164,15 +164,15 @@ Table Op Msg_type Msg_text ...@@ -164,15 +164,15 @@ Table Op Msg_type Msg_text
test.v1 check status OK test.v1 check status OK
information_schema.routines check note The storage engine for the table doesn't support check information_schema.routines check note The storage engine for the table doesn't support check
drop view v1; drop view v1;
CREATE TABLE t1(a INT); CREATE TABLE t1(a INT) engine=myisam;
CREATE TABLE t2(a INT); CREATE TABLE t2(a INT) engine=myisam;
test.t1 test.t1
Error : Incorrect information in file: './test/t1.frm' Error : Incorrect information in file: './test/t1.frm'
error : Corrupt error : Corrupt
test.t2 OK test.t2 OK
DROP TABLE t1, t2; DROP TABLE t1, t2;
End of 5.0 tests End of 5.0 tests
create table t1(a int); create table t1(a int) engine=myisam;
create view v1 as select * from t1; create view v1 as select * from t1;
show tables; show tables;
Tables_in_test Tables_in_test
...@@ -192,7 +192,7 @@ v-1 ...@@ -192,7 +192,7 @@ v-1
drop view v1, `v-1`; drop view v1, `v-1`;
drop table t1; drop table t1;
SET NAMES utf8; SET NAMES utf8;
CREATE TABLE `#mysql50#@` (a INT); CREATE TABLE `#mysql50#@` (a INT) engine=myisam;
SHOW TABLES; SHOW TABLES;
Tables_in_test Tables_in_test
#mysql50#@ #mysql50#@
...@@ -203,7 +203,7 @@ SHOW TABLES; ...@@ -203,7 +203,7 @@ SHOW TABLES;
Tables_in_test Tables_in_test
@ @
DROP TABLE `@`; DROP TABLE `@`;
CREATE TABLE `я` (a INT); CREATE TABLE `я` (a INT) engine=myisam;
SET NAMES DEFAULT; SET NAMES DEFAULT;
mysqlcheck --default-character-set="latin1" --databases test mysqlcheck --default-character-set="latin1" --databases test
test.? test.?
...@@ -216,8 +216,8 @@ DROP TABLE `я`; ...@@ -216,8 +216,8 @@ DROP TABLE `я`;
SET NAMES DEFAULT; SET NAMES DEFAULT;
CREATE DATABASE `#mysql50#a@b`; CREATE DATABASE `#mysql50#a@b`;
USE `#mysql50#a@b`; USE `#mysql50#a@b`;
CREATE TABLE `#mysql50#c@d` (a INT); CREATE TABLE `#mysql50#c@d` (a INT) engine=myisam;
CREATE TABLE t1 (a INT); CREATE TABLE t1 (a INT) engine=myisam;
SELECT * FROM INFORMATION_SCHEMA.TRIGGERS SELECT * FROM INFORMATION_SCHEMA.TRIGGERS
WHERE TRIGGER_SCHEMA="#mysql50#a@b" ORDER BY trigger_name; 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 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; ...@@ -246,12 +246,12 @@ USE test;
# Bug #31821: --all-in-1 and --fix-table-names don't work together # Bug #31821: --all-in-1 and --fix-table-names don't work together
# #
drop table if exists `#mysql50#t1-1`; 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'; show tables like 't1-1';
Tables_in_test (t1-1) Tables_in_test (t1-1)
t1-1 t1-1
drop table `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'; show tables like 't1-1';
Tables_in_test (t1-1) Tables_in_test (t1-1)
t1-1 t1-1
...@@ -260,3 +260,67 @@ End of 5.1 tests ...@@ -260,3 +260,67 @@ End of 5.1 tests
# #
# Bug #35269: mysqlcheck behaves different depending on order of parameters # 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;
This diff was suppressed by a .gitattributes entry.
...@@ -2,6 +2,8 @@ ...@@ -2,6 +2,8 @@
# Embedded server doesn't support external clients # Embedded server doesn't support external clients
--source include/not_embedded.inc --source include/not_embedded.inc
--source include/have_innodb.inc
# check that CSV engine was compiled in, as the result of the test # 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). # depends on the presence of the log tables (which are CSV-based).
--source include/have_csv.inc --source include/have_csv.inc
...@@ -34,7 +36,7 @@ drop database if exists client_test_db; ...@@ -34,7 +36,7 @@ drop database if exists client_test_db;
# #
# Bug #16502: mysqlcheck tries to check views # 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; create view v1 as select * from t1;
--replace_result 'Table is already up to date' OK --replace_result 'Table is already up to date' OK
--exec $MYSQL_CHECK --analyze --databases test --exec $MYSQL_CHECK --analyze --databases test
...@@ -48,8 +50,8 @@ drop table t1; ...@@ -48,8 +50,8 @@ drop table t1;
# #
# Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks # Bug #30654: mysqlcheck fails during upgrade of tables whose names include backticks
# #
create table `t``1`(a int); create table `t``1`(a int) engine=myisam;
create table `t 1`(a int); create table `t 1`(a int) engine=myisam;
--replace_result 'Table is already up to date' OK --replace_result 'Table is already up to date' OK
--exec $MYSQL_CHECK --databases test --exec $MYSQL_CHECK --databases test
drop table `t``1`, `t 1`; drop table `t``1`, `t 1`;
...@@ -59,7 +61,7 @@ drop table `t``1`, `t 1`; ...@@ -59,7 +61,7 @@ drop table `t``1`, `t 1`;
# #
create database d_bug25347; create database d_bug25347;
use 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; create view v_bug25347 as select * from t_bug25347;
insert into t_bug25347 values (1),(2),(3); insert into t_bug25347 values (1),(2),(3);
flush tables; flush tables;
...@@ -91,8 +93,8 @@ drop view v1; ...@@ -91,8 +93,8 @@ drop view v1;
# Bug#37527: mysqlcheck fails to report entire database # Bug#37527: mysqlcheck fails to report entire database
# when frm file corruption # when frm file corruption
# #
CREATE TABLE t1(a INT); CREATE TABLE t1(a INT) engine=myisam;
CREATE TABLE t2(a INT); CREATE TABLE t2(a INT) engine=myisam;
# backup then null t1.frm # backup then null t1.frm
--copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t1.frm.bak --copy_file $MYSQLD_DATADIR/test/t1.frm $MYSQLD_DATADIR/test/t1.frm.bak
--remove_file $MYSQLD_DATADIR/test/t1.frm --remove_file $MYSQLD_DATADIR/test/t1.frm
...@@ -112,7 +114,7 @@ DROP TABLE t1, t2; ...@@ -112,7 +114,7 @@ DROP TABLE t1, t2;
# #
# Bug #30679: 5.1 name encoding not performed for views during upgrade # 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; create view v1 as select * from t1;
show tables; show tables;
let $MYSQLD_DATADIR= `select @@datadir`; let $MYSQLD_DATADIR= `select @@datadir`;
...@@ -131,7 +133,7 @@ drop table t1; ...@@ -131,7 +133,7 @@ drop table t1;
# triggers # triggers
# #
SET NAMES utf8; SET NAMES utf8;
CREATE TABLE `#mysql50#@` (a INT); CREATE TABLE `#mysql50#@` (a INT) engine=myisam;
SHOW TABLES; SHOW TABLES;
SET NAMES DEFAULT; SET NAMES DEFAULT;
--echo mysqlcheck --fix-table-names --databases test --echo mysqlcheck --fix-table-names --databases test
...@@ -140,7 +142,7 @@ SET NAMES utf8; ...@@ -140,7 +142,7 @@ SET NAMES utf8;
SHOW TABLES; SHOW TABLES;
DROP TABLE `@`; DROP TABLE `@`;
CREATE TABLE `я` (a INT); CREATE TABLE `я` (a INT) engine=myisam;
SET NAMES DEFAULT; SET NAMES DEFAULT;
--echo mysqlcheck --default-character-set="latin1" --databases test --echo mysqlcheck --default-character-set="latin1" --databases test
# Error returned depends on platform, replace it with "Table doesn't exist" # Error returned depends on platform, replace it with "Table doesn't exist"
...@@ -154,8 +156,8 @@ SET NAMES DEFAULT; ...@@ -154,8 +156,8 @@ SET NAMES DEFAULT;
CREATE DATABASE `#mysql50#a@b`; CREATE DATABASE `#mysql50#a@b`;
USE `#mysql50#a@b`; USE `#mysql50#a@b`;
CREATE TABLE `#mysql50#c@d` (a INT); CREATE TABLE `#mysql50#c@d` (a INT) engine=myisam;
CREATE TABLE t1 (a INT); CREATE TABLE t1 (a INT) engine=myisam;
# Create 5.0 like triggers # Create 5.0 like triggers
let $MYSQLTEST_VARDIR= `select @@datadir`; let $MYSQLTEST_VARDIR= `select @@datadir`;
...@@ -207,12 +209,12 @@ USE test; ...@@ -207,12 +209,12 @@ USE test;
drop table if exists `#mysql50#t1-1`; drop table if exists `#mysql50#t1-1`;
--enable_warnings --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 --exec $MYSQL_CHECK --all-in-1 --fix-table-names --databases test
show tables like 't1-1'; show tables like 't1-1';
drop table `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" --exec $MYSQL_CHECK --all-in-1 --fix-table-names test "#mysql50#t1-1"
show tables like 't1-1'; show tables like 't1-1';
drop table `t1-1`; drop table `t1-1`;
...@@ -229,3 +231,83 @@ drop table `t1-1`; ...@@ -229,3 +231,83 @@ drop table `t1-1`;
--error 1 --error 1
--exec $MYSQL_CHECK -aoc test "#mysql50#t1-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;
...@@ -3214,9 +3214,13 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt) ...@@ -3214,9 +3214,13 @@ int handler::ha_repair(THD* thd, HA_CHECK_OPT* check_opt)
mark_trx_read_write(); mark_trx_read_write();
if ((result= repair(thd, check_opt))) 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; return result;
return update_frm_version(table);
} }
......
...@@ -153,6 +153,12 @@ ...@@ -153,6 +153,12 @@
ordered. ordered.
*/ */
#define HA_DUPLICATE_KEY_NOT_IN_ORDER (LL(1) << 36) #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 Set of all binlog flags. Currently only contain the capabilities
...@@ -2010,7 +2016,10 @@ class handler :public Sql_alloc ...@@ -2010,7 +2016,10 @@ class handler :public Sql_alloc
upon the table. upon the table.
*/ */
virtual int repair(THD* thd, HA_CHECK_OPT* check_opt) 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 void start_bulk_insert(ha_rows rows) {}
virtual int end_bulk_insert() { return 0; } virtual int end_bulk_insert() { return 0; }
virtual int index_read(uchar * buf, const uchar * key, uint key_len, virtual int index_read(uchar * buf, const uchar * key, uint key_len,
......
...@@ -6397,3 +6397,8 @@ ER_STMT_CACHE_FULL ...@@ -6397,3 +6397,8 @@ ER_STMT_CACHE_FULL
ER_MULTI_UPDATE_KEY_CONFLICT ER_MULTI_UPDATE_KEY_CONFLICT
eng "Primary key/partition key update is not allowed since the table is updated both as '%-.192s' and '%-.192s'." 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!"
...@@ -771,7 +771,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables, ...@@ -771,7 +771,11 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
size_t length; size_t length;
protocol->store(STRING_WITH_LEN("error"), system_charset_info); protocol->store(STRING_WITH_LEN("error"), system_charset_info);
length=my_snprintf(buf, sizeof(buf), ER(ER_TABLE_NEEDS_UPGRADE), 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); table->table_name);
protocol->store(buf, length, system_charset_info); protocol->store(buf, length, system_charset_info);
fatal_error=1; fatal_error=1;
......
...@@ -944,20 +944,19 @@ inline bool st_select_lex_unit::is_union () ...@@ -944,20 +944,19 @@ inline bool st_select_lex_unit::is_union ()
#define ALTER_CHANGE_COLUMN_DEFAULT (1L << 8) #define ALTER_CHANGE_COLUMN_DEFAULT (1L << 8)
#define ALTER_KEYS_ONOFF (1L << 9) #define ALTER_KEYS_ONOFF (1L << 9)
#define ALTER_CONVERT (1L << 10) #define ALTER_CONVERT (1L << 10)
#define ALTER_FORCE (1L << 11) #define ALTER_RECREATE (1L << 11)
#define ALTER_RECREATE (1L << 12) #define ALTER_ADD_PARTITION (1L << 12)
#define ALTER_ADD_PARTITION (1L << 13) #define ALTER_DROP_PARTITION (1L << 13)
#define ALTER_DROP_PARTITION (1L << 14) #define ALTER_COALESCE_PARTITION (1L << 14)
#define ALTER_COALESCE_PARTITION (1L << 15) #define ALTER_REORGANIZE_PARTITION (1L << 15)
#define ALTER_REORGANIZE_PARTITION (1L << 16) #define ALTER_PARTITION (1L << 16)
#define ALTER_PARTITION (1L << 17) #define ALTER_ADMIN_PARTITION (1L << 17)
#define ALTER_ADMIN_PARTITION (1L << 18) #define ALTER_TABLE_REORG (1L << 18)
#define ALTER_TABLE_REORG (1L << 19) #define ALTER_REBUILD_PARTITION (1L << 19)
#define ALTER_REBUILD_PARTITION (1L << 20) #define ALTER_ALL_PARTITION (1L << 20)
#define ALTER_ALL_PARTITION (1L << 21) #define ALTER_REMOVE_PARTITIONING (1L << 21)
#define ALTER_REMOVE_PARTITIONING (1L << 22) #define ALTER_FOREIGN_KEY (1L << 22)
#define ALTER_FOREIGN_KEY (1L << 23) #define ALTER_TRUNCATE_PARTITION (1L << 23)
#define ALTER_TRUNCATE_PARTITION (1L << 24)
enum enum_alter_table_change_level enum enum_alter_table_change_level
{ {
......
...@@ -6747,7 +6747,7 @@ alter_list_item: ...@@ -6747,7 +6747,7 @@ alter_list_item:
} }
| FORCE_SYM | FORCE_SYM
{ {
Lex->alter_info.flags|= ALTER_FORCE; Lex->alter_info.flags|= ALTER_RECREATE;
} }
| alter_order_clause | alter_order_clause
{ {
......
...@@ -90,7 +90,7 @@ class ha_archive: public handler ...@@ -90,7 +90,7 @@ class ha_archive: public handler
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD | return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_CAN_BIT_FIELD |
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_STATS_RECORDS_IS_EXACT | HA_STATS_RECORDS_IS_EXACT |
HA_HAS_RECORDS | HA_HAS_RECORDS | HA_CAN_REPAIR |
HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY); HA_FILE_BASED | HA_CAN_INSERT_DELAYED | HA_CAN_GEOMETRY);
} }
ulong index_flags(uint idx, uint part, bool all_parts) const ulong index_flags(uint idx, uint part, bool all_parts) const
......
...@@ -106,7 +106,8 @@ class ha_tina: public handler ...@@ -106,7 +106,8 @@ class ha_tina: public handler
ulonglong table_flags() const ulonglong table_flags() const
{ {
return (HA_NO_TRANSACTIONS | HA_REC_NOT_IN_SEQ | HA_NO_AUTO_INCREMENT | 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 ulong index_flags(uint idx, uint part, bool all_parts) const
{ {
......
...@@ -149,7 +149,8 @@ class ha_federated: public handler ...@@ -149,7 +149,8 @@ class ha_federated: public handler
HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE | HA_BINLOG_ROW_CAPABLE | HA_BINLOG_STMT_CAPABLE |
HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | HA_NO_PREFIX_CHAR_KEYS | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
HA_NO_TRANSACTIONS /* until fixed by WL#2952 */ | 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 This is a bitmap of flags that says how the storage engine
......
...@@ -639,7 +639,7 @@ ha_myisam::ha_myisam(handlerton *hton, TABLE_SHARE *table_arg) ...@@ -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_DUPLICATE_POS | HA_CAN_INDEX_BLOBS | HA_AUTO_PART_KEY |
HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS | HA_FILE_BASED | HA_CAN_GEOMETRY | HA_NO_TRANSACTIONS |
HA_CAN_INSERT_DELAYED | HA_CAN_BIT_FIELD | HA_CAN_RTREEKEYS | 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) can_enable_indexes(1)
{} {}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment