summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <pem@mysql.com>2005-09-26 18:22:00 +0200
committerunknown <pem@mysql.com>2005-09-26 18:22:00 +0200
commitad8ff14165ed656aee697b49eac6c7e8cb5a5c00 (patch)
treea751b9a10f86ec7538d34a5e7a81a973627b9de7
parent4aa9a107413c3c614984f4c0bca2d63f4396041b (diff)
downloadmariadb-git-ad8ff14165ed656aee697b49eac6c7e8cb5a5c00.tar.gz
Fixed BUG#6127: Stored procedure handlers within handlers don't work
Replaced the dumb in-handler/not-in-handler check with a proper recursion check of handlers being executed. (Re-commit in a different tree, to make push possible.) mysql-test/r/sp.result: New test case for BUG#6127. mysql-test/t/sp.test: New test case for BUG#6127. sql/sp_head.cc: Replaced the setting of ctx->in_handler with a enter/exit handler methods. sql/sp_rcontext.cc: Replaced the boolean in_handler flag with a stack of handlers being exectuted, for proper recursion check. sql/sp_rcontext.h: Replaced the boolean in_handler flag with a stack of handlers being exectuted, for proper recursion check. (And added some comments in the sp_rcontext class.)
-rw-r--r--mysql-test/r/sp.result30
-rw-r--r--mysql-test/t/sp.test36
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sp_rcontext.cc13
-rw-r--r--sql/sp_rcontext.h27
5 files changed, 97 insertions, 13 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 82dda16933f..f9e6eae7e57 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -3360,4 +3360,34 @@ call bug12979_2()|
internal_var
NULL
drop procedure bug12979_2|
+drop table if exists t3|
+drop procedure if exists bug6127|
+create table t3 (s1 int unique)|
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+create procedure bug6127()
+begin
+declare continue handler for sqlstate '23000'
+ begin
+declare continue handler for sqlstate '22003'
+ insert into t3 values (0);
+insert into t3 values (1000000000000000);
+end;
+insert into t3 values (1);
+insert into t3 values (1);
+end|
+call bug6127()|
+select * from t3|
+s1
+0
+1
+call bug6127()|
+ERROR 23000: Duplicate entry '0' for key 1
+select * from t3|
+s1
+0
+1
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
drop table t1,t2;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index afcbd98277a..65d4f89e2bb 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -4229,6 +4229,42 @@ drop procedure bug12979_2|
#
+# BUG#6127: Stored procedure handlers within handlers don't work
+#
+--disable_warnings
+drop table if exists t3|
+drop procedure if exists bug6127|
+--enable_warnings
+create table t3 (s1 int unique)|
+
+set @sm=@@sql_mode|
+set sql_mode='traditional'|
+
+create procedure bug6127()
+begin
+ declare continue handler for sqlstate '23000'
+ begin
+ declare continue handler for sqlstate '22003'
+ insert into t3 values (0);
+
+ insert into t3 values (1000000000000000);
+ end;
+
+ insert into t3 values (1);
+ insert into t3 values (1);
+end|
+
+call bug6127()|
+select * from t3|
+--error ER_DUP_ENTRY
+call bug6127()|
+select * from t3|
+set sql_mode=@sm|
+drop table t3|
+drop procedure bug6127|
+
+
+#
# BUG#NNNN: New bug synopsis
#
#--disable_warnings
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 36a37924ea4..671acbc2a0c 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -1015,7 +1015,7 @@ int sp_head::execute(THD *thd)
ip= hip;
ret= 0;
ctx->clear_handler();
- ctx->in_handler= TRUE;
+ ctx->enter_handler(hip);
thd->clear_error();
thd->killed= THD::NOT_KILLED;
continue;
@@ -2378,7 +2378,7 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp)
thd->spcont->restore_variables(m_frame);
*nextp= thd->spcont->pop_hstack();
}
- thd->spcont->in_handler= FALSE;
+ thd->spcont->exit_handler();
DBUG_RETURN(0);
}
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index fcb7719aeb1..252bd7e5cab 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -31,12 +31,12 @@
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)
+ m_ihsp(0), m_hfound(-1), m_ccount(0)
{
- in_handler= FALSE;
m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
+ m_in_handler= (uint *)sql_alloc(hmax * sizeof(uint));
m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
m_saved.empty();
}
@@ -68,8 +68,6 @@ bool
sp_rcontext::find_handler(uint sql_errno,
MYSQL_ERROR::enum_warning_level level)
{
- if (in_handler)
- return 0; // Already executing a handler
if (m_hfound >= 0)
return 1; // Already got one
@@ -79,6 +77,13 @@ sp_rcontext::find_handler(uint sql_errno,
while (i--)
{
sp_cond_type_t *cond= m_handler[i].cond;
+ int j= m_ihsp;
+
+ while (j--)
+ if (m_in_handler[j] == m_handler[i].handler)
+ break;
+ if (j >= 0)
+ continue; // Already executing this handler
switch (cond->type)
{
diff --git a/sql/sp_rcontext.h b/sql/sp_rcontext.h
index 9c0fa88fe34..22fa4f6e865 100644
--- a/sql/sp_rcontext.h
+++ b/sql/sp_rcontext.h
@@ -58,7 +58,6 @@ class sp_rcontext : public Sql_alloc
public:
- bool in_handler;
/*
Arena used to (re) allocate items on . E.g. reallocate INOUT/OUT
SP parameters when they don't fit into prealloced items. This
@@ -169,6 +168,18 @@ class sp_rcontext : public Sql_alloc
return m_hstack[--m_hsp];
}
+ inline void
+ enter_handler(int hid)
+ {
+ m_in_handler[m_ihsp++]= hid;
+ }
+
+ inline void
+ exit_handler()
+ {
+ m_ihsp-= 1;
+ }
+
// Save variables starting at fp and up
void
save_variables(uint fp);
@@ -203,12 +214,14 @@ private:
Item *m_result; // For FUNCTIONs
- sp_handler_t *m_handler;
- uint m_hcount;
- uint *m_hstack;
- uint m_hsp;
- int m_hfound; // Set by find_handler; -1 if not found
- List<Item> m_saved; // Saved variables
+ sp_handler_t *m_handler; // Visible handlers
+ uint m_hcount; // Stack pointer for m_handler
+ uint *m_hstack; // Return stack for continue handlers
+ uint m_hsp; // Stack pointer for m_hstack
+ uint *m_in_handler; // Active handler, for recursion check
+ uint m_ihsp; // Stack pointer for m_in_handler
+ int m_hfound; // Set by find_handler; -1 if not found
+ List<Item> m_saved; // Saved variables during handler exec.
sp_cursor **m_cstack;
uint m_ccount;