From 862e78568e43272002dea1a12ff62e3d097be558 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Sep 2004 10:29:08 +0400 Subject: [PATCH 1/2] Fixed --with-embedded builds. Added previously missing sql_trigger.cc file to embedded library. BitKeeper/etc/ignore: Added libmysqld/sql_trigger.cc to the ignore list libmysqld/Makefile.am: Added previously sql_trigger.cc file to embedded library. --- .bzrignore | 1 + libmysqld/Makefile.am | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.bzrignore b/.bzrignore index be7211af9e2..2ab7737922f 100644 --- a/.bzrignore +++ b/.bzrignore @@ -919,3 +919,4 @@ vio/test-ssl vio/test-sslclient vio/test-sslserver vio/viotest-ssl +libmysqld/sql_trigger.cc diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index f0cda9ae524..56762f5771e 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -59,7 +59,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ unireg.cc uniques.cc stacktrace.c sql_union.cc hash_filo.cc \ spatial.cc gstream.cc sql_help.cc tztime.cc protocol_cursor.cc \ sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \ - parse_file.cc sql_view.cc + parse_file.cc sql_view.cc sql_trigger.cc libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) libmysqld_a_SOURCES= From 1912148cec19f4a20eddae9d0143124909872173 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 10 Sep 2004 11:11:52 +0200 Subject: [PATCH 2/2] Fixed BUG#3294: Stored procedure crash if table dropped before use. Dropping the table was not the real problem, the problem was with errors occuring within error handlers. mysql-test/r/sp-error.result: New test case for BUG#3294. mysql-test/t/sp-error.test: New test case for BUG#3294. sql/sp_head.cc: Use hreturn instruction both for continue and exit handlers (a special case of a jump). sql/sp_head.h: Use hreturn instruction both for continue and exit handlers (a special case of a jump). sql/sp_rcontext.cc: Keep track on if we're in a handler already, for error handling. sql/sp_rcontext.h: Keep track on if we're in a handler already, for error handling. sql/sql_yacc.yy: Use hreturn instruction both for continue and exit handlers (a special case of a jump). --- mysql-test/r/sp-error.result | 9 +++++++++ mysql-test/t/sp-error.test | 18 +++++++++++++++++- sql/sp_head.cc | 28 +++++++++++++++++++++++++--- sql/sp_head.h | 10 +++------- sql/sp_rcontext.cc | 3 +++ sql/sp_rcontext.h | 2 ++ sql/sql_yacc.yy | 10 +++++++--- 7 files changed, 66 insertions(+), 14 deletions(-) diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 55c34ca471f..540a5652197 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -485,4 +485,13 @@ create procedure bug4344() drop procedure bug4344| ERROR HY000: Can't drop a PROCEDURE from within another stored routine create procedure bug4344() drop function bug4344| ERROR HY000: Can't drop a FUNCTION from within another stored routine +drop procedure if exists bug3294| +create procedure bug3294() +begin +declare continue handler for sqlexception drop table t5; +drop table t5; +end| +call bug3294()| +ERROR 42S02: Unknown table 't5' +drop procedure bug3294| drop table t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 32c146141b5..46700293578 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -5,7 +5,7 @@ # Make sure we don't have any procedures left. delete from mysql.proc; -# A test "global" procedures, i.e. not belonging to any database. +# A test of "global" procedures, i.e. not belonging to any database. create function .f1() returns int return 1; create procedure .p1() select 1, database(); create procedure p1() select 2, database(); @@ -650,6 +650,22 @@ create procedure bug4344() drop procedure bug4344| --error 1357 create procedure bug4344() drop function bug4344| +# +# BUG#3294: Stored procedure crash if table dropped before use +# (Actually, when an error occurs within an error handler.) +--disable_warnings +drop procedure if exists bug3294| +--enable_warnings +create procedure bug3294() +begin + declare continue handler for sqlexception drop table t5; + drop table t5; +end| + +--error 1051 +call bug3294()| +drop procedure bug3294| + drop table t1| diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 311b464b9c7..6e4269ad8a5 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -499,6 +499,7 @@ sp_head::execute(THD *thd) ip= hip; ret= 0; ctx->clear_handler(); + ctx->in_handler= TRUE; continue; } } @@ -1586,19 +1587,40 @@ int sp_instr_hreturn::execute(THD *thd, uint *nextp) { DBUG_ENTER("sp_instr_hreturn::execute"); - thd->spcont->restore_variables(m_frame); - *nextp= thd->spcont->pop_hstack(); + if (m_dest) + *nextp= m_dest; + else + { + thd->spcont->restore_variables(m_frame); + *nextp= thd->spcont->pop_hstack(); + } + thd->spcont->in_handler= FALSE; DBUG_RETURN(0); } void sp_instr_hreturn::print(String *str) { - str->reserve(12); + str->reserve(16); str->append("hreturn "); str->qs_append(m_frame); + if (m_dest) + str->qs_append(m_dest); } +uint +sp_instr_hreturn::opt_mark(sp_head *sp) +{ + if (m_dest) + return sp_instr_jump::opt_mark(sp); + else + { + marked= 1; + return UINT_MAX; + } +} + + // // sp_instr_cpush // diff --git a/sql/sp_head.h b/sql/sp_head.h index f4ed3760b94..9c308961aa4 100644 --- a/sql/sp_head.h +++ b/sql/sp_head.h @@ -677,7 +677,7 @@ private: }; // class sp_instr_hpop : public sp_instr -class sp_instr_hreturn : public sp_instr +class sp_instr_hreturn : public sp_instr_jump { sp_instr_hreturn(const sp_instr_hreturn &); /* Prevent use of these */ void operator=(sp_instr_hreturn &); @@ -685,7 +685,7 @@ class sp_instr_hreturn : public sp_instr public: sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp) - : sp_instr(ip, ctx), m_frame(fp) + : sp_instr_jump(ip, ctx), m_frame(fp) {} virtual ~sp_instr_hreturn() @@ -695,11 +695,7 @@ public: virtual void print(String *str); - virtual uint opt_mark(sp_head *sp) - { - marked= 1; - return UINT_MAX; - } + virtual uint opt_mark(sp_head *sp); private: diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index 7fa44f217f6..1bdd022470b 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -32,6 +32,7 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) : m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0), m_hfound(-1), m_ccount(0) { + in_handler= FALSE; m_frame= (Item **)sql_alloc(fsize * sizeof(Item*)); m_outs= (int *)sql_alloc(fsize * sizeof(int)); m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t)); @@ -58,6 +59,8 @@ sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type) int sp_rcontext::find_handler(uint sql_errno) { + if (in_handler) + return 0; // Already executing a handler if (m_hfound >= 0) return 1; // Already got one diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h index 15a2fe62138..f26b6760310 100644 --- a/sql/sp_rcontext.h +++ b/sql/sp_rcontext.h @@ -46,6 +46,8 @@ class sp_rcontext : public Sql_alloc public: + bool in_handler; + sp_rcontext(uint fsize, uint hmax, uint cmax); ~sp_rcontext() diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 8a5526a6b9f..8d1a668e98d 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1599,13 +1599,17 @@ sp_decl: sp_head *sp= lex->sphead; sp_pcontext *ctx= lex->spcont; sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */ + sp_instr_hreturn *i; if ($2 == SP_HANDLER_CONTINUE) - sp->add_instr(new sp_instr_hreturn(sp->instructions(), ctx, - ctx->current_pvars())); + { + i= new sp_instr_hreturn(sp->instructions(), ctx, + ctx->current_pvars()); + sp->add_instr(i); + } else { /* EXIT or UNDO handler, just jump to the end of the block */ - sp_instr_jump *i= new sp_instr_jump(sp->instructions(), ctx); + i= new sp_instr_hreturn(sp->instructions(), ctx, 0); sp->add_instr(i); sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */