mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 10:14:19 +01:00
Bug#50423: Crash on second call of a procedure dropping a trigger
The problem was that a DROP TRIGGER statement inside a stored procedure could cause a crash in subsequent invocations. This was due to the addition, on the first execution, of a temporary table reference to the stored procedure query table list. In a subsequent invocation, there would be a attempt to reinitialize the temporary table reference, which by then was already gone. The solution is to backup and reset the query table list each time a trigger needs to be dropped. This ensures that any temp changes to the query table list are discarded. It is safe to do so at this time as drop trigger is restricted from more complicated scenarios (ie, not allowed within stored functions, etc).
This commit is contained in:
parent
f89f6c3036
commit
d7797f51ec
3 changed files with 48 additions and 4 deletions
|
@ -44,4 +44,19 @@ SELECT f2 ();
|
|||
f2 ()
|
||||
NULL
|
||||
DROP SCHEMA testdb;
|
||||
USE test;
|
||||
#
|
||||
# Bug#50423: Crash on second call of a procedure dropping a trigger
|
||||
#
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
CREATE TABLE t1 (f1 INTEGER);
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @aux = 1;
|
||||
CREATE PROCEDURE p1 () DROP TRIGGER tr1;
|
||||
CALL p1 ();
|
||||
CALL p1 ();
|
||||
ERROR HY000: Trigger does not exist
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
End of 5.1 tests
|
||||
|
|
|
@ -57,5 +57,27 @@ SELECT f2 ();
|
|||
|
||||
DROP SCHEMA testdb;
|
||||
|
||||
USE test;
|
||||
|
||||
--echo #
|
||||
--echo # Bug#50423: Crash on second call of a procedure dropping a trigger
|
||||
--echo #
|
||||
|
||||
--disable_warnings
|
||||
DROP TABLE IF EXISTS t1;
|
||||
DROP TRIGGER IF EXISTS tr1;
|
||||
DROP PROCEDURE IF EXISTS p1;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (f1 INTEGER);
|
||||
CREATE TRIGGER tr1 BEFORE INSERT ON t1 FOR EACH ROW SET @aux = 1;
|
||||
CREATE PROCEDURE p1 () DROP TRIGGER tr1;
|
||||
|
||||
CALL p1 ();
|
||||
--error ER_TRG_DOES_NOT_EXIST
|
||||
CALL p1 ();
|
||||
|
||||
DROP TABLE t1;
|
||||
DROP PROCEDURE p1;
|
||||
|
||||
--echo End of 5.1 tests
|
||||
|
|
|
@ -327,6 +327,7 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||
TABLE *table;
|
||||
bool result= TRUE;
|
||||
String stmt_query;
|
||||
Query_tables_list backup;
|
||||
bool need_start_waiting= FALSE;
|
||||
|
||||
DBUG_ENTER("mysql_create_or_drop_trigger");
|
||||
|
@ -393,6 +394,12 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
|||
{
|
||||
bool if_exists= thd->lex->drop_if_exists;
|
||||
|
||||
/*
|
||||
Protect the query table list from the temporary and potentially
|
||||
destructive changes necessary to open the trigger's table.
|
||||
*/
|
||||
thd->lex->reset_n_backup_query_tables_list(&backup);
|
||||
|
||||
if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables))
|
||||
goto end;
|
||||
|
||||
|
@ -512,6 +519,10 @@ end:
|
|||
|
||||
VOID(pthread_mutex_unlock(&LOCK_open));
|
||||
|
||||
/* Restore the query table list. Used only for drop trigger. */
|
||||
if (!create)
|
||||
thd->lex->restore_backup_query_tables_list(&backup);
|
||||
|
||||
if (need_start_waiting)
|
||||
start_waiting_global_read_lock(thd);
|
||||
|
||||
|
@ -1625,10 +1636,6 @@ bool add_table_for_trigger(THD *thd,
|
|||
if (load_table_name_for_trigger(thd, trg_name, &trn_path, &tbl_name))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/* We need to reset statement table list to be PS/SP friendly. */
|
||||
lex->query_tables= 0;
|
||||
lex->query_tables_last= &lex->query_tables;
|
||||
|
||||
*table= sp_add_to_query_tables(thd, lex, trg_name->m_db.str,
|
||||
tbl_name.str, TL_IGNORE);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue