Commit 624cf0e5 authored by pem@mysql.comhem.se's avatar pem@mysql.comhem.se

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.
parent 7c8213ea
...@@ -485,4 +485,13 @@ create procedure bug4344() drop procedure bug4344| ...@@ -485,4 +485,13 @@ create procedure bug4344() drop procedure bug4344|
ERROR HY000: Can't drop a PROCEDURE from within another stored routine ERROR HY000: Can't drop a PROCEDURE from within another stored routine
create procedure bug4344() drop function bug4344| create procedure bug4344() drop function bug4344|
ERROR HY000: Can't drop a FUNCTION from within another stored routine 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| drop table t1|
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# Make sure we don't have any procedures left. # Make sure we don't have any procedures left.
delete from mysql.proc; 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 function .f1() returns int return 1;
create procedure .p1() select 1, database(); create procedure .p1() select 1, database();
create procedure p1() select 2, database(); create procedure p1() select 2, database();
...@@ -650,6 +650,22 @@ create procedure bug4344() drop procedure bug4344| ...@@ -650,6 +650,22 @@ create procedure bug4344() drop procedure bug4344|
--error 1357 --error 1357
create procedure bug4344() drop function bug4344| 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| drop table t1|
......
...@@ -499,6 +499,7 @@ sp_head::execute(THD *thd) ...@@ -499,6 +499,7 @@ sp_head::execute(THD *thd)
ip= hip; ip= hip;
ret= 0; ret= 0;
ctx->clear_handler(); ctx->clear_handler();
ctx->in_handler= TRUE;
continue; continue;
} }
} }
...@@ -1586,19 +1587,40 @@ int ...@@ -1586,19 +1587,40 @@ int
sp_instr_hreturn::execute(THD *thd, uint *nextp) sp_instr_hreturn::execute(THD *thd, uint *nextp)
{ {
DBUG_ENTER("sp_instr_hreturn::execute"); DBUG_ENTER("sp_instr_hreturn::execute");
if (m_dest)
*nextp= m_dest;
else
{
thd->spcont->restore_variables(m_frame); thd->spcont->restore_variables(m_frame);
*nextp= thd->spcont->pop_hstack(); *nextp= thd->spcont->pop_hstack();
}
thd->spcont->in_handler= FALSE;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
void void
sp_instr_hreturn::print(String *str) sp_instr_hreturn::print(String *str)
{ {
str->reserve(12); str->reserve(16);
str->append("hreturn "); str->append("hreturn ");
str->qs_append(m_frame); 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 // sp_instr_cpush
// //
......
...@@ -677,7 +677,7 @@ private: ...@@ -677,7 +677,7 @@ private:
}; // class sp_instr_hpop : public sp_instr }; // 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 */ sp_instr_hreturn(const sp_instr_hreturn &); /* Prevent use of these */
void operator=(sp_instr_hreturn &); void operator=(sp_instr_hreturn &);
...@@ -685,7 +685,7 @@ class sp_instr_hreturn : public sp_instr ...@@ -685,7 +685,7 @@ class sp_instr_hreturn : public sp_instr
public: public:
sp_instr_hreturn(uint ip, sp_pcontext *ctx, uint fp) 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() virtual ~sp_instr_hreturn()
...@@ -695,11 +695,7 @@ public: ...@@ -695,11 +695,7 @@ public:
virtual void print(String *str); virtual void print(String *str);
virtual uint opt_mark(sp_head *sp) virtual uint opt_mark(sp_head *sp);
{
marked= 1;
return UINT_MAX;
}
private: private:
......
...@@ -32,6 +32,7 @@ sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax) ...@@ -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_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0),
m_hfound(-1), m_ccount(0) m_hfound(-1), m_ccount(0)
{ {
in_handler= FALSE;
m_frame= (Item **)sql_alloc(fsize * sizeof(Item*)); m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
m_outs= (int *)sql_alloc(fsize * sizeof(int)); m_outs= (int *)sql_alloc(fsize * sizeof(int));
m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t)); 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) ...@@ -58,6 +59,8 @@ sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type)
int int
sp_rcontext::find_handler(uint sql_errno) sp_rcontext::find_handler(uint sql_errno)
{ {
if (in_handler)
return 0; // Already executing a handler
if (m_hfound >= 0) if (m_hfound >= 0)
return 1; // Already got one return 1; // Already got one
......
...@@ -46,6 +46,8 @@ class sp_rcontext : public Sql_alloc ...@@ -46,6 +46,8 @@ class sp_rcontext : public Sql_alloc
public: public:
bool in_handler;
sp_rcontext(uint fsize, uint hmax, uint cmax); sp_rcontext(uint fsize, uint hmax, uint cmax);
~sp_rcontext() ~sp_rcontext()
......
...@@ -1599,13 +1599,17 @@ sp_decl: ...@@ -1599,13 +1599,17 @@ sp_decl:
sp_head *sp= lex->sphead; sp_head *sp= lex->sphead;
sp_pcontext *ctx= lex->spcont; sp_pcontext *ctx= lex->spcont;
sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */ sp_label_t *hlab= lex->spcont->pop_label(); /* After this hdlr */
sp_instr_hreturn *i;
if ($2 == SP_HANDLER_CONTINUE) 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 else
{ /* EXIT or UNDO handler, just jump to the end of the block */ { /* 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->add_instr(i);
sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */ sp->push_backpatch(i, lex->spcont->last_label()); /* Block end */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment