1
0
mirror of https://github.com/MariaDB/server.git synced 2025-08-31 22:22:30 +03:00

Bug#30882 Dropping a temporary table inside a stored function may cause a server crash

If a stored function that contains a drop temporary table statement
is invoked by a create temporary table of the same name may cause
a server crash. The problem is that when dropping a table no check
is done to ensure that table is not being used by some outer query
(or outer statement), potentially leaving the outer query with a
reference to a stale (freed) table.

The solution is when dropping a temporary table, always check if
the table is being used by some outer statement as a temporary
table can be dropped inside stored procedures.

The check is performed by looking at the TABLE::query_id value for
temporary tables. To simplify this check and to solve a bug related
to handling of temporary tables in prelocked mode, this patch changes
the way in which this member is used to track the fact that table is
used/unused. Now we ensure that TABLE::query_id is zero for unused
temporary tables (which means that all temporary tables which were
used by a statement should be marked as free for reuse after it's
execution has been completed).
This commit is contained in:
davi@endora.local
2007-11-01 18:52:56 -02:00
parent 6bd9f5c1cb
commit cc007acb78
15 changed files with 431 additions and 83 deletions

View File

@@ -1503,7 +1503,7 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
char path[FN_REFLEN], *alias;
uint path_length;
String wrong_tables;
int error;
int error= 0;
int non_temp_tables_count= 0;
bool some_tables_deleted=0, tmp_table_deleted=0, foreign_key_error=0;
String built_query;
@@ -1563,10 +1563,27 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
enum legacy_db_type frm_db_type;
mysql_ha_flush(thd, table, MYSQL_HA_CLOSE_FINAL, 1);
if (!close_temporary_table(thd, table))
{
tmp_table_deleted=1;
continue; // removed temporary table
error= drop_temporary_table(thd, table);
switch (error) {
case 0:
// removed temporary table
tmp_table_deleted= 1;
continue;
case -1:
// table already in use
/*
XXX: This branch should never be taken outside of SF, trigger or
prelocked mode.
DBUG_ASSERT(thd->in_sub_stmt);
*/
error= 1;
goto err_with_placeholders;
default:
// temporary table not found
error= 0;
}
/*
@@ -1593,7 +1610,6 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
built_query.append("`,");
}
error=0;
table_type= table->db_type;
if (!drop_temporary)
{