Commit e5caf6e5 authored by unknown's avatar unknown

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).
parent 3678fe2a
......@@ -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|
......@@ -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|
......
......@@ -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
//
......
......@@ -677,7 +677,7 @@ 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 */
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 @@ class sp_instr_hreturn : public sp_instr
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:
......
......@@ -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
......
......@@ -46,6 +46,8 @@ class sp_rcontext : public Sql_alloc
public:
bool in_handler;
sp_rcontext(uint fsize, uint hmax, uint cmax);
~sp_rcontext()
......
......@@ -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 */
......
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