diff options
author | Sergei Golubchik <serg@mariadb.org> | 2015-06-16 17:27:53 +0200 |
---|---|---|
committer | Sergei Golubchik <serg@mariadb.org> | 2015-06-16 23:58:40 +0200 |
commit | b56ad494b47c19fef98101c224ed764664691b72 (patch) | |
tree | a1e0521666a552d8e2ff71324112e198b383c456 /sql/handler.cc | |
parent | 66fd45afce1ba5e1032c32cc891c09d64fa38d9e (diff) | |
download | mariadb-git-b56ad494b47c19fef98101c224ed764664691b72.tar.gz |
MDEV-8287 DROP TABLE suppresses all engine errors
in ha_delete_table()
* only convert ENOENT and HA_ERR_NO_SUCH_TABLE to warnings
* only return real error codes (that is, not ENOENT and
not HA_ERR_NO_SUCH_TABLE)
* intercept HA_ERR_ROW_IS_REFERENCED to generate backward
compatible ER_ROW_IS_REFERENCED
in mysql_rm_table_no_locks()
* no special code to handle HA_ERR_ROW_IS_REFERENCED
* no special code to handle ENOENT and HA_ERR_NO_SUCH_TABLE
* return multi-table error ER_BAD_TABLE_ERROR <table list> only
when there were many errors, not when there were many
tables to drop (but only one table generated an error)
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 85 |
1 files changed, 53 insertions, 32 deletions
diff --git a/sql/handler.cc b/sql/handler.cc index 70bce6f3963..1f8daf3927b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2298,9 +2298,11 @@ handle_condition(THD *, } -/** @brief - This should return ENOENT if the file doesn't exists. - The .frm file will be deleted only if we return 0 or ENOENT +/** delete a table in the engine + + @note + ENOENT and HA_ERR_NO_SUCH_TABLE are not considered errors. + The .frm file will be deleted only if we return 0. */ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, const char *db, const char *alias, bool generate_warning) @@ -2315,47 +2317,66 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, /* 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(HA_ERR_NO_SUCH_TABLE); + DBUG_RETURN(0); bzero((char*) &dummy_table, sizeof(dummy_table)); bzero((char*) &dummy_share, sizeof(dummy_share)); dummy_table.s= &dummy_share; path= get_canonical_filename(file, path, tmp_path); - if ((error= file->ha_delete_table(path)) && generate_warning) + if ((error= file->ha_delete_table(path))) { /* - Because file->print_error() use my_error() to generate the error message - we use an internal error handler to intercept it and store the text - in a temporary buffer. Later the message will be presented to user - as a warning. + it's not an error if the table doesn't exist in the engine. + warn the user, but still report DROP being a success */ - Ha_delete_table_error_handler ha_delete_table_error_handler; - - /* Fill up strucutures that print_error may need */ - dummy_share.path.str= (char*) path; - dummy_share.path.length= strlen(path); - dummy_share.normalized_path= dummy_share.path; - dummy_share.db.str= (char*) db; - dummy_share.db.length= strlen(db); - dummy_share.table_name.str= (char*) alias; - dummy_share.table_name.length= strlen(alias); - dummy_table.alias.set(alias, dummy_share.table_name.length, - table_alias_charset); + bool intercept= error == ENOENT || error == HA_ERR_NO_SUCH_TABLE; - file->change_table_ptr(&dummy_table, &dummy_share); - - thd->push_internal_handler(&ha_delete_table_error_handler); - file->print_error(error, 0); + if (!intercept || generate_warning) + { + /* + Because file->print_error() use my_error() to generate the error message + we use an internal error handler to intercept it and store the text + in a temporary buffer. Later the message will be presented to user + as a warning. + */ + Ha_delete_table_error_handler ha_delete_table_error_handler; + + /* Fill up strucutures that print_error may need */ + dummy_share.path.str= (char*) path; + dummy_share.path.length= strlen(path); + dummy_share.normalized_path= dummy_share.path; + dummy_share.db.str= (char*) db; + dummy_share.db.length= strlen(db); + dummy_share.table_name.str= (char*) alias; + dummy_share.table_name.length= strlen(alias); + dummy_table.alias.set(alias, dummy_share.table_name.length, + table_alias_charset); + + file->change_table_ptr(&dummy_table, &dummy_share); + +#if MYSQL_VERSION_ID > 100105 + // XXX as an ugly 10.0-only hack we intercept HA_ERR_ROW_IS_REFERENCED, + // to report it under the old historical error number. +#error remove HA_ERR_ROW_IS_REFERENCED, use ME_JUST_WARNING instead of a handler +#endif + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + thd->push_internal_handler(&ha_delete_table_error_handler); - thd->pop_internal_handler(); + file->print_error(error, 0); - /* - XXX: should we convert *all* errors to warnings here? - What if the error is fatal? - */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, - ha_delete_table_error_handler.buff); + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + { + thd->pop_internal_handler(); + if (error == HA_ERR_ROW_IS_REFERENCED) + my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); + else + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, + ha_delete_table_error_handler.buff); + } + } + if (intercept) + error= 0; } delete file; |