From 63fcccb1933ea2bc16773785410d956ace45b8c3 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Thu, 17 Nov 2005 03:51:14 +0300 Subject: [PATCH] Fix for bug #13399 Crash when executing PS/SP which should activate trigger which is now dropped" and bug #12329 "Bogus error msg when executing PS with stored procedure after SP was re-created". --- mysql-test/r/sp-error.result | 18 +++++++++++++++++ mysql-test/r/trigger.result | 25 +++++++++++++++++++++++ mysql-test/t/sp-error.test | 22 ++++++++++++++++++++ mysql-test/t/trigger.test | 39 ++++++++++++++++++++++++++++++++++++ sql/sp_head.cc | 21 ++++++++++--------- 5 files changed, 115 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 2f4b420a2ae..26bb0fa4694 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -975,6 +975,24 @@ return 1; END | drop table t1| drop function bug_13627_f| +drop function if exists bug12329; +create table t1 as select 1 a; +create table t2 as select 1 a; +create function bug12329() returns int return (select a from t1); +prepare stmt1 from 'select bug12329()'; +execute stmt1; +bug12329() +1 +drop function bug12329; +create function bug12329() returns int return (select a+100 from t2); +select bug12329(); +bug12329() +101 +execute stmt1; +ERROR HY000: Table 't2' was not locked with LOCK TABLES +deallocate prepare stmt1; +drop function bug12329; +drop table t1, t2; create database mysqltest1; use mysqltest1; drop database mysqltest1; diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index d3fbb56e493..af99dea58b9 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -738,3 +738,28 @@ f1 1 drop trigger t1_bi; drop tables t1, t2; +create table t1 (id int); +create table t2 (id int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +drop trigger t1_bi; +execute stmt1; +call p1(); +deallocate prepare stmt1; +drop procedure p1; +create table t3 (id int); +create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +drop trigger t1_bi; +create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id); +execute stmt1; +ERROR HY000: Table 't3' was not locked with LOCK TABLES +call p1(); +ERROR HY000: Table 't3' was not locked with LOCK TABLES +deallocate prepare stmt1; +drop procedure p1; +drop table t1, t2, t3; diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index f16562227f3..4cc141fea4b 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -1403,6 +1403,28 @@ drop function bug_13627_f| delimiter ;| +# BUG#12329: "Bogus error msg when executing PS with stored procedure after +# SP was re-created". See also test for related bug#13399 in trigger.test +--disable_warnings +drop function if exists bug12329; +--enable_warnings +create table t1 as select 1 a; +create table t2 as select 1 a; +create function bug12329() returns int return (select a from t1); +prepare stmt1 from 'select bug12329()'; +execute stmt1; +drop function bug12329; +create function bug12329() returns int return (select a+100 from t2); +select bug12329(); +# Until we implement proper mechanism for invalidation of PS/SP when table +# or SP's are changed the following statement will fail with 'Table ... was +# not locked' error (this mechanism should be based on the new TDC). +--error 1100 +execute stmt1; +deallocate prepare stmt1; +drop function bug12329; +drop table t1, t2; + # # Bug#13514 "server crash when create a stored procedure before choose a # database" and diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index cd79eb82ace..02d994128e2 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -875,3 +875,42 @@ drop function f1; drop view v1; drop table t1, t2, t3; --enable_parsing + +# +# Test for bug #13399 "Crash when executing PS/SP which should activate +# trigger which is now dropped". See also test for similar bug for stored +# routines in sp-error.test (#12329). +create table t1 (id int); +create table t2 (id int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +# Actually it is enough to do FLUSH TABLES instead of DROP TRIGGER +drop trigger t1_bi; +# Server should not crash on these two statements +execute stmt1; +call p1(); +deallocate prepare stmt1; +drop procedure p1; + +# Let us test more complex situation when we alter trigger in such way that +# it uses different set of tables (or simply add new trigger). +create table t3 (id int); +create trigger t1_bi after insert on t1 for each row insert into t2 values (new.id); +prepare stmt1 from "insert into t1 values (10)"; +create procedure p1() insert into t1 values (10); +call p1(); +# Altering trigger forcing it use different set of tables +drop trigger t1_bi; +create trigger t1_bi after insert on t1 for each row insert into t3 values (new.id); +# Until we implement proper mechanism for invalidation of PS/SP when table +# or SP's are changed these two statements will fail with 'Table ... was +# not locked' error (this mechanism should be based on the new TDC). +--error 1100 +execute stmt1; +--error 1100 +call p1(); +deallocate prepare stmt1; +drop procedure p1; +drop table t1, t2, t3; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index e3cdc909048..6248a60521b 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2906,33 +2906,34 @@ sp_head::add_used_tables_to_table_list(THD *thd, DBUG_ENTER("sp_head::add_used_tables_to_table_list"); /* - Use persistent arena for table list allocation to be PS friendly. + Use persistent arena for table list allocation to be PS/SP friendly. + Note that we also have to copy database/table names and alias to PS/SP + memory since current instance of sp_head object can pass away before + next execution of PS/SP for which tables are added to prelocking list. + This will be fixed by introducing of proper invalidation mechanism + once new TDC is ready. */ arena= thd->activate_stmt_arena_if_needed(&backup); for (i=0 ; i < m_sptabs.records ; i++) { - char *tab_buff; + char *tab_buff, *key_buff; TABLE_LIST *table; SP_TABLE *stab= (SP_TABLE *)hash_element(&m_sptabs, i); if (stab->temp) continue; if (!(tab_buff= (char *)thd->calloc(ALIGN_SIZE(sizeof(TABLE_LIST)) * - stab->lock_count))) + stab->lock_count)) || + !(key_buff= (char*)thd->memdup(stab->qname.str, + stab->qname.length + 1))) DBUG_RETURN(FALSE); for (uint j= 0; j < stab->lock_count; j++) { table= (TABLE_LIST *)tab_buff; - /* - It's enough to just copy the pointers as the data will not change - during the lifetime of the SP. If the SP is used by PS, we assume - that the PS will be invalidated if the functions is deleted or - changed. - */ - table->db= stab->qname.str; + table->db= key_buff; table->db_length= stab->db_length; table->table_name= table->db + table->db_length + 1; table->table_name_length= stab->table_name_length;