mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
Make error messages from DROP TABLE and DROP TABLE IF EXISTS consistent
- IF EXISTS ends with a list of all not existing object, instead of a separate note for every not existing object - Produce a "Note" for all wrongly dropped objects (like trying to do DROP SEQUENCE for a normal table) - Do not write existing tables that could not be dropped to binlog Other things: MDEV-22820 Bogus "Unknown table" warnings produced upon attempt to drop parent table referenced by FK This was caused by an older version of this commit patch and later fixed
This commit is contained in:
161
sql/sql_table.cc
161
sql/sql_table.cc
@ -2236,11 +2236,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
bool dont_free_locks)
|
||||
{
|
||||
TABLE_LIST *table;
|
||||
char path[FN_REFLEN + 1], wrong_tables_buff[160];
|
||||
char path[FN_REFLEN + 1], unknown_tables_buff[160];
|
||||
LEX_CSTRING alias= null_clex_str;
|
||||
String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1,
|
||||
String unknown_tables(unknown_tables_buff, sizeof(unknown_tables_buff)-1,
|
||||
system_charset_info);
|
||||
uint path_length= 0, errors= 0;
|
||||
uint not_found_errors= 0;
|
||||
int error= 0;
|
||||
int non_temp_tables_count= 0;
|
||||
bool non_tmp_error= 0;
|
||||
@ -2253,7 +2253,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
String built_trans_tmp_query, built_non_trans_tmp_query;
|
||||
DBUG_ENTER("mysql_rm_table_no_locks");
|
||||
|
||||
wrong_tables.length(0);
|
||||
unknown_tables.length(0);
|
||||
/*
|
||||
Prepares the drop statements that will be written into the binary
|
||||
log as follows:
|
||||
@ -2310,9 +2310,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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;
|
||||
bool table_dropped= 0;
|
||||
LEX_CSTRING db= table->db;
|
||||
handlerton *table_type= 0;
|
||||
size_t path_length= 0;
|
||||
char *path_end= 0;
|
||||
|
||||
error= 0;
|
||||
DBUG_PRINT("table", ("table_l: '%s'.'%s' table: %p s: %p",
|
||||
@ -2410,6 +2412,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
/* remove .frm file and engine files */
|
||||
path_length= build_table_filename(path, sizeof(path) - 1, db.str,
|
||||
alias.str, reg_ext, 0);
|
||||
path_end= path + path_length - reg_ext_length;
|
||||
}
|
||||
|
||||
DEBUG_SYNC(thd, "rm_table_no_locks_before_delete_table");
|
||||
@ -2435,15 +2438,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
was_table|= wrong_drop_sequence;
|
||||
local_non_tmp_error= 1;
|
||||
error= -1;
|
||||
if ((!frm_exists && !table_type) || // no .frm
|
||||
if_exists)
|
||||
if ((!frm_exists && !table_type)) // no .frm
|
||||
error= ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
char *end;
|
||||
int frm_delete_error= 0;
|
||||
|
||||
#ifdef WITH_WSREP
|
||||
if (WSREP(thd) &&
|
||||
!wsrep_should_replicate_ddl(thd, table_type->db_type))
|
||||
@ -2487,7 +2486,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
MDL_EXCLUSIVE));
|
||||
|
||||
// Remove extension for delete
|
||||
*(end= path + path_length - reg_ext_length)= '\0';
|
||||
*path_end= '\0';
|
||||
|
||||
if (table_type && table_type != view_pseudo_hton &&
|
||||
table_type->flags & HTON_TABLE_MAY_NOT_EXIST_ON_SLAVE)
|
||||
@ -2497,9 +2496,11 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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 (!error)
|
||||
table_dropped= 1;
|
||||
else if (error < 0)
|
||||
error= 0; // Table didn't exists
|
||||
else if (error)
|
||||
{
|
||||
if (thd->is_killed())
|
||||
{
|
||||
@ -2507,15 +2508,20 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* This may be set by the storage engine in handler::delete_table() */
|
||||
if (thd->replication_flags & OPTION_IF_EXISTS)
|
||||
log_if_exists= 1;
|
||||
|
||||
/*
|
||||
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))
|
||||
strmov(path_end, reg_ext);
|
||||
if ((likely(!error) || non_existing_table_error(error)) &&
|
||||
!access(path, F_OK))
|
||||
{
|
||||
int frm_delete_error= 0;
|
||||
/* Delete the table definition file */
|
||||
strmov(end,reg_ext);
|
||||
if (table_type && table_type != view_pseudo_hton &&
|
||||
(table_type->discover_table || error))
|
||||
{
|
||||
@ -2526,7 +2532,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
*/
|
||||
if (mysql_file_delete(key_file_frm, path,
|
||||
MYF(MY_WME | MY_IGNORE_ENOENT)))
|
||||
error= my_errno;
|
||||
frm_delete_error= my_errno;
|
||||
}
|
||||
else if (unlikely(mysql_file_delete(key_file_frm, path,
|
||||
!error ? MYF(MY_WME) :
|
||||
@ -2535,25 +2541,19 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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;
|
||||
frm_was_deleted= 1; // We tried to delete .frm
|
||||
|
||||
if (frm_delete_error)
|
||||
{
|
||||
/*
|
||||
Remember error if unexpected error from dropping the .frm file
|
||||
or we got an error from ha_delete_table()
|
||||
*/
|
||||
if (frm_delete_error != ENOENT)
|
||||
if (frm_delete_error)
|
||||
{
|
||||
/* Remember unexpected error from dropping the .frm file */
|
||||
error= frm_delete_error;
|
||||
else if (if_exists && ! error)
|
||||
thd->clear_error();
|
||||
}
|
||||
else
|
||||
{
|
||||
error= 0; // We succeeded to delete the frm
|
||||
table_dropped= 1;
|
||||
}
|
||||
}
|
||||
if (likely(!error) || !frm_delete_error)
|
||||
non_tmp_table_deleted= TRUE;
|
||||
|
||||
if (likely(!error) || non_existing_table_error(error))
|
||||
{
|
||||
trigger_drop_executed= 1;
|
||||
@ -2580,17 +2580,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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';
|
||||
*path_end= '\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;
|
||||
table_dropped= 1;
|
||||
error= 0;
|
||||
}
|
||||
if (ferror <= 0)
|
||||
@ -2600,7 +2599,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
/* Delete the table definition file */
|
||||
if (!frm_was_deleted)
|
||||
{
|
||||
strmov(end, reg_ext);
|
||||
strmov(path_end, reg_ext);
|
||||
if (mysql_file_delete(key_file_frm, path,
|
||||
MYF(MY_WME | MY_IGNORE_ENOENT)))
|
||||
ferror= my_errno;
|
||||
@ -2615,50 +2614,67 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
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))
|
||||
if (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);
|
||||
uint is_note= (if_exists && (was_view || wrong_drop_sequence) ?
|
||||
ME_NOTE : 0);
|
||||
|
||||
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());
|
||||
|
||||
if (!non_existing_table_error(error) || is_note)
|
||||
{
|
||||
/*
|
||||
Error from engine already given. Here we only have to take
|
||||
care about errors for trying to drop view or sequence
|
||||
*/
|
||||
if (was_view)
|
||||
my_error(ER_IT_IS_A_VIEW, MYF(is_note), tbl_name.c_ptr_safe());
|
||||
else if (wrong_drop_sequence)
|
||||
my_error(ER_NOT_SEQUENCE2, MYF(is_note), tbl_name.c_ptr_safe());
|
||||
if (is_note)
|
||||
error= ENOENT;
|
||||
}
|
||||
else
|
||||
{
|
||||
not_found_errors++;
|
||||
if (unknown_tables.append(tbl_name) || unknown_tables.append(','))
|
||||
{
|
||||
error= 1;
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
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))
|
||||
{
|
||||
error= 0;
|
||||
local_non_tmp_error= 0;
|
||||
drop_table_not_done= 1;
|
||||
}
|
||||
|
||||
non_tmp_error|= local_non_tmp_error;
|
||||
|
||||
if (error)
|
||||
{
|
||||
if (wrong_tables.length())
|
||||
wrong_tables.append(',');
|
||||
wrong_tables.append(&db);
|
||||
wrong_tables.append('.');
|
||||
wrong_tables.append(&table->table_name);
|
||||
errors++;
|
||||
}
|
||||
else if (!drop_table_not_done)
|
||||
if (!error && table_dropped)
|
||||
{
|
||||
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);
|
||||
table->table_name.str,
|
||||
(uint)table->table_name.length);
|
||||
mysql_audit_drop_table(thd, table);
|
||||
}
|
||||
|
||||
if (!dont_log_query && !drop_temporary)
|
||||
if (!dont_log_query && !drop_temporary &&
|
||||
(!error || table_dropped || non_existing_table_error(error)))
|
||||
{
|
||||
non_tmp_table_deleted= (if_exists ? TRUE : non_tmp_table_deleted);
|
||||
non_tmp_table_deleted|= (if_exists || table_dropped);
|
||||
/*
|
||||
Don't write the database name if it is the current one (or if
|
||||
thd->db is NULL).
|
||||
@ -2678,20 +2694,16 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists,
|
||||
DEBUG_SYNC(thd, "rm_table_no_locks_before_binlog");
|
||||
thd->thread_specific_used= TRUE;
|
||||
error= 0;
|
||||
|
||||
err:
|
||||
if (wrong_tables.length())
|
||||
if (unknown_tables.length() > 1)
|
||||
{
|
||||
DBUG_ASSERT(errors);
|
||||
if (errors == 1 && was_view)
|
||||
my_error(ER_IT_IS_A_VIEW, MYF(0), wrong_tables.c_ptr_safe());
|
||||
else if (errors == 1 && drop_sequence && was_table)
|
||||
my_error(ER_NOT_SEQUENCE2, MYF(0), wrong_tables.c_ptr_safe());
|
||||
else if (errors > 1 || !thd->is_error())
|
||||
my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES :
|
||||
ER_BAD_TABLE_ERROR),
|
||||
MYF(0), wrong_tables.c_ptr_safe());
|
||||
error= 1;
|
||||
uint is_note= if_exists ? ME_NOTE : 0;
|
||||
unknown_tables.chop();
|
||||
my_error((drop_sequence ? ER_UNKNOWN_SEQUENCES : ER_BAD_TABLE_ERROR),
|
||||
MYF(is_note), unknown_tables.c_ptr_safe());
|
||||
}
|
||||
error= thd->is_error();
|
||||
|
||||
/*
|
||||
We are always logging drop of temporary tables.
|
||||
@ -5143,7 +5155,8 @@ int create_table_impl(THD *thd, const LEX_CSTRING &orig_db,
|
||||
If a table exists, it must have been pre-opened. Try looking for one
|
||||
in-use in THD::all_temp_tables list of TABLE_SHAREs.
|
||||
*/
|
||||
TABLE *tmp_table= thd->find_temporary_table(db.str, table_name.str);
|
||||
TABLE *tmp_table= thd->find_temporary_table(db.str, table_name.str,
|
||||
THD::TMP_TABLE_ANY);
|
||||
|
||||
if (tmp_table)
|
||||
{
|
||||
|
Reference in New Issue
Block a user