diff --git a/mysql-test/r/sp-bugs.result b/mysql-test/r/sp-bugs.result index 14c5311bbe5..38ddab52b8a 100644 --- a/mysql-test/r/sp-bugs.result +++ b/mysql-test/r/sp-bugs.result @@ -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 diff --git a/mysql-test/t/sp-bugs.test b/mysql-test/t/sp-bugs.test index 7b94e65a5e9..1eb283f7874 100644 --- a/mysql-test/t/sp-bugs.test +++ b/mysql-test/t/sp-bugs.test @@ -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 diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index ba0515d38ad..aafb25013f6 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -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);