diff options
author | unknown <pem@mysql.comhem.se> | 2004-09-10 11:11:52 +0200 |
---|---|---|
committer | unknown <pem@mysql.comhem.se> | 2004-09-10 11:11:52 +0200 |
commit | 1912148cec19f4a20eddae9d0143124909872173 (patch) | |
tree | 177a307bee403859b893521b666bfd245cbef01f | |
parent | 862e78568e43272002dea1a12ff62e3d097be558 (diff) | |
download | mariadb-git-1912148cec19f4a20eddae9d0143124909872173.tar.gz |
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).
-rw-r--r-- | mysql-test/r/sp-error.result | 9 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 18 | ||||
-rw-r--r-- | sql/sp_head.cc | 28 | ||||
-rw-r--r-- | sql/sp_head.h | 10 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 3 | ||||
-rw-r--r-- | sql/sp_rcontext.h | 2 | ||||
-rw-r--r-- | 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 */ |