Commit 8cb6031d authored by unknown's avatar unknown

Generate warning in ha_delete_table() if files is missing in handler



mysql-test/r/myisam.result:
  Test of DROP TABLE when .MYI or .MYD is missing
mysql-test/r/ndb_autodiscover.result:
  Update test results
mysql-test/r/rpl_EE_error.result:
  Change test to conform with new handling of drop table when handler file is missing
mysql-test/t/myisam.test:
  Test of DROP TABLE when .MYI or .MYD is missing
mysql-test/t/rpl_EE_error.test:
  Change test to conform with new handling of drop table when handler file is missing
sql/handler.cc:
  Generate a warning in ha_delete_table() if we get an error from 'delete_table()'
sql/handler.h:
  More parameters to ha_delete_table() so that we can generate better error messages
sql/sql_table.cc:
  Generate warning in ha_delete_table()
parent ac1852b4
...@@ -1150,3 +1150,15 @@ drop table t1; ...@@ -1150,3 +1150,15 @@ drop table t1;
set storage_engine=MyISAM; set storage_engine=MyISAM;
create table t1 (v varchar(65535)); create table t1 (v varchar(65535));
ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
create table t1 (a int) engine=myisam;
drop table if exists t1;
Warnings:
Error 2 Can't find file: 't1' (errno: 2)
create table t1 (a int) engine=myisam;
drop table t1;
ERROR 42S02: Unknown table 't1'
create table t1 (a int) engine=myisam;
drop table t1;
ERROR HY000: File './test/t1.MYD' not found (Errcode: 2)
drop table t1;
ERROR 42S02: Unknown table 't1'
...@@ -180,7 +180,7 @@ select * from t4; ...@@ -180,7 +180,7 @@ select * from t4;
ERROR 42S02: Table 'test.t4' doesn't exist ERROR 42S02: Table 'test.t4' doesn't exist
drop table if exists t4; drop table if exists t4;
Warnings: Warnings:
Note 1051 Unknown table 't4' Error 155 Table 'test.t4' doesn't exist
drop table t5; drop table t5;
ERROR 42S02: Unknown table 't5' ERROR 42S02: Unknown table 't5'
drop table if exists t5; drop table if exists t5;
......
...@@ -6,7 +6,9 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; ...@@ -6,7 +6,9 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
create table t1 (a int) engine=myisam; create table t1 (a int) engine=myisam;
flush tables; flush tables;
drop table t1; drop table if exists t1;
Warnings:
Error 2 Can't find file: 't1' (errno: 2)
create table t1 (a int, unique(a)) engine=myisam; create table t1 (a int, unique(a)) engine=myisam;
set sql_log_bin=0; set sql_log_bin=0;
insert into t1 values(2); insert into t1 values(2);
......
...@@ -539,3 +539,20 @@ eval set storage_engine=$default; ...@@ -539,3 +539,20 @@ eval set storage_engine=$default;
# MyISAM specific varchar tests # MyISAM specific varchar tests
--error 1118 --error 1118
create table t1 (v varchar(65535)); create table t1 (v varchar(65535));
#
# Test how DROP TABLE works if the index or data file doesn't exists
create table t1 (a int) engine=myisam;
system rm ./var/master-data/test/t1.MYI ;
drop table if exists t1;
create table t1 (a int) engine=myisam;
system rm ./var/master-data/test/t1.MYI ;
--error 1051
drop table t1;
create table t1 (a int) engine=myisam;
system rm ./var/master-data/test/t1.MYD ;
--error 1105
drop table t1;
--error 1051
drop table t1;
...@@ -9,7 +9,7 @@ source include/master-slave.inc; ...@@ -9,7 +9,7 @@ source include/master-slave.inc;
create table t1 (a int) engine=myisam; create table t1 (a int) engine=myisam;
flush tables; flush tables;
system rm ./var/master-data/test/t1.MYI ; system rm ./var/master-data/test/t1.MYI ;
drop table t1; drop table if exists t1;
save_master_pos; save_master_pos;
connection slave; connection slave;
sync_with_master; sync_with_master;
......
...@@ -1027,15 +1027,24 @@ bool ha_flush_logs() ...@@ -1027,15 +1027,24 @@ bool ha_flush_logs()
The .frm file will be deleted only if we return 0 or ENOENT The .frm file will be deleted only if we return 0 or ENOENT
*/ */
int ha_delete_table(enum db_type table_type, const char *path) int ha_delete_table(THD *thd, enum db_type table_type, const char *path,
const char *alias, bool generate_warning)
{ {
handler *file; handler *file;
char tmp_path[FN_REFLEN]; char tmp_path[FN_REFLEN];
int error;
TABLE dummy_table;
TABLE_SHARE dummy_share;
DBUG_ENTER("ha_delete_table");
bzero((char*) &dummy_table, sizeof(dummy_table));
bzero((char*) &dummy_share, sizeof(dummy_share));
dummy_table.s= &dummy_share;
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */ /* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
if (table_type == DB_TYPE_UNKNOWN || if (table_type == DB_TYPE_UNKNOWN ||
! (file=get_new_handler((TABLE*) 0, table_type))) ! (file=get_new_handler(&dummy_table, table_type)))
return ENOENT; DBUG_RETURN(ENOENT);
if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED)) if (lower_case_table_names == 2 && !(file->table_flags() & HA_FILE_BASED))
{ {
...@@ -1044,9 +1053,45 @@ int ha_delete_table(enum db_type table_type, const char *path) ...@@ -1044,9 +1053,45 @@ int ha_delete_table(enum db_type table_type, const char *path)
my_casedn_str(files_charset_info, tmp_path); my_casedn_str(files_charset_info, tmp_path);
path= tmp_path; path= tmp_path;
} }
int error=file->delete_table(path); if ((error= file->delete_table(path)) && generate_warning)
{
/*
Because file->print_error() use my_error() to generate the error message
we must store the error state in thd, reset it and restore it to
be able to get hold of the error message.
(We should in the future either rewrite handler::print_error() or make
a nice method of this.
*/
bool query_error= thd->query_error;
sp_rcontext *spcont= thd->spcont;
SELECT_LEX *current_select= thd->lex->current_select;
char buff[sizeof(thd->net.last_error)];
char new_error[sizeof(thd->net.last_error)];
int last_errno= thd->net.last_errno;
strmake(buff, thd->net.last_error, sizeof(buff)-1);
thd->query_error= 0;
thd->spcont= 0;
thd->lex->current_select= 0;
thd->net.last_error[0]= 0;
/* Fill up strucutures that print_error may need */
dummy_table.s->path= path;
dummy_table.alias= alias;
file->print_error(error, 0);
strmake(new_error, thd->net.last_error, sizeof(buff)-1);
/* restore thd */
thd->query_error= query_error;
thd->spcont= spcont;
thd->lex->current_select= current_select;
thd->net.last_errno= last_errno;
strmake(thd->net.last_error, buff, sizeof(buff)-1);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, new_error);
}
delete file; delete file;
return error; DBUG_RETURN(error);
} }
/**************************************************************************** /****************************************************************************
...@@ -1320,7 +1365,16 @@ ulonglong handler::get_auto_increment() ...@@ -1320,7 +1365,16 @@ ulonglong handler::get_auto_increment()
return nr; return nr;
} }
/* Print error that we got from handler function */
/*
Print error that we got from handler function
NOTE:
In case of delete table it's only safe to use the following parts of
the 'table' structure:
table->s->path
table->alias
*/
void handler::print_error(int error, myf errflag) void handler::print_error(int error, myf errflag)
{ {
...@@ -1529,7 +1583,7 @@ int handler::delete_table(const char *name) ...@@ -1529,7 +1583,7 @@ int handler::delete_table(const char *name)
break; break;
} }
else else
enoent_or_zero= 0; enoent_or_zero= 0; // No error for ENOENT
error= enoent_or_zero; error= enoent_or_zero;
} }
return error; return error;
......
...@@ -757,7 +757,8 @@ bool ha_flush_logs(void); ...@@ -757,7 +757,8 @@ bool ha_flush_logs(void);
void ha_drop_database(char* path); void ha_drop_database(char* path);
int ha_create_table(const char *name, HA_CREATE_INFO *create_info, int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
bool update_create_info); bool update_create_info);
int ha_delete_table(enum db_type db_type, const char *path); int ha_delete_table(THD *thd, enum db_type db_type, const char *path,
const char *alias, bool generate_warning);
/* discovery */ /* discovery */
int ha_create_table_from_engine(THD* thd, const char *db, const char *name, int ha_create_table_from_engine(THD* thd, const char *db, const char *name,
......
...@@ -109,11 +109,12 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, ...@@ -109,11 +109,12 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
delete (drop) tables. delete (drop) tables.
SYNOPSIS SYNOPSIS
mysql_rm_table_part2_with_lock() mysql_rm_table_part2_with_lock()
thd Thread handle thd Thread handle
tables List of tables to delete tables List of tables to delete
if_exists If 1, don't give error if one table doesn't exists if_exists If 1, don't give error if one table doesn't exists
dont_log_query Don't write query to log files dont_log_query Don't write query to log files. This will also not
generate warnings if the handler files doesn't exists
NOTES NOTES
Works like documented in mysql_rm_table(), but don't check Works like documented in mysql_rm_table(), but don't check
...@@ -157,7 +158,8 @@ int mysql_rm_table_part2_with_lock(THD *thd, ...@@ -157,7 +158,8 @@ int mysql_rm_table_part2_with_lock(THD *thd,
In this case we give an warning of level 'NOTE' In this case we give an warning of level 'NOTE'
drop_temporary Only drop temporary tables drop_temporary Only drop temporary tables
drop_view Allow to delete VIEW .frm drop_view Allow to delete VIEW .frm
dont_log_query Don't log the query dont_log_query Don't write query to log files. This will also not
generate warnings if the handler files doesn't exists
TODO: TODO:
When logging to the binary log, we should log When logging to the binary log, we should log
...@@ -234,16 +236,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists, ...@@ -234,16 +236,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char *end; char *end;
db_type table_type= get_table_type(path); db_type table_type= get_table_type(path);
*(end=fn_ext(path))=0; // Remove extension for delete *(end=fn_ext(path))=0; // Remove extension for delete
error=ha_delete_table(table_type, path); error= ha_delete_table(thd, table_type, path, table->table_name,
!dont_log_query);
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists) if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) && if_exists)
{
/* Warn that the table did not exist in engine */
if (error == HA_ERR_NO_SUCH_TABLE)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR),
table->table_name);
error= 0; error= 0;
}
if (error == HA_ERR_ROW_IS_REFERENCED) if (error == HA_ERR_ROW_IS_REFERENCED)
{ {
/* the table is referenced by a foreign key constraint */ /* the table is referenced by a foreign key constraint */
...@@ -306,7 +302,7 @@ int quick_rm_table(enum db_type base,const char *db, ...@@ -306,7 +302,7 @@ int quick_rm_table(enum db_type base,const char *db,
error=1; /* purecov: inspected */ error=1; /* purecov: inspected */
my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home, db, table_name); my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home, db, table_name);
unpack_filename(path,path); unpack_filename(path,path);
return ha_delete_table(base,path) || error; return ha_delete_table(current_thd, base, path, table_name, 0) || error;
} }
/* /*
......
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