maria-developers team mailing list archive
-
maria-developers team
-
Mailing list archive
-
Message #12279
Re: 250bc3b6d74: Ensure that table is truly dropped when using DROP TABLE
Hi, Michael!
On Jun 11, Michael Widenius wrote:
> revision-id: 250bc3b6d74 (mariadb-10.5.2-390-g250bc3b6d74)
> parent(s): ba2c2cfb20e
> author: Michael Widenius <michael.widenus@xxxxxxxxx>
> committer: Michael Widenius <michael.widenus@xxxxxxxxx>
> timestamp: 2020-06-11 11:33:55 +0300
> message:
>
> Ensure that table is truly dropped when using DROP TABLE
>
> MDEV-11412 AliSQL: [Feature] Issue#34 Support force drop table
please, put this line ^^^ first in the comment comment.
> The used code is largely based on code from Tencent
>
> The problem is that in some rare cases there may be a conflict between .frm
> files and the files in the storage engine. In this case the DROP TABLE
> was not able to properly drop the table.
>
> Some MariaDB/MySQL forks has solved this by adding a FORCE option to
TSQL? Or some other fork?
> DROP TABLE. After some discussion among MariaDB developers, we concluded
> that users expects that DROP TABLE should always work, even if the
> table would not be consistent. There should not be a need to use a
> separate keyword to ensure that the table is really deleted.
>
> The used solution is:
> - If a .frm table doesn't exists, try dropping the table from all storage
> engines.
> - If the .frm table exists but the table does not exist in the engine
> try dropping the table from all storage engines.
I don't see why is that needed, if .frm exists, it tells exactly what
storage engine to use, there is no point in trying other engines.
> - Update storage engines using many table files (.CVS, MyISAM, Aria) to
> succeed with the drop even if some of the files are missing.
> - Add HTON_AUTOMATIC_DELETE_TABLE to handlerton's where delete_table()
> is not needed and always succeed. This is used by ha_delete_table_force()
> to know which handlers to ignore when trying to drop a table without
> a .frm file.
>
> The disadvantage of this solution is that a DROP TABLE on a non existing
> table will be a bit slower as we have to ask all active storage engines
> if they know anything about the table.
>
> Other things:
> - Added a new flag MY_IGNORE_ENOENT to my_delete() to not give an error
> if the file doesn't exist. This simplifies some of the code.
> - Don't clear thd->error in ha_delete_table() if there was an active
> error. This is a bug fix.
> - handler::delete_table() will not abort if first file doesn't exists.
> This is bug fix to handle the case when a drop table was aborted in
> the middle.
> - Cleaned up mysql_rm_table_no_locks() to ensure that if_exists uses
> same code path as when it's not used.
> - Use non_existing_Table_error() to detect if table didn't exists.
> Old code used different errors tests in different position.
> - Table_triggers_list::drop_all_triggers() now drops trigger file if
> it can't be parsed instead of leaving it hanging around (bug fix)
> - InnoDB doesn't anymore print error about .frm file out of sync with
> InnoDB directory if .frm file does not exists. This change was required
> to be able to try to drop an InnoDB file when .frm doesn't exists.
> - Fixed bug in mi_delete_table() where the .MYD file would not be dropped
> if the .MYI file didn't exists.
> - Fixed memory leak in Mroonga when deleting non existing table
> - Fixed memory leak in Connect when deleting non existing table
>
> Bugs fixed introduced by the original version of this commit:
> MDEV-22826 Presence of Spider prevents tables from being force-deleted from
> other engines
I don't think this part of the comment makes any sense, when one looks
through git history there is no "original version of this commit".
It's like a rolled back transaction, that value did not exist, unless
you use READ UNCOMMITTED :)
> diff --git a/mysql-test/main/drop_table_force.test b/mysql-test/main/drop_table_force.test
> new file mode 100644
> index 00000000000..8fdd79465b7
> --- /dev/null
> +++ b/mysql-test/main/drop_table_force.test
> @@ -0,1 +1,197 @@
> +--source include/have_log_bin.inc
> +--source include/have_innodb.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");
not sure it's a good idea, error numbers aren't very portable, this will
blow up some day like a time bomb
> +
> +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;
why with grant option?
better remove it if it's not essential for drop to work.
if it is essential, why is it?
> +
> +# 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;
aha, so it works! :)
> +
> +# 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;
you've just tested it in Test7, haven't you?
> +
> +--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 froeign key references
typo "foreign"
> +--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;
may be csv and archive tests too?
> diff --git a/sql/handler.cc b/sql/handler.cc
> index 1af0157783e..5dd02d057c7 100644
> --- a/sql/handler.cc
> +++ b/sql/handler.cc
> @@ -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);
"Table didn't exists, no error given"?
if get_new_handler() fails it's OOM.
>
> bzero((char*) &dummy_table, sizeof(dummy_table));
> bzero((char*) &dummy_share, sizeof(dummy_share));
> @@ -2723,8 +2769,10 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
> }
> if (intercept)
> {
> + /* Clear error if we got it in this function */
> + if (!is_error)
> thd->clear_error();
this is generally a wrong approach. One should use push_internal_handler
to silence errors, not thd->is_error() or thd->clear_error().
In this particilar case there will be no errors if there was no error
before ha_delete_table() - which is correct. But if there was an error
before, this will leave spurious and confusing errors in `SHOW WARNINGS`
output.
> - error= 0;
> + error= -1;
> }
> }
> delete file;
> @@ -4365,45 +4413,63 @@ 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. If this exist and we can't delete
> + that one we will abort the delete.
after "the most important one" you can add "(see the comment near
handlerton::tablefile_extensions)"
> + If the first one doesn't exists, we have to try to delete all other
"doesn't exist"
> + 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
> +
> @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
why would that be ok?
> 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++)
> {
> + int error;
> - if (mysql_file_delete_with_symlink(key_file_misc, name, *ext, 0))
> + if ((error= mysql_file_delete_with_symlink(key_file_misc, name, *ext,
> + MYF(0))))
why do you need this `error` variable, if you never use it?
> {
> 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);
> }
>
>
> @@ -4439,5 +4505,20 @@ 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);
> +}
this should, I believe, be inline in handler.h
> +
> +
> +/**
> Performs checks upon the table.
>
> @@ -4899,5 +4981,89 @@ 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;
> + bool generate_warning;
> + 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, param->generate_warning);
This is doing a a lot of extra work. dummy_table/dummy_share, if()s.
Allocating and constructing new handlers.
I suggest the following:
1. Introduce new handlerton method hton->drop_table().
By default it'll be
hton->get_new_handler()
get_canonical_filename()
file->ha_delete_table()
like now, so all engines will still work. But later we can start
moving drop table functionality out of the handler. In this commit
only engines like blackhole will have a dummy drop_table() method.
2. Here you can do, basically
hton->drop_table(hton, param->path)
without checking for discovery, without a new flag
HTON_AUTOMATIC_DELETE_TABLE. I'm not sure why you check for
DB_TYPE_HEAP, could you please explain that?
> + 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, bool generate_warning)
> +{
> + 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.generate_warning= generate_warning;
this is never used, you always invoke ha_delete_table_force() with
generate_warning=0.
> + 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.
>
> diff --git a/sql/handler.h b/sql/handler.h
> index f592c635c5d..f5ccdbe1ee4 100644
> --- a/sql/handler.h
> +++ b/sql/handler.h
> @@ -1780,6 +1780,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
> diff --git a/sql/sql_table.cc b/sql/sql_table.cc
> index 61b1113f680..7c79acef3ea 100644
> --- a/sql/sql_table.cc
> +++ b/sql/sql_table.cc
> @@ -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));
>
> + /* 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))
> - error= 1;
> - else
> + if ((table->open_type != OT_BASE_ONLY && is_temporary_table(table)) &&
unnecessary parentheses
> + (!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)
DBUG_ASSERT(error == 0) please
> +
> 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)
can temporary_table_was_dropped be false here?
> + 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 &&
> + 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 &&
this is an overkill. ha_table_exists() will do a full table discovery,
you don't need it here, because you'll try to delete anyway.
So, basically you only need dd_frm_type() here.
> 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
> {
> @@ -2509,49 +2507,138 @@ 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))
I don't think this new drop table logic needs to have any special
handling of discovery. If the table didn't exist in engine - it's the
normal case now, discovery or not, it's be handled normally.
> {
> /*
> - 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();
no, please, don't do thd->clear_error().
I've seen and fixed so many bugs because of that. The last one - just an
hour ago. Use push_internal_handler() instead.
> + }
> + if (likely(!error) || !frm_delete_error)
> + non_tmp_table_deleted= TRUE;
>
> - if (likely(!frm_delete_error))
> + 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, 0);
> + if (!ferror)
> + {
> + /* Table existed and was deleted */
> non_tmp_table_deleted= TRUE;
> - trigger_drop_error=
> - Table_triggers_list::drop_all_triggers(thd, &db,
> - &table->table_name);
> + local_non_tmp_error= 0;
> + error= 0;
> }
> + if (ferror <= 0)
> + {
> + ferror= 0; // Ignore table not found
>
> - if (unlikely(trigger_drop_error) ||
> - (frm_delete_error && frm_delete_error != ENOENT))
> - error= 1;
> - else if (frm_delete_error && if_exists)
> - thd->clear_error();
> + /* Delete the table definition file */
> + if (!frm_was_deleted)
> + {
> + strmov(end, reg_ext);
> + if (mysql_file_delete(key_file_frm, path,
> + MYF(MY_WME | MY_IGNORE_ENOENT)))
> + ferror= my_errno;
> }
> - non_tmp_error|= MY_TEST(error);
> + if (Table_triggers_list::drop_all_triggers(thd, &db,
> + &table->table_name,
> + MYF(MY_WME |
> + MY_IGNORE_ENOENT)))
> + ferror= -1;
Why do you need two copies of code to drop triggers?
Why cannot you do it once, on the first drop_all_triggers() place?
> }
> + 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)
> {
> diff --git a/storage/blackhole/ha_blackhole.cc b/storage/blackhole/ha_blackhole.cc
> index 15548350b20..98589f1d043 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 6ee30877b64..646fba6da9f 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 0194b08c792..b1b44085e53 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 f0ad8553d8b..34f58a845dc 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 00168791d35..b62b74d12bb 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 080d0ebd5f0..2e785f87858 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 6547964cc11..2370473236e 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 a62456e1c33..67fe5f8cc22 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 6940f8ff3bd..97cfdb01d9f 100644
> --- a/storage/innobase/handler/ha_innodb.cc
> +++ b/storage/innobase/handler/ha_innodb.cc
> @@ -13347,5 +13347,18 @@ ha_innobase::discard_or_import_tablespace(
> }
>
> /**
> + @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.
> @@ -13446,7 +13459,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 b1b2db6161b..037a6a59487 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 7990c3e8a80..d318b44720a 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 33d4c854c8b..c4c59d109f5 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 |
> + pfs_hton->flags= (HTON_ALTER_NOT_SUPPORTED |
> HTON_TEMPORARY_NOT_SUPPORTED |
> HTON_NO_PARTITION |
> - HTON_NO_BINLOG_ROW_OPT;
> + 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 8684a5c60b9..31522b8f3b7 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 8403c767796..d60a4d229e6 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 1607dd07902..583bfebbed6 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
Regards,
Sergei
VP of MariaDB Server Engineering
and security@xxxxxxxxxxx
Follow ups