From f5acf0be01633647f783f436fd01cb2cfa010665 Mon Sep 17 00:00:00 2001 From: "monty@mysql.com" <> Date: Mon, 21 Feb 2005 20:41:48 +0200 Subject: [PATCH] Generate warning in ha_delete_table() if files is missing in handler --- mysql-test/r/myisam.result | 12 +++++ mysql-test/r/ndb_autodiscover.result | 2 +- mysql-test/r/rpl_EE_error.result | 4 +- mysql-test/t/myisam.test | 17 +++++++ mysql-test/t/rpl_EE_error.test | 2 +- sql/handler.cc | 68 +++++++++++++++++++++++++--- sql/handler.h | 3 +- sql/sql_table.cc | 26 +++++------ 8 files changed, 108 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result index 138cae5cadd..01aca27d4fc 100644 --- a/mysql-test/r/myisam.result +++ b/mysql-test/r/myisam.result @@ -1150,3 +1150,15 @@ drop table t1; set storage_engine=MyISAM; 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 +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' diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result index afea2fa3e0a..38b34579f03 100644 --- a/mysql-test/r/ndb_autodiscover.result +++ b/mysql-test/r/ndb_autodiscover.result @@ -180,7 +180,7 @@ select * from t4; ERROR 42S02: Table 'test.t4' doesn't exist drop table if exists t4; Warnings: -Note 1051 Unknown table 't4' +Error 155 Table 'test.t4' doesn't exist drop table t5; ERROR 42S02: Unknown table 't5' drop table if exists t5; diff --git a/mysql-test/r/rpl_EE_error.result b/mysql-test/r/rpl_EE_error.result index 49ad4832c81..f4765b4b13c 100644 --- a/mysql-test/r/rpl_EE_error.result +++ b/mysql-test/r/rpl_EE_error.result @@ -6,7 +6,9 @@ drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; create table t1 (a int) engine=myisam; 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; set sql_log_bin=0; insert into t1 values(2); diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test index 44ff789632d..05e80597fab 100644 --- a/mysql-test/t/myisam.test +++ b/mysql-test/t/myisam.test @@ -539,3 +539,20 @@ eval set storage_engine=$default; # MyISAM specific varchar tests --error 1118 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; diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test index 1a1572b48b0..90d8c36685f 100644 --- a/mysql-test/t/rpl_EE_error.test +++ b/mysql-test/t/rpl_EE_error.test @@ -9,7 +9,7 @@ source include/master-slave.inc; create table t1 (a int) engine=myisam; flush tables; system rm ./var/master-data/test/t1.MYI ; -drop table t1; +drop table if exists t1; save_master_pos; connection slave; sync_with_master; diff --git a/sql/handler.cc b/sql/handler.cc index 08571521677..b733ec6c267 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1027,15 +1027,24 @@ bool ha_flush_logs() 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; 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 */ if (table_type == DB_TYPE_UNKNOWN || - ! (file=get_new_handler((TABLE*) 0, table_type))) - return ENOENT; + ! (file=get_new_handler(&dummy_table, table_type))) + DBUG_RETURN(ENOENT); 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) my_casedn_str(files_charset_info, 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; - return error; + DBUG_RETURN(error); } /**************************************************************************** @@ -1320,7 +1365,16 @@ ulonglong handler::get_auto_increment() 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) { @@ -1529,7 +1583,7 @@ int handler::delete_table(const char *name) break; } else - enoent_or_zero= 0; + enoent_or_zero= 0; // No error for ENOENT error= enoent_or_zero; } return error; diff --git a/sql/handler.h b/sql/handler.h index fb368bad29f..3a1862cad07 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -757,7 +757,8 @@ bool ha_flush_logs(void); void ha_drop_database(char* path); int ha_create_table(const char *name, HA_CREATE_INFO *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 */ int ha_create_table_from_engine(THD* thd, const char *db, const char *name, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 7f89db4f651..b38014eb4ea 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -109,11 +109,12 @@ bool mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists, delete (drop) tables. SYNOPSIS - mysql_rm_table_part2_with_lock() - thd Thread handle - tables List of tables to delete - if_exists If 1, don't give error if one table doesn't exists - dont_log_query Don't write query to log files + mysql_rm_table_part2_with_lock() + thd Thread handle + tables List of tables to delete + if_exists If 1, don't give error if one table doesn't exists + dont_log_query Don't write query to log files. This will also not + generate warnings if the handler files doesn't exists NOTES Works like documented in mysql_rm_table(), but don't check @@ -157,7 +158,8 @@ int mysql_rm_table_part2_with_lock(THD *thd, In this case we give an warning of level 'NOTE' drop_temporary Only drop temporary tables 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: 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, char *end; db_type table_type= get_table_type(path); *(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) - { - /* 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; - } if (error == HA_ERR_ROW_IS_REFERENCED) { /* the table is referenced by a foreign key constraint */ @@ -306,7 +302,7 @@ int quick_rm_table(enum db_type base,const char *db, error=1; /* purecov: inspected */ my_snprintf(path, sizeof(path), "%s/%s/%s", mysql_data_home, db, table_name); unpack_filename(path,path); - return ha_delete_table(base,path) || error; + return ha_delete_table(current_thd, base, path, table_name, 0) || error; } /*