diff options
author | unknown <pem@mysql.com> | 2005-09-26 18:22:00 +0200 |
---|---|---|
committer | unknown <pem@mysql.com> | 2005-09-26 18:22:00 +0200 |
commit | ad8ff14165ed656aee697b49eac6c7e8cb5a5c00 (patch) | |
tree | a751b9a10f86ec7538d34a5e7a81a973627b9de7 | |
parent | 4aa9a107413c3c614984f4c0bca2d63f4396041b (diff) | |
download | mariadb-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.result | 30 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 36 | ||||
-rw-r--r-- | sql/sp_head.cc | 4 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 13 | ||||
-rw-r--r-- | sql/sp_rcontext.h | 27 |
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; |