summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.comhem.se>2004-09-10 11:11:52 +0200
committerunknown <pem@mysql.comhem.se>2004-09-10 11:11:52 +0200
commit1912148cec19f4a20eddae9d0143124909872173 (patch)
tree177a307bee403859b893521b666bfd245cbef01f
parent862e78568e43272002dea1a12ff62e3d097be558 (diff)
downloadmariadb-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.result9
-rw-r--r--mysql-test/t/sp-error.test18
-rw-r--r--sql/sp_head.cc28
-rw-r--r--sql/sp_head.h10
-rw-r--r--sql/sp_rcontext.cc3
-rw-r--r--sql/sp_rcontext.h2
-rw-r--r--sql/sql_yacc.yy10
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 */