diff --git a/include/my_sys.h b/include/my_sys.h index 7fca0ed676a51..c038199795785 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -60,6 +60,7 @@ C_MODE_START #define MY_WME 16U /* Write message on error */ #define MY_WAIT_IF_FULL 32U /* Wait and try again if disk full error */ #define MY_IGNORE_BADFD 32U /* my_sync(): ignore 'bad descriptor' errors */ +#define MY_IGNORE_ENOENT 32U /* my_delete() ignores ENOENT (no such file) */ #define MY_ENCRYPT 64U /* Encrypt IO_CACHE temporary files */ #define MY_TEMPORARY 64U /* create_temp_file(): delete file at once */ #define MY_NOSYMLINKS 512U /* my_open(): don't follow symlinks */ diff --git a/mysql-test/main/create_drop_view.result b/mysql-test/main/create_drop_view.result index 9d7e42552bf9f..92fbf5ac9e5fc 100644 --- a/mysql-test/main/create_drop_view.result +++ b/mysql-test/main/create_drop_view.result @@ -52,8 +52,14 @@ id 50 80 40 +DROP TABLE IF EXISTS v1; +Warnings: +Note 1051 Unknown table 'test.v1' DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1; Warnings: Note 4092 Unknown VIEW: 'test.v1' +DROP VIEW IF EXISTS t1; +Warnings: +Note 4092 Unknown VIEW: 'test.t1' DROP TABLE t1; diff --git a/mysql-test/main/create_drop_view.test b/mysql-test/main/create_drop_view.test index 5f5df43a7e065..0ebf643e1f11c 100644 --- a/mysql-test/main/create_drop_view.test +++ b/mysql-test/main/create_drop_view.test @@ -22,6 +22,8 @@ INSERT INTO t1 VALUES (50), (80), (3), (2), (40); SELECT * FROM t1; SELECT * FROM v1; +DROP TABLE IF EXISTS v1; DROP VIEW IF EXISTS v1; DROP VIEW IF EXISTS v1; +DROP VIEW IF EXISTS t1; DROP TABLE t1; diff --git a/mysql-test/main/drop_table_force.result b/mysql-test/main/drop_table_force.result new file mode 100644 index 0000000000000..bb4ecc060b0b3 --- /dev/null +++ b/mysql-test/main/drop_table_force.result @@ -0,0 +1,133 @@ +CALL mtr.add_suppression("Operating system error number"); +CALL mtr.add_suppression("The error means the system cannot"); +CALL mtr.add_suppression("returned OS error 71"); +#Test1: table with missing .ibd can be dropped directly +create table t1(a int)engine=innodb; +drop table t1; +db.opt +# Test droping table without frm without super privilege +create table t1(a int) engine=innodb; +create user test identified by '123456'; +grant all privileges on test.t1 to 'test'@'%'identified by '123456' with grant option; +connect con_test, localhost, test,'123456', ; +connection con_test; +drop table t1; +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +connection default; +disconnect con_test; +drop user test; +db.opt +#Test4: drop table can drop consistent table as well +create table t1(a int) engine=innodb; +drop table t1; +db.opt +#Test5: drop table with triger, and with missing frm +create table t1(a int)engine=innodb; +create trigger t1_trg before insert on t1 for each row begin end; +drop table t1; +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +db.opt +#Test6: table with foreign key references can not be dropped +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table child; +drop table parent; +db.opt +#Test7: drop table twice +create table t1(a int)engine=innodb; +drop table t1; +db.opt +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +db.opt +#Test8: check compatibility with if exists +create table t1(a int)engine=innodb; +drop table t1; +db.opt +drop table if exists t1; +Warnings: +Note 1051 Unknown table 'test.t1' +#Test9: check compatibility with restrict/cascade +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent restrict; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent cascade; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent restrict; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table parent cascade; +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails +drop table child; +drop table parent; +#Test10: drop non-innodb engine table returns ok +create table t1(a int) engine=myisam; +drop table t1; +create table t1(a int) engine=myisam; +drop table t1; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +create table t1(a int) engine=myisam; +drop table t1; +Warnings: +Warning 1017 Can't find file: './test/t1.MYI' (errno: 2 "No such file or directory") +db.opt +create table t1(a int) engine=aria; +db.opt +t1.MAI +drop table t1; +ERROR 42S02: Unknown table 'test.t1' +show warnings; +Level Code Message +Error 29 File './test/t1.MAD' not found (Errcode: 2 "No such file or directory") +Error 1051 Unknown table 'test.t1' +db.opt +create table t2(a int) engine=aria; +flush tables; +db.opt +t2.MAD +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +show warnings; +Level Code Message +Error 1051 Unknown table 'test.t2' +db.opt +create table t2(a int) engine=aria; +flush tables; +db.opt +t2.frm +drop table t2; +Warnings: +Warning 1017 Can't find file: './test/t2.MAI' (errno: 2 "No such file or directory") +create table t2(a int not null) engine=CSV; +flush tables; +drop table t2; +db.opt +create table t2(a int not null) engine=CSV; +flush tables; +drop table t2; +db.opt +create table t2(a int not null) engine=archive; +flush tables; +select * from t2; +a +flush tables; +select * from t2; +ERROR 42S02: Table 'test.t2' doesn't exist +db.opt +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +create table t2(a int not null) engine=archive; +flush tables; +drop table t2; +ERROR 42S02: Unknown table 'test.t2' +db.opt diff --git a/mysql-test/main/drop_table_force.test b/mysql-test/main/drop_table_force.test new file mode 100644 index 0000000000000..bb735309167c2 --- /dev/null +++ b/mysql-test/main/drop_table_force.test @@ -0,0 +1,235 @@ +--source include/have_log_bin.inc +--source include/have_innodb.inc +--source include/have_archive.inc +# +# This test is based on the orginal test from Tencent for DROP TABLE ... FORCE +# In MariaDB we did reuse the code but MariaDB does not require the FORCE +# keyword to drop a table even if the .frm file or some engine files are +# missing. +# To make it easy to see the differences between the orginal code and +# the new one, we have left some references to the original test case +# + +CALL mtr.add_suppression("Operating system error number"); +CALL mtr.add_suppression("The error means the system cannot"); +CALL mtr.add_suppression("returned OS error 71"); + +let $DATADIR= `select @@datadir`; + +--echo #Test1: table with missing .ibd can be dropped directly +# drop table without ibd +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.ibd +drop table t1; +--list_files $DATADIR/test/ + +# Original DROP TABLE .. FORCE required SUPER privilege. MariaDB doesn't +--echo # Test droping table without frm without super privilege + +# create table t1 and rm frm +create table t1(a int) engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# create test user +create user test identified by '123456'; +grant all privileges on test.t1 to 'test'@'%'identified by '123456' with grant option; + +# connect as test +connect (con_test, localhost, test,'123456', ); +--connection con_test + +# drop table with user test +drop table t1; +--error ER_BAD_TABLE_ERROR +drop table t1; + +# connect as root +--connection default + +--disconnect con_test +drop user test; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test4: drop table can drop consistent table as well +create table t1(a int) engine=innodb; +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test5: drop table with triger, and with missing frm +# create table t1 with triger and rm frm +create table t1(a int)engine=innodb; +create trigger t1_trg before insert on t1 for each row begin end; + +let $DATADIR= `select @@datadir`; +--remove_file $DATADIR/test/t1.frm + +drop table t1; +--error ER_BAD_TABLE_ERROR +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test6: table with foreign key references can not be dropped +# create table with foreign key reference and rm frm +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; +--remove_file $DATADIR/test/parent.frm + +# parent can not be dropped when there are foreign key references +--error ER_ROW_IS_REFERENCED_2 +drop table parent; + +# parent can be dropped when there are no foreign key references +drop table child; +drop table parent; + +# check files in datadir about child and parent +--list_files $DATADIR/test/ + +--echo #Test7: drop table twice +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# first drop table will success +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +# second drop with if exists will also ok +drop table if exists t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +--echo #Test8: check compatibility with if exists +create table t1(a int)engine=innodb; +--remove_file $DATADIR/test/t1.frm + +# first drop will success +drop table t1; + +# check files in datadir about t1 +--list_files $DATADIR/test/ + +# second drop with if exists will success +drop table if exists t1; + +--echo #Test9: check compatibility with restrict/cascade +# create table with foreign key reference and rm frm +CREATE TABLE parent (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB; +CREATE TABLE child (id INT, parent_id INT, INDEX par_ind (parent_id), FOREIGN KEY (parent_id) REFERENCES parent(id) ON DELETE CASCADE) ENGINE=INNODB; + +# parent can not be dropped when there are foreign key references +--error ER_ROW_IS_REFERENCED_2 +drop table parent; +--error ER_ROW_IS_REFERENCED_2 +drop table parent restrict; +--error ER_ROW_IS_REFERENCED_2 +drop table parent cascade; +--error ER_ROW_IS_REFERENCED_2 +drop table parent; +--error ER_ROW_IS_REFERENCED_2 +drop table parent restrict; +--error ER_ROW_IS_REFERENCED_2 +drop table parent cascade; + +# parent can be dropped when there are no foreign key references +drop table child; +drop table parent; + +--echo #Test10: drop non-innodb engine table returns ok +# create myisam table t1 and rm .frm +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.frm +--replace_result \\ / +drop table t1; + +# create myisam table t1 and rm .MYD +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.MYD +--replace_result \\ / +drop table t1; + +# create myisam table t1 and rm .MYI +create table t1(a int) engine=myisam; +--remove_file $DATADIR/test/t1.MYI +--replace_result \\ / +drop table t1; +--list_files $DATADIR/test/ + +# create Aria table t1 and rm .frm and .MAD +create table t1(a int) engine=aria; +--remove_file $DATADIR/test/t1.frm +--remove_file $DATADIR/test/t1.MAD +--list_files $DATADIR/test/ +--error ER_BAD_TABLE_ERROR +drop table t1; +--replace_result \\ / +show warnings; +--list_files $DATADIR/test/ + +# create Aria table t2 and rm .frm and .MAI +create table t2(a int) engine=aria; +flush tables; +--remove_file $DATADIR/test/t2.frm +--remove_file $DATADIR/test/t2.MAI +--list_files $DATADIR/test/ +--error ER_BAD_TABLE_ERROR +drop table t2; +--replace_result \\ / +show warnings; +--list_files $DATADIR/test/ + +# create Aria table t2 and rm .MAI and .MAD +create table t2(a int) engine=aria; +flush tables; +--remove_file $DATADIR/test/t2.MAD +--remove_file $DATADIR/test/t2.MAI +--list_files $DATADIR/test/ +--replace_result \\ / +drop table t2; + +# create CVS table t2 and rm .frm +create table t2(a int not null) engine=CSV; +flush tables; +--remove_file $DATADIR/test/t2.frm +drop table t2; +--list_files $DATADIR/test/ + +# create CVS table t2 and rm .frm +create table t2(a int not null) engine=CSV; +flush tables; +--remove_file $DATADIR/test/t2.CSV +drop table t2; +--list_files $DATADIR/test/ + +# create Archive table t2 and rm +# Note that as Archive has discovery, removing the +# ARZ will automatically remove the .frm + +create table t2(a int not null) engine=archive; +flush tables; +--error 1 +--remove_file $DATADIR/test/t2.frm +select * from t2; +flush tables; +--remove_file $DATADIR/test/t2.ARZ +--error ER_NO_SUCH_TABLE +select * from t2; +--list_files $DATADIR/test/ +--replace_result \\ / +--error ER_BAD_TABLE_ERROR +drop table t2; + +create table t2(a int not null) engine=archive; +flush tables; +--remove_file $DATADIR/test/t2.ARZ +--error ER_BAD_TABLE_ERROR +drop table t2; +--list_files $DATADIR/test/ diff --git a/mysql-test/suite/innodb/r/innodb_force_recovery.result b/mysql-test/suite/innodb/r/innodb_force_recovery.result index 9d5371262163c..029a6f71fa337 100644 --- a/mysql-test/suite/innodb/r/innodb_force_recovery.result +++ b/mysql-test/suite/innodb/r/innodb_force_recovery.result @@ -40,7 +40,7 @@ ERROR HY000: Running in read-only mode create table t3(f1 int not null)engine=innodb; ERROR HY000: Can't create table `test`.`t3` (errno: 165 "Table is read only") drop table t3; -ERROR 42S02: Unknown table 'test.t3' +ERROR HY000: Table 't3' is read only rename table t2 to t3; ERROR HY000: Error on rename of './test/t2' to './test/t3' (errno: 165 "Table is read only") truncate table t2; diff --git a/mysql-test/suite/innodb/t/innodb_force_recovery.test b/mysql-test/suite/innodb/t/innodb_force_recovery.test index bd9554e6b6e4e..76baf55af8391 100644 --- a/mysql-test/suite/innodb/t/innodb_force_recovery.test +++ b/mysql-test/suite/innodb/t/innodb_force_recovery.test @@ -68,7 +68,7 @@ update t2 set f1=3 where f2=2; --error ER_CANT_CREATE_TABLE create table t3(f1 int not null)engine=innodb; ---error ER_BAD_TABLE_ERROR +--error ER_OPEN_AS_READONLY drop table t3; --error ER_ERROR_ON_RENAME diff --git a/mysys/my_delete.c b/mysys/my_delete.c index a0210558dfd48..3d80f187e194a 100644 --- a/mysys/my_delete.c +++ b/mysys/my_delete.c @@ -43,9 +43,12 @@ int my_delete(const char *name, myf MyFlags) err= unlink(name); #endif - if(err) + if ((MyFlags & MY_IGNORE_ENOENT) && errno == ENOENT) + DBUG_RETURN(0); + + if (err) { - my_errno=errno; + my_errno= errno; if (MyFlags & (MY_FAE+MY_WME)) my_error(EE_DELETE, MYF(ME_BELL), name, errno); } diff --git a/mysys/my_symlink2.c b/mysys/my_symlink2.c index aef77333e7549..0b580ecd32f5f 100644 --- a/mysys/my_symlink2.c +++ b/mysys/my_symlink2.c @@ -170,6 +170,7 @@ int my_rename_with_symlink(const char *from, const char *to, myf MyFlags) in this case both the symlink and the symlinked file are deleted, but only if the symlinked file is not in the datadir. */ + int my_handler_delete_with_symlink(const char *filename, myf sync_dir) { char real[FN_REFLEN]; @@ -182,8 +183,9 @@ int my_handler_delete_with_symlink(const char *filename, myf sync_dir) Delete the symlinked file only if the symlink is not pointing into datadir. */ - if (!(my_realpath(real, filename, MYF(0)) || mysys_test_invalid_symlink(real))) + if (!(my_realpath(real, filename, MYF(0)) || + mysys_test_invalid_symlink(real))) res= my_delete(real, MYF(MY_NOSYMLINKS | sync_dir)); } - DBUG_RETURN(my_delete(filename, MYF(sync_dir)) || res); + DBUG_RETURN(my_delete(filename, sync_dir) || res); } diff --git a/sql/ha_sequence.cc b/sql/ha_sequence.cc index 5362dd2fc7398..4eabd82007113 100644 --- a/sql/ha_sequence.cc +++ b/sql/ha_sequence.cc @@ -19,13 +19,13 @@ #include "mariadb.h" #include "sql_list.h" #include "table.h" +#include "sql_table.h" #include "sql_sequence.h" #include "ha_sequence.h" #include "sql_plugin.h" #include "mysql/plugin.h" #include "sql_priv.h" #include "sql_parse.h" -#include "sql_table.h" #include "sql_update.h" #include "sql_base.h" #include "log_event.h" @@ -380,6 +380,13 @@ static handler *sequence_create_handler(handlerton *hton, MEM_ROOT *mem_root) { DBUG_ENTER("sequence_create_handler"); + if (unlikely(!share)) + { + /* + This can happen if we call get_new_handler with a non existing share + */ + DBUG_RETURN(0); + } DBUG_RETURN(new (mem_root) ha_sequence(hton, share)); } @@ -427,7 +434,8 @@ static int sequence_initialize(void *p) HTON_HIDDEN | HTON_TEMPORARY_NOT_SUPPORTED | HTON_ALTER_NOT_SUPPORTED | - HTON_NO_PARTITION); + HTON_NO_PARTITION | + HTON_AUTOMATIC_DELETE_TABLE); DBUG_RETURN(0); } diff --git a/sql/handler.cc b/sql/handler.cc index 64d7fae1f1a00..ed1ac7356ccf0 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -148,6 +148,44 @@ TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"", static TYPELIB known_extensions= {0,"known_exts", NULL, NULL}; uint known_extensions_id= 0; + +class Table_exists_error_handler : public Internal_error_handler +{ +public: + Table_exists_error_handler() + : m_handled_errors(0), m_unhandled_errors(0) + {} + + bool handle_condition(THD *thd, + uint sql_errno, + const char* sqlstate, + Sql_condition::enum_warning_level *level, + const char* msg, + Sql_condition ** cond_hdl) + { + *cond_hdl= NULL; + if (non_existing_table_error(sql_errno)) + { + m_handled_errors++; + return TRUE; + } + + if (*level == Sql_condition::WARN_LEVEL_ERROR) + m_unhandled_errors++; + return FALSE; + } + + bool safely_trapped_errors() + { + return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); + } + +private: + int m_handled_errors; + int m_unhandled_errors; +}; + + static int commit_one_phase_2(THD *thd, bool all, THD_TRANS *trans, bool is_real_trans); @@ -2674,26 +2712,34 @@ const char *get_canonical_filename(handler *file, const char *path, } -/** delete a table in the engine +/** + Delete a table in the engine + + @return 0 Table was deleted + @return -1 Table didn't exists, no error given + @return # Error from table handler @note ENOENT and HA_ERR_NO_SUCH_TABLE are not considered errors. - The .frm file will be deleted only if we return 0. + The .frm file should be deleted by the caller only if we return <= 0. */ + int ha_delete_table(THD *thd, handlerton *table_type, const char *path, - const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning) + const LEX_CSTRING *db, const LEX_CSTRING *alias, + bool generate_warning) { handler *file; char tmp_path[FN_REFLEN]; int error; TABLE dummy_table; TABLE_SHARE dummy_share; + bool is_error= thd->is_error(); DBUG_ENTER("ha_delete_table"); /* table_type is NULL in ALTER TABLE when renaming only .frm files */ if (table_type == NULL || table_type == view_pseudo_hton || ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) - DBUG_RETURN(0); + DBUG_RETURN(-1); bzero((char*) &dummy_table, sizeof(dummy_table)); bzero((char*) &dummy_share, sizeof(dummy_share)); @@ -2703,11 +2749,11 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, if (unlikely((error= file->ha_delete_table(path)))) { /* - it's not an error if the table doesn't exist in the engine. + It's not an error if the table doesn't exist in the engine. warn the user, but still report DROP being a success */ - bool intercept= (error == ENOENT || error == HA_ERR_NO_SUCH_TABLE || - error == HA_ERR_UNSUPPORTED); + bool intercept= non_existing_table_error(error); + DBUG_ASSERT(error > 0); if ((!intercept || generate_warning) && ! thd->is_error()) { @@ -2723,8 +2769,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, } if (intercept) { - thd->clear_error(); - error= 0; + /* Clear error if we got it in this function */ + if (!is_error) + thd->clear_error(); + error= -1; } } delete file; @@ -4368,45 +4416,64 @@ uint handler::get_dup_key(int error) @note We assume that the handler may return more extensions than - was actually used for the file. + was actually used for the file. We also assume that the first + extension is the most important one (see the comment near + handlerton::tablefile_extensions). If this exist and we can't delete + that it, we will abort the delete. + If the first one doesn't exists, we have to try to delete all other + extension as there is chance that the server had crashed between + the delete of the first file and the next @retval 0 If we successfully deleted at least one file from base_ext and - didn't get any other errors than ENOENT + didn't get any other errors than ENOENT + @retval !0 Error */ + int handler::delete_table(const char *name) { - int saved_error= 0; - int error= 0; - int enoent_or_zero; + int saved_error= ENOENT; + bool abort_if_first_file_error= 1; + bool some_file_deleted= 0; + DBUG_ENTER("handler::delete_table"); + // For discovery tables, it's ok if first file doesn't exists if (ht->discover_table) - enoent_or_zero= 0; // the table may not exist in the engine, it's ok - else - enoent_or_zero= ENOENT; // the first file of bas_ext() *must* exist + { + abort_if_first_file_error= 0; + saved_error= 0; + if (!bas_ext()) + { + DBUG_ASSERT(ht->flags & HTON_AUTOMATIC_DELETE_TABLE); + DBUG_RETURN(0); // Drop succeded + } + } - for (const char **ext=bas_ext(); *ext ; ext++) + for (const char **ext= bas_ext(); *ext ; ext++) { - if (mysql_file_delete_with_symlink(key_file_misc, name, *ext, 0)) + int error; + if ((error= mysql_file_delete_with_symlink(key_file_misc, name, *ext, + MYF(0)))) { if (my_errno != ENOENT) { + saved_error= my_errno; /* - If error on the first existing file, return the error. + If error other than file not found on the first existing file, + return the error. Otherwise delete as much as possible. */ - if (enoent_or_zero) - return my_errno; - saved_error= my_errno; + if (abort_if_first_file_error) + DBUG_RETURN(saved_error); } } else - enoent_or_zero= 0; // No error for ENOENT - error= enoent_or_zero; + some_file_deleted= 1; + abort_if_first_file_error= 0; } - return saved_error ? saved_error : error; + DBUG_RETURN(some_file_deleted && saved_error == ENOENT ? 0 : saved_error); } @@ -4441,6 +4508,21 @@ void handler::drop_table(const char *name) } +/** + Return true if the error from drop table means that the + table didn't exists +*/ + +bool non_existing_table_error(int error) +{ + return (error == ENOENT || error == HA_ERR_NO_SUCH_TABLE || + error == HA_ERR_UNSUPPORTED || + error == ER_NO_SUCH_TABLE || + error == ER_NO_SUCH_TABLE_IN_ENGINE || + error == ER_WRONG_OBJECT); +} + + /** Performs checks upon the table. @@ -4456,6 +4538,7 @@ void handler::drop_table(const char *name) @retval HA_ADMIN_NOT_IMPLEMENTED */ + int handler::ha_check(THD *thd, HA_CHECK_OPT *check_opt) { int error; @@ -4901,6 +4984,88 @@ handler::ha_drop_table(const char *name) } +/** + Structure used during force drop table. +*/ + +struct st_force_drop_table_params +{ + const char *path; + const LEX_CSTRING *db; + const LEX_CSTRING *alias; + int error; +}; + + +/** + Try to delete table from a given plugin + Table types with discovery is ignored as these .frm files would have + been created during discovery and thus doesn't need to be found + for drop table force +*/ + +static my_bool delete_table_force(THD *thd, plugin_ref plugin, void *arg) +{ + handlerton *hton = plugin_hton(plugin); + st_force_drop_table_params *param = (st_force_drop_table_params *)arg; + + /* + We have to ignore HEAP tables as these may not have been created yet + We also remove engines that is using discovery (as these will recrate + any missing .frm if needed) and tables marked with + HTON_AUTOMATIC_DELETE_TABLE as for these we can't check if the table + ever existed. + */ + if (!hton->discover_table && hton->db_type != DB_TYPE_HEAP && + !(hton->flags & HTON_AUTOMATIC_DELETE_TABLE)) + { + int error; + error= ha_delete_table(thd, hton, param->path, param->db, + param->alias, 0); + if (error > 0 && !non_existing_table_error(error)) + param->error= error; + if (error == 0) + { + param->error= 0; + return TRUE; // Table was deleted + } + } + return FALSE; +} + +/** + @brief + Traverse all plugins to delete table when .frm file is missing. + + @return -1 Table was not found in any engine + @return 0 Table was found in some engine and delete succeded + @return # Error from first engine that had a table but didn't succeed to + delete the table + @return HA_ERR_ROW_IS_REFERENCED if foreign key reference is encountered, + +*/ + +int ha_delete_table_force(THD *thd, const char *path, const LEX_CSTRING *db, + const LEX_CSTRING *alias) +{ + st_force_drop_table_params param; + Table_exists_error_handler no_such_table_handler; + DBUG_ENTER("ha_delete_table_force"); + + param.path= path; + param.db= db; + param.alias= alias; + param.error= -1; // Table not found + + thd->push_internal_handler(&no_such_table_handler); + if (plugin_foreach(thd, delete_table_force, MYSQL_STORAGE_ENGINE_PLUGIN, + ¶m)) + param.error= 0; // Delete succeded + thd->pop_internal_handler(); + DBUG_RETURN(param.error); +} + + /** Create a table in the engine: public interface. @@ -5615,43 +5780,6 @@ static my_bool discover_existence(THD *thd, plugin_ref plugin, return ht->discover_table_existence(ht, args->db, args->table_name); } -class Table_exists_error_handler : public Internal_error_handler -{ -public: - Table_exists_error_handler() - : m_handled_errors(0), m_unhandled_errors(0) - {} - - bool handle_condition(THD *thd, - uint sql_errno, - const char* sqlstate, - Sql_condition::enum_warning_level *level, - const char* msg, - Sql_condition ** cond_hdl) - { - *cond_hdl= NULL; - if (sql_errno == ER_NO_SUCH_TABLE || - sql_errno == ER_NO_SUCH_TABLE_IN_ENGINE || - sql_errno == ER_WRONG_OBJECT) - { - m_handled_errors++; - return TRUE; - } - - if (*level == Sql_condition::WARN_LEVEL_ERROR) - m_unhandled_errors++; - return FALSE; - } - - bool safely_trapped_errors() - { - return ((m_handled_errors > 0) && (m_unhandled_errors == 0)); - } - -private: - int m_handled_errors; - int m_unhandled_errors; -}; /** Check if a given table exists, without doing a full discover, if possible @@ -5722,7 +5850,7 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, if ((type= dd_frm_type(thd, path, &engine, is_sequence)) == TABLE_TYPE_UNKNOWN) - DBUG_RETURN(0); + DBUG_RETURN(true); // Frm exists if (type != TABLE_TYPE_VIEW) { @@ -5730,8 +5858,10 @@ bool ha_table_exists(THD *thd, const LEX_CSTRING *db, MYSQL_STORAGE_ENGINE_PLUGIN); *hton= p ? plugin_hton(p) : NULL; if (*hton) + { // verify that the table really exists exists= discover_existence(thd, p, &args); + } } else *hton= view_pseudo_hton; diff --git a/sql/handler.h b/sql/handler.h index f8482501b3ffe..11731ae374925 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1788,6 +1788,13 @@ handlerton *ha_default_tmp_handlerton(THD *thd); */ #define HTON_TRANSACTIONAL_AND_NON_TRANSACTIONAL (1 << 17) +/* + The engine doesn't keep track of tables, delete_table() is not + needed and delete_table() always returns 0 (table deleted). This flag + mainly used to skip storage engines in case of ha_delete_table_force() +*/ +#define HTON_AUTOMATIC_DELETE_TABLE (1 << 18) + class Ha_trx_info; struct THD_TRANS @@ -5106,7 +5113,11 @@ int ha_create_table(THD *thd, const char *path, const char *db, const char *table_name, HA_CREATE_INFO *create_info, LEX_CUSTRING *frm); int ha_delete_table(THD *thd, handlerton *db_type, const char *path, - const LEX_CSTRING *db, const LEX_CSTRING *alias, bool generate_warning); + const LEX_CSTRING *db, const LEX_CSTRING *alias, + bool generate_warning); +int ha_delete_table_force(THD *thd, const char *path, const LEX_CSTRING *db, + const LEX_CSTRING *alias); + void ha_prepare_for_backup(); void ha_end_backup(); void ha_pre_shutdown(); @@ -5295,4 +5306,5 @@ void print_keydup_error(TABLE *table, KEY *key, myf errflag); int del_global_index_stat(THD *thd, TABLE* table, KEY* key_info); int del_global_table_stat(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table); uint ha_count_rw_all(THD *thd, Ha_trx_info **ptr_ha_info); +bool non_existing_table_error(int error); #endif /* HANDLER_INCLUDED */ diff --git a/sql/log.cc b/sql/log.cc index 0182d41431e37..d5fcb853dc62b 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -1701,7 +1701,10 @@ int binlog_init(void *p) // recover needs to be set to make xa{commit,rollback}_handlerton effective binlog_hton->recover= binlog_xa_recover_dummy; } - binlog_hton->flags= HTON_NOT_USER_SELECTABLE | HTON_HIDDEN | HTON_NO_ROLLBACK; + binlog_hton->flags= (HTON_NOT_USER_SELECTABLE | + HTON_HIDDEN | + HTON_NO_ROLLBACK | + HTON_AUTOMATIC_DELETE_TABLE); return 0; } diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 05bef5f4bdae0..2569665fc5947 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -1107,7 +1107,7 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) LEX_CSTRING handler_name; handler *file= NULL; MEM_ROOT mem_root; - int error= TRUE; + int error= 1; char to_path[FN_REFLEN]; char from_path[FN_REFLEN]; handlerton *hton; @@ -1157,28 +1157,27 @@ static int execute_ddl_log_action(THD *thd, DDL_LOG_ENTRY *ddl_log_entry) { strxmov(to_path, ddl_log_entry->name, reg_ext, NullS); if (unlikely((error= mysql_file_delete(key_file_frm, to_path, - MYF(MY_WME))))) - { - if (my_errno != ENOENT) - break; - } + MYF(MY_WME | + MY_IGNORE_ENOENT))))) + break; #ifdef WITH_PARTITION_STORAGE_ENGINE strxmov(to_path, ddl_log_entry->name, PAR_EXT, NullS); - (void) mysql_file_delete(key_file_partition_ddl_log, to_path, MYF(MY_WME)); + (void) mysql_file_delete(key_file_partition_ddl_log, to_path, + MYF(0)); #endif } else { if (unlikely((error= file->ha_delete_table(ddl_log_entry->name)))) { - if (error != ENOENT && error != HA_ERR_NO_SUCH_TABLE) + if (!non_existing_table_error(error)) break; } } if ((deactivate_ddl_log_entry_no_lock(ddl_log_entry->entry_pos))) break; (void) sync_ddl_log_no_lock(); - error= FALSE; + error= 0; if (ddl_log_entry->action_type == DDL_LOG_DELETE_ACTION) break; } @@ -2308,11 +2307,14 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, for (table= tables; table; table= table->next_local) { - bool is_trans= 0; - bool table_creation_was_logged= 0; + bool is_trans= 0, frm_was_deleted= 0, temporary_table_was_dropped= 0; + bool table_creation_was_logged= 0, trigger_drop_executed= 0; + bool local_non_tmp_error= 0, frm_exists= 0, wrong_drop_sequence= 0; + bool drop_table_not_done= 0; LEX_CSTRING db= table->db; handlerton *table_type= 0; + error= 0; DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p", table->db.str, table->table_name.str, table->table, table->table ? table->table->s : NULL)); @@ -2327,36 +2329,42 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, thd->find_temporary_table(table) && table->mdl_request.ticket != NULL)); - if (table->open_type == OT_BASE_ONLY || !is_temporary_table(table) || - (drop_sequence && table->table->s->table_type != TABLE_TYPE_SEQUENCE)) - error= 1; - else + /* First try to delete temporary tables and temporary sequences */ + if ((table->open_type != OT_BASE_ONLY && is_temporary_table(table)) && + (!drop_sequence || table->table->s->table_type == TABLE_TYPE_SEQUENCE)) { table_creation_was_logged= table->table->s->table_creation_was_logged; if (thd->drop_temporary_table(table->table, &is_trans, true)) { + /* + This is a very unlikely scenaro as dropping a temporary table + should always work. Would be better if we tried to drop all + temporary tables before giving the error. + */ error= 1; goto err; } - error= 0; table->table= 0; + temporary_table_was_dropped= 1; } - if ((drop_temporary && if_exists) || !error) + if ((drop_temporary && if_exists) || temporary_table_was_dropped) { /* This handles the case of temporary tables. We have the following cases: - . "DROP TEMPORARY" was executed and a temporary table was affected - (i.e. drop_temporary && !error) or the if_exists was specified (i.e. - drop_temporary && if_exists). - - . "DROP" was executed but a temporary table was affected (.i.e - !error). + - "DROP TEMPORARY" was executed and table was dropped + temporary_table_was_dropped == 1 + - "DROP TEMPORARY IF EXISTS" was specified but no temporary table + existed + temporary_table_was_dropped == 0 */ if (!dont_log_query && table_creation_was_logged) { /* + DROP TEMPORARY succeded. For the moment when we only come + here on success (error == 0) + If there is an error, we don't know the type of the engine at this point. So, we keep it in the trx-cache. */ @@ -2387,7 +2395,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, is no need to proceed with the code that tries to drop a regular table. */ - if (!error) continue; + if (temporary_table_was_dropped) + continue; } else if (!drop_temporary) { @@ -2402,48 +2411,33 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, path_length= build_table_filename(path, sizeof(path) - 1, db.str, alias.str, reg_ext, 0); } + DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table"); error= 0; - if (drop_temporary || - (ha_table_exists(thd, &db, &alias, &table_type, &is_sequence) == 0 && - table_type == 0) || - (!drop_view && (was_view= (table_type == view_pseudo_hton))) || - (drop_sequence && !is_sequence)) + if (drop_temporary) + { + /* "DROP TEMPORARY" but a temporary table was not found */ + error= ENOENT; + } + else if (((frm_exists= ha_table_exists(thd, &db, &alias, &table_type, + &is_sequence)) == 0 && + table_type == 0) || + (!drop_view && (was_view= (table_type == view_pseudo_hton))) || + (drop_sequence && !is_sequence)) { /* One of the following cases happened: - . "DROP TEMPORARY" but a temporary table was not found. . "DROP" but table was not found . "DROP TABLE" statement, but it's a view. . "DROP SEQUENCE", but it's not a sequence */ - was_table= drop_sequence && table_type; - if (if_exists) - { - char buff[FN_REFLEN]; - int err= (drop_sequence ? ER_UNKNOWN_SEQUENCES : - ER_BAD_TABLE_ERROR); - String tbl_name(buff, sizeof(buff), system_charset_info); - tbl_name.length(0); - tbl_name.append(&db); - tbl_name.append('.'); - tbl_name.append(&table->table_name); - push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, - err, ER_THD(thd, err), - tbl_name.c_ptr_safe()); - - /* - Our job is done here. This statement was added to avoid executing - unnecessary code farther below which in some strange corner cases - caused the server to crash (see MDEV-17896). - */ - goto log_query; - } - else - { - non_tmp_error = (drop_temporary ? non_tmp_error : TRUE); - error= 1; - } + wrong_drop_sequence= drop_sequence && table_type; + was_table|= wrong_drop_sequence; + local_non_tmp_error= 1; + error= -1; + if ((!frm_exists && !table_type) || // no .frm + if_exists) + error= ENOENT; } else { @@ -2500,8 +2494,12 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, log_if_exists= 1; thd->replication_flags= 0; - if ((error= ha_delete_table(thd, table_type, path, &db, - &table->table_name, !dont_log_query))) + error= ha_delete_table(thd, table_type, path, &db, + &table->table_name, !dont_log_query); + + if (error < 0) // Table didn't exists + error= 0; + if (error) { if (thd->is_killed()) { @@ -2509,49 +2507,137 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, goto err; } } - else + + /* + Delete the .frm file if we managed to delete the table from the + engine or the table didn't exists in the engine + */ + if (likely(!error) || non_existing_table_error(error)) { /* Delete the table definition file */ strmov(end,reg_ext); if (table_type && table_type != view_pseudo_hton && - table_type->discover_table) + (table_type->discover_table || error)) { /* - Table type is using discovery and may not need a .frm file. + Table type is using discovery and may not need a .frm file + or the .frm file existed but no table in engine. Delete it silently if it exists */ - (void) mysql_file_delete(key_file_frm, path, MYF(0)); + if (mysql_file_delete(key_file_frm, path, + MYF(MY_WME | MY_IGNORE_ENOENT))) + error= my_errno; } else if (unlikely(mysql_file_delete(key_file_frm, path, - MYF(MY_WME)))) + !error ? MYF(MY_WME) : + MYF(MY_WME | MY_IGNORE_ENOENT)))) { frm_delete_error= my_errno; DBUG_ASSERT(frm_delete_error); } } + frm_was_deleted= 1; if (thd->replication_flags & OPTION_IF_EXISTS) log_if_exists= 1; - if (likely(!error)) + if (frm_delete_error) { - int trigger_drop_error= 0; + /* + Remember error if unexpected error from dropping the .frm file + or we got an error from ha_delete_table() + */ + if (frm_delete_error != ENOENT) + error= frm_delete_error; + else if (if_exists && ! error) + thd->clear_error(); + } + if (likely(!error) || !frm_delete_error) + non_tmp_table_deleted= TRUE; + + if (likely(!error) || non_existing_table_error(error)) + { + trigger_drop_executed= 1; + + if (Table_triggers_list::drop_all_triggers(thd, &db, + &table->table_name, + MYF(MY_WME | + MY_IGNORE_ENOENT))) + error= error ? error : -1; + } + local_non_tmp_error|= MY_TEST(error); + } + + /* + If there was no .frm file and the table is not temporary, + scan all engines try to drop the table from there. + This is to ensure we don't have any partial table files left. + + We check for trigger_drop_executed to ensure we don't again try + to drop triggers when it failed above (after sucecssfully dropping + the table). + */ + if (non_existing_table_error(error) && !drop_temporary && + table_type != view_pseudo_hton && !trigger_drop_executed && + !wrong_drop_sequence) + { + char *end; + int ferror= 0; + + /* Remove extension for delete */ + *(end = path + path_length - reg_ext_length) = '\0'; + ferror= ha_delete_table_force(thd, path, &db, &table->table_name); + if (!ferror) + { + /* Table existed and was deleted */ + non_tmp_table_deleted= TRUE; + local_non_tmp_error= 0; + error= 0; + } + if (ferror <= 0) + { + ferror= 0; // Ignore table not found - if (likely(!frm_delete_error)) + /* Delete the table definition file */ + if (!frm_was_deleted) { - non_tmp_table_deleted= TRUE; - trigger_drop_error= - Table_triggers_list::drop_all_triggers(thd, &db, - &table->table_name); + strmov(end, reg_ext); + if (mysql_file_delete(key_file_frm, path, + MYF(MY_WME | MY_IGNORE_ENOENT))) + ferror= my_errno; } - - if (unlikely(trigger_drop_error) || - (frm_delete_error && frm_delete_error != ENOENT)) - error= 1; - else if (frm_delete_error && if_exists) - thd->clear_error(); + if (Table_triggers_list::drop_all_triggers(thd, &db, + &table->table_name, + MYF(MY_WME | + MY_IGNORE_ENOENT))) + ferror= -1; } - non_tmp_error|= MY_TEST(error); + if (!error) + error= ferror; + } + + /* + Don't give an error if we are using IF EXISTS for a table that + didn't exists + */ + + if (if_exists && non_existing_table_error(error)) + { + char buff[FN_REFLEN]; + int err= (drop_sequence ? ER_UNKNOWN_SEQUENCES : + ER_BAD_TABLE_ERROR); + String tbl_name(buff, sizeof(buff), system_charset_info); + tbl_name.length(0); + tbl_name.append(&db); + tbl_name.append('.'); + tbl_name.append(&table->table_name); + push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE, + err, ER_THD(thd, err), + tbl_name.c_ptr_safe()); + error= 0; + local_non_tmp_error= 0; + drop_table_not_done= 1; } + non_tmp_error|= local_non_tmp_error; if (error) { @@ -2562,14 +2648,14 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(&table->table_name); errors++; } - else + else if (!drop_table_not_done) { - PSI_CALL_drop_table_share(false, table->db.str, (uint)table->db.length, + PSI_CALL_drop_table_share(temporary_table_was_dropped, + table->db.str, (uint)table->db.length, table->table_name.str, (uint)table->table_name.length); mysql_audit_drop_table(thd, table); } -log_query: if (!dont_log_query && !drop_temporary) { non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted); @@ -2727,9 +2813,10 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, } end: - DBUG_RETURN(error); + DBUG_RETURN(error || thd->is_error()); } + /** Log the drop of a table. @@ -2809,7 +2896,8 @@ bool quick_rm_table(THD *thd, handlerton *base, const LEX_CSTRING *db, delete file; } if (!(flags & (FRM_ONLY|NO_HA_TABLE))) - error|= ha_delete_table(thd, base, path, db, table_name, 0); + if (ha_delete_table(thd, base, path, db, table_name, 0) > 0) + error= 1; if (likely(error == 0)) { diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 0b2d2d8ca1c89..779faa96f8273 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -1029,10 +1029,10 @@ bool Trigger::add_to_file_list(void* param_arg) */ static bool rm_trigger_file(char *path, const LEX_CSTRING *db, - const LEX_CSTRING *table_name) + const LEX_CSTRING *table_name, myf MyFlags) { build_table_filename(path, FN_REFLEN-1, db->str, table_name->str, TRG_EXT, 0); - return mysql_file_delete(key_file_trg, path, MYF(MY_WME)); + return mysql_file_delete(key_file_trg, path, MyFlags); } @@ -1051,10 +1051,11 @@ static bool rm_trigger_file(char *path, const LEX_CSTRING *db, */ static bool rm_trigname_file(char *path, const LEX_CSTRING *db, - const LEX_CSTRING *trigger_name) + const LEX_CSTRING *trigger_name, myf MyFlags) { - build_table_filename(path, FN_REFLEN - 1, db->str, trigger_name->str, TRN_EXT, 0); - return mysql_file_delete(key_file_trn, path, MYF(MY_WME)); + build_table_filename(path, FN_REFLEN - 1, db->str, trigger_name->str, + TRN_EXT, 0); + return mysql_file_delete(key_file_trn, path, MyFlags); } @@ -1172,7 +1173,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, parse_file.cc functionality (because we will need it elsewhere). */ - if (rm_trigger_file(path, &tables->db, &tables->table_name)) + if (rm_trigger_file(path, &tables->db, &tables->table_name, MYF(MY_WME))) return 1; } else @@ -1181,7 +1182,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables, return 1; } - if (rm_trigname_file(path, &tables->db, sp_name)) + if (rm_trigname_file(path, &tables->db, sp_name, MYF(MY_WME))) return 1; delete trigger; @@ -1322,9 +1323,9 @@ bool Table_triggers_list::prepare_record_accessors(TABLE *table) This could be avoided if there is no triggers for UPDATE and DELETE. @retval - False success + False no triggers or triggers where correctly loaded @retval - True error + True error (wrong trigger file) */ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, @@ -1638,7 +1639,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const LEX_CSTRING *db, } error: - if (unlikely(!thd->is_error())) + if (unlikely(!thd->is_error())) { /* We don't care about this error message much because .TRG files will @@ -1815,7 +1816,8 @@ bool add_table_for_trigger(THD *thd, */ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, - const LEX_CSTRING *name) + const LEX_CSTRING *name, + myf MyFlags) { TABLE table; char path[FN_REFLEN]; @@ -1824,11 +1826,13 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, table.reset(); init_sql_alloc(key_memory_Table_trigger_dispatcher, - &table.mem_root, 8192, 0, MYF(0)); + &table.mem_root, 8192, 0, MYF(MY_WME)); if (Table_triggers_list::check_n_load(thd, db, name, &table, 1)) { result= 1; + /* We couldn't parse trigger file, best to just remove it */ + rm_trigger_file(path, db, name, MyFlags); goto end; } if (table.triggers) @@ -1848,7 +1852,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, Such triggers have zero-length name and are skipped here. */ if (trigger->name.length && - rm_trigname_file(path, db, &trigger->name)) + rm_trigname_file(path, db, &trigger->name, MyFlags)) { /* Instead of immediately bailing out with error if we were unable @@ -1862,7 +1866,7 @@ bool Table_triggers_list::drop_all_triggers(THD *thd, const LEX_CSTRING *db, } } } - if (rm_trigger_file(path, db, name)) + if (rm_trigger_file(path, db, name, MyFlags)) result= 1; delete table.triggers; } @@ -1923,9 +1927,10 @@ change_table_name_in_triggers(THD *thd, if (save_trigger_file(thd, new_db_name, new_table_name)) return TRUE; - if (rm_trigger_file(path_buff, old_db_name, old_table_name)) + if (rm_trigger_file(path_buff, old_db_name, old_table_name, MYF(MY_WME))) { - (void) rm_trigger_file(path_buff, new_db_name, new_table_name); + (void) rm_trigger_file(path_buff, new_db_name, new_table_name, + MYF(MY_WME)); return TRUE; } return FALSE; @@ -2034,9 +2039,11 @@ bool Trigger::change_on_table_name(void* param_arg) /* Remove stale .TRN file in case of database upgrade */ if (param->old_db_name) { - if (rm_trigname_file(trigname_buff, param->old_db_name, &name)) + if (rm_trigname_file(trigname_buff, param->old_db_name, &name, + MYF(MY_WME))) { - (void) rm_trigname_file(trigname_buff, param->new_db_name, &name); + (void) rm_trigname_file(trigname_buff, param->new_db_name, &name, + MYF(MY_WME)); return 1; } } diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index ae3d1738b1693..040d8eba98900 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -231,7 +231,7 @@ class Table_triggers_list: public Sql_alloc static bool check_n_load(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *table_name, TABLE *table, bool names_only); static bool drop_all_triggers(THD *thd, const LEX_CSTRING *db, - const LEX_CSTRING *table_name); + const LEX_CSTRING *table_name, myf MyFlags); static bool change_table_name(THD *thd, const LEX_CSTRING *db, const LEX_CSTRING *old_alias, const LEX_CSTRING *old_table, diff --git a/sql/temporary_tables.cc b/sql/temporary_tables.cc index 203571441fcc0..a8d8113945b4e 100644 --- a/sql/temporary_tables.cc +++ b/sql/temporary_tables.cc @@ -698,10 +698,10 @@ bool THD::rm_temporary_table(handlerton *base, const char *path) char frm_path[FN_REFLEN + 1]; strxnmov(frm_path, sizeof(frm_path) - 1, path, reg_ext, NullS); - if (mysql_file_delete(key_file_frm, frm_path, MYF(0))) - { + if (mysql_file_delete(key_file_frm, frm_path, + MYF(MY_WME | MY_IGNORE_ENOENT))) error= true; - } + file= get_new_handler((TABLE_SHARE*) 0, current_thd->mem_root, base); if (file && file->ha_delete_table(path)) { diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc index 15548350b2062..98589f1d043e9 100644 --- a/storage/blackhole/ha_blackhole.cc +++ b/storage/blackhole/ha_blackhole.cc @@ -399,7 +399,7 @@ static int blackhole_init(void *p) blackhole_hton= (handlerton *)p; blackhole_hton->db_type= DB_TYPE_BLACKHOLE_DB; blackhole_hton->create= blackhole_create_handler; - blackhole_hton->flags= HTON_CAN_RECREATE; + blackhole_hton->flags= HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE; mysql_mutex_init(bh_key_mutex_blackhole, &blackhole_mutex, MY_MUTEX_INIT_FAST); diff --git a/storage/blackhole/ha_blackhole.h b/storage/blackhole/ha_blackhole.h index 6ee30877b64b4..646fba6da9fe2 100644 --- a/storage/blackhole/ha_blackhole.h +++ b/storage/blackhole/ha_blackhole.h @@ -95,6 +95,10 @@ class ha_blackhole: public handler THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to, enum thr_lock_type lock_type); + int delete_table(const char *name) + { + return 0; + } private: virtual int write_row(const uchar *buf); virtual int update_row(const uchar *old_data, const uchar *new_data); diff --git a/storage/connect/ha_connect.cc b/storage/connect/ha_connect.cc index 0194b08c79251..b1b44085e5306 100644 --- a/storage/connect/ha_connect.cc +++ b/storage/connect/ha_connect.cc @@ -5192,7 +5192,8 @@ int ha_connect::delete_or_rename_table(const char *name, const char *to) } // endif pos } // endif open_table_def - + else + rc= ENOENT; free_table_share(share); } else // Temporary file ok= true; diff --git a/storage/connect/mysql-test/connect/r/drop-open-error.result b/storage/connect/mysql-test/connect/r/drop-open-error.result index f0ad8553d8be4..34f58a845dc5b 100644 --- a/storage/connect/mysql-test/connect/r/drop-open-error.result +++ b/storage/connect/mysql-test/connect/r/drop-open-error.result @@ -2,6 +2,8 @@ create table t1 (c varchar(8)); create table tcon engine=connect table_type=mysql CONNECTION='mysql://root@localhost/test/t1' SRCDEF='select c from t1 where c in ("foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar", "foo", "bar", "qux", "foobar")'; ERROR HY000: Too long value for 'SRCDEF' drop table mdev9949; +Warnings: +Warning 1017 Can't find file: './test/mdev9949.dos' (errno: 2 "No such file or directory") drop table t1; select @@secure_file_priv 'must be NULL'; must be NULL diff --git a/storage/federated/ha_federated.cc b/storage/federated/ha_federated.cc index 00168791d3564..b62b74d12bb83 100644 --- a/storage/federated/ha_federated.cc +++ b/storage/federated/ha_federated.cc @@ -484,7 +484,8 @@ int federated_db_init(void *p) federated_hton->commit= federated_commit; federated_hton->rollback= federated_rollback; federated_hton->create= federated_create_handler; - federated_hton->flags= HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION; + federated_hton->flags= (HTON_ALTER_NOT_SUPPORTED | HTON_NO_PARTITION | + HTON_AUTOMATIC_DELETE_TABLE); /* Support for transactions disabled until WL#2952 fixes it. diff --git a/storage/federated/ha_federated.h b/storage/federated/ha_federated.h index 080d0ebd5f066..2e785f878582e 100644 --- a/storage/federated/ha_federated.h +++ b/storage/federated/ha_federated.h @@ -244,7 +244,10 @@ class ha_federated: public handler void update_auto_increment(void); int repair(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt); - + int delete_table(const char *name) + { + return 0; + } int delete_all_rows(void); int truncate(); int create(const char *name, TABLE *form, diff --git a/storage/federatedx/ha_federatedx.cc b/storage/federatedx/ha_federatedx.cc index 6547964cc114c..2370473236e82 100644 --- a/storage/federatedx/ha_federatedx.cc +++ b/storage/federatedx/ha_federatedx.cc @@ -438,7 +438,8 @@ int federatedx_db_init(void *p) federatedx_hton->rollback= ha_federatedx::rollback; federatedx_hton->discover_table_structure= ha_federatedx::discover_assisted; federatedx_hton->create= federatedx_create_handler; - federatedx_hton->flags= HTON_ALTER_NOT_SUPPORTED; + federatedx_hton->flags= (HTON_ALTER_NOT_SUPPORTED | + HTON_AUTOMATIC_DELETE_TABLE); federatedx_hton->create_derived= create_federatedx_derived_handler; federatedx_hton->create_select= create_federatedx_select_handler; diff --git a/storage/federatedx/ha_federatedx.h b/storage/federatedx/ha_federatedx.h index a62456e1c33c4..67fe5f8cc2214 100644 --- a/storage/federatedx/ha_federatedx.h +++ b/storage/federatedx/ha_federatedx.h @@ -431,7 +431,10 @@ class ha_federatedx: public handler void update_auto_increment(void); int repair(THD* thd, HA_CHECK_OPT* check_opt); int optimize(THD* thd, HA_CHECK_OPT* check_opt); - + int delete_table(const char *name) + { + return 0; + } int delete_all_rows(void); int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info); //required diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index d5734ee1bb0df..00a226d59824b 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -13347,6 +13347,19 @@ ha_innobase::discard_or_import_tablespace( DBUG_RETURN(0); } +/** + @return 1 if frm file exists + @return 0 if it doesn't exists +*/ + +static bool frm_file_exists(const char *path) +{ + char buff[FN_REFLEN]; + strxnmov(buff, FN_REFLEN, path, reg_ext, NullS); + return !access(buff, F_OK); +} + + /** Drops a table from an InnoDB database. Before calling this function, MySQL calls innobase_commit to commit the transaction of the current user. @@ -13447,7 +13460,9 @@ inline int ha_innobase::delete_table(const char* name, enum_sql_command sqlcom) } } - if (err == DB_TABLE_NOT_FOUND) { + if (err == DB_TABLE_NOT_FOUND && + frm_file_exists(name)) + { /* Test to drop all tables which matches db/tablename + '#'. Only partitions can have '#' as non-first character in the table name! diff --git a/storage/mroonga/mrn_table.cpp b/storage/mroonga/mrn_table.cpp index b1b2db6161b38..037a6a594871f 100644 --- a/storage/mroonga/mrn_table.cpp +++ b/storage/mroonga/mrn_table.cpp @@ -1080,6 +1080,7 @@ TABLE_SHARE *mrn_create_tmp_table_share(TABLE_LIST *table_list, const char *path if (open_table_def(thd, share, GTS_TABLE)) { *error = ER_CANT_OPEN_FILE; + mrn_free_tmp_table_share(share); DBUG_RETURN(NULL); } DBUG_RETURN(share); diff --git a/storage/myisam/mi_delete_table.c b/storage/myisam/mi_delete_table.c index 7990c3e8a8031..d318b44720a6b 100644 --- a/storage/myisam/mi_delete_table.c +++ b/storage/myisam/mi_delete_table.c @@ -28,19 +28,23 @@ int mi_delete_table(const char *name) { + int error= 0; DBUG_ENTER("mi_delete_table"); #ifdef EXTRA_DEBUG check_table_is_closed(name,"delete"); #endif - if (mysql_file_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, MYF(MY_WME)) || - mysql_file_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, MYF(MY_WME))) - DBUG_RETURN(my_errno); + if (mysql_file_delete_with_symlink(mi_key_file_kfile, name, MI_NAME_IEXT, + MYF(MY_WME))) + error= my_errno; + if (mysql_file_delete_with_symlink(mi_key_file_dfile, name, MI_NAME_DEXT, + MYF(MY_WME))) + error= my_errno; // optionally present: mysql_file_delete_with_symlink(mi_key_file_dfile, name, ".OLD", MYF(0)); mysql_file_delete_with_symlink(mi_key_file_dfile, name, ".TMD", MYF(0)); - DBUG_RETURN(0); + DBUG_RETURN(error); } diff --git a/storage/perfschema/ha_perfschema.cc b/storage/perfschema/ha_perfschema.cc index 33d4c854c8b62..c4c59d109f538 100644 --- a/storage/perfschema/ha_perfschema.cc +++ b/storage/perfschema/ha_perfschema.cc @@ -95,10 +95,11 @@ static int pfs_init_func(void *p) pfs_hton->create= pfs_create_handler; pfs_hton->show_status= pfs_show_status; - pfs_hton->flags= HTON_ALTER_NOT_SUPPORTED | - HTON_TEMPORARY_NOT_SUPPORTED | - HTON_NO_PARTITION | - HTON_NO_BINLOG_ROW_OPT; + pfs_hton->flags= (HTON_ALTER_NOT_SUPPORTED | + HTON_TEMPORARY_NOT_SUPPORTED | + HTON_NO_PARTITION | + HTON_NO_BINLOG_ROW_OPT | + HTON_AUTOMATIC_DELETE_TABLE); /* As long as the server implementation keeps using legacy_db_type, diff --git a/storage/sequence/sequence.cc b/storage/sequence/sequence.cc index 8684a5c60b963..31522b8f3b717 100644 --- a/storage/sequence/sequence.cc +++ b/storage/sequence/sequence.cc @@ -69,10 +69,15 @@ class ha_seq: public handler /* open/close/locking */ int create(const char *name, TABLE *table_arg, - HA_CREATE_INFO *create_info) { return HA_ERR_WRONG_COMMAND; } + HA_CREATE_INFO *create_info) + { return HA_ERR_WRONG_COMMAND; } int open(const char *name, int mode, uint test_if_locked); int close(void); + int delete_table(const char *name) + { + return 0; + } THR_LOCK_DATA **store_lock(THD *, THR_LOCK_DATA **, enum thr_lock_type); /* table scan */ @@ -503,6 +508,7 @@ static int init(void *p) hton->savepoint_set= hton->savepoint_rollback= hton->savepoint_release= dummy_savepoint; hton->create_group_by= create_group_by_handler; + hton->flags= HTON_AUTOMATIC_DELETE_TABLE; return 0; } @@ -526,4 +532,3 @@ maria_declare_plugin(sequence) MariaDB_PLUGIN_MATURITY_STABLE } maria_declare_plugin_end; - diff --git a/storage/sphinx/ha_sphinx.cc b/storage/sphinx/ha_sphinx.cc index 8403c7677964c..d60a4d229e6bf 100644 --- a/storage/sphinx/ha_sphinx.cc +++ b/storage/sphinx/ha_sphinx.cc @@ -696,7 +696,7 @@ handlerton sphinx_hton = NULL, // create_cursor_read_view NULL, // set_cursor_read_view NULL, // close_cursor_read_view - HTON_CAN_RECREATE + HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE }; #else static handlerton * sphinx_hton_ptr = NULL; @@ -749,7 +749,7 @@ static int sphinx_init_func ( void * p ) hton->close_connection = sphinx_close_connection; hton->show_status = sphinx_show_status; hton->panic = sphinx_panic; - hton->flags = HTON_CAN_RECREATE; + hton->flags = HTON_CAN_RECREATE | HTON_AUTOMATIC_DELETE_TABLE; #endif } SPH_RET(0); diff --git a/storage/spider/spd_table.cc b/storage/spider/spd_table.cc index 1607dd079024c..583bfebbed6af 100644 --- a/storage/spider/spd_table.cc +++ b/storage/spider/spd_table.cc @@ -7249,7 +7249,7 @@ int spider_db_init( DBUG_ENTER("spider_db_init"); spider_hton_ptr = spider_hton; - spider_hton->flags = HTON_NO_FLAGS; + spider_hton->flags = HTON_NO_FLAGS | HTON_AUTOMATIC_DELETE_TABLE; #ifdef HTON_CAN_READ_CONNECT_STRING_IN_PARTITION spider_hton->flags |= HTON_CAN_READ_CONNECT_STRING_IN_PARTITION; #endif