mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +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). mysql-test/include/handler.inc: Add test case for side effect of Bug#30882 mysql-test/r/handler_innodb.result: Add test case result for side effect of Bug#30882 mysql-test/r/handler_myisam.result: Add test case result for side effect of Bug#30882 mysql-test/r/sp-error.result: Add test case result for Bug#30882 mysql-test/t/sp-error.test: Add test case for Bug#30882 sql/event_db_repository.cc: Update close_thread_tables call, no more default values. sql/mysql_priv.h: Remove implicit default parameters values of the close_thread_tables function as no callers are using it. sql/slave.cc: Update close_thread_tables call, no more default values sql/sp_head.cc: Update close_thread_tables call, no more default values sql/sql_base.cc: Changed the approach to distinguishing currently unused temporary tables. Now we ensure that such tables always have TABLE::query_id set to 0 and use this fact to perform checks during opening and dropping of temporary tables. This means that we have to call close_thread_tables() even for statements which use only temporary tables. To make this call cheaper, we re-factored close_thread_tables() to not take LOCK_open unless there are open base tables. sql/sql_handler.cc: Properly close temporary tables associated with a handler. sql/sql_insert.cc: close_temporary_table is now merged into drop_temporary_table. sql/sql_parse.cc: Now the condition doesn't cover all cases because close_thread_tables() must be called even for statements that use only temporary tables. sql/sql_table.cc: Use drop_temporary_table which perform checks to verify if the table is not being used. Error path problem is due to a handler tables issue and is going to be addressed in bug 31397. sql/table.h: Rename previously unused clear_query_id and document the usage of query_id and open_by_handler.
This commit is contained in:
@ -151,6 +151,14 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables)
|
||||
}
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
}
|
||||
else if (tables->table)
|
||||
{
|
||||
/* Must be a temporary table */
|
||||
TABLE *table= tables->table;
|
||||
table->file->ha_index_or_rnd_end();
|
||||
table->query_id= thd->query_id;
|
||||
table->open_by_handler= 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -282,6 +290,12 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/*
|
||||
If it's a temp table, don't reset table->query_id as the table is
|
||||
being used by this handler. Otherwise, no meaning at all.
|
||||
*/
|
||||
tables->table->open_by_handler= 1;
|
||||
|
||||
if (! reopen)
|
||||
send_ok(thd);
|
||||
DBUG_PRINT("exit",("OK"));
|
||||
|
Reference in New Issue
Block a user