diff options
-rw-r--r-- | mysql-test/r/sp-error.result | 41 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 50 | ||||
-rw-r--r-- | sql/share/errmsg.txt | 3 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 37 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 10 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 36 |
6 files changed, 170 insertions, 7 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 42e45f67d33..b9d33bbe606 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -526,4 +526,45 @@ delete from t1| call bug7299()| ERROR 02000: No data to FETCH drop procedure bug7299| +create procedure bug9073() +begin +declare continue handler for sqlexception select 1; +declare continue handler for sqlexception select 2; +end| +ERROR 42000: Duplicate handler declared in the same block +create procedure bug9073() +begin +declare condname1 condition for 1234; +declare continue handler for condname1 select 1; +declare exit handler for condname1 select 2; +end| +ERROR 42000: Duplicate handler declared in the same block +create procedure bug9073() +begin +declare condname1 condition for sqlstate '42000'; +declare condname2 condition for sqlstate '42000'; +declare exit handler for condname1 select 1; +declare continue handler for condname2 select 2; +end| +ERROR 42000: Duplicate handler declared in the same block +create procedure bug9073() +begin +declare condname1 condition for sqlstate '42000'; +declare exit handler for condname1 select 1; +declare exit handler for sqlstate '42000' select 2; +end| +ERROR 42000: Duplicate handler declared in the same block +drop procedure if exists bug9073| +create procedure bug9073() +begin +declare condname1 condition for sqlstate '42000'; +declare continue handler for condname1 select 1; +begin +declare exit handler for sqlstate '42000' select 2; +begin +declare continue handler for sqlstate '42000' select 3; +end; +end; +end| +drop procedure bug9073| drop table t1| diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 90c776a8b88..a02d2ff6733 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -743,6 +743,56 @@ drop procedure bug7299| # +# BUG#9073: Able to declare two handlers for same condition in same scope +# +--error ER_SP_DUP_HANDLER +create procedure bug9073() +begin + declare continue handler for sqlexception select 1; + declare continue handler for sqlexception select 2; +end| +--error ER_SP_DUP_HANDLER +create procedure bug9073() +begin + declare condname1 condition for 1234; + declare continue handler for condname1 select 1; + declare exit handler for condname1 select 2; +end| +--error ER_SP_DUP_HANDLER +create procedure bug9073() +begin + declare condname1 condition for sqlstate '42000'; + declare condname2 condition for sqlstate '42000'; + declare exit handler for condname1 select 1; + declare continue handler for condname2 select 2; +end| +--error ER_SP_DUP_HANDLER +create procedure bug9073() +begin + declare condname1 condition for sqlstate '42000'; + declare exit handler for condname1 select 1; + declare exit handler for sqlstate '42000' select 2; +end| + +# This should still work. +--disable_warnings +drop procedure if exists bug9073| +--enable_warnings +create procedure bug9073() +begin + declare condname1 condition for sqlstate '42000'; + declare continue handler for condname1 select 1; + begin + declare exit handler for sqlstate '42000' select 2; + begin + declare continue handler for sqlstate '42000' select 3; + end; + end; +end| +drop procedure bug9073| + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 2ef2555753d..95fb1736741 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5338,4 +5338,5 @@ ER_WRONG_VALUE_FOR_TYPE eng "Incorrect %-.32s value: '%-.128s' for function %-.32s" ER_TABLE_DEF_CHANGED eng "Table definition has changed, please retry transaction" - +ER_SP_DUP_HANDLER 42000 + eng "Duplicate handler declared in the same block" diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 15d3f87ff29..26f576233f3 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -57,6 +57,7 @@ sp_pcontext::sp_pcontext(sp_pcontext *prev) VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cursor, sizeof(LEX_STRING), 16, 8)); + VOID(my_init_dynamic_array(&m_handler, sizeof(sp_cond_type_t *), 16, 8)); m_label.empty(); m_children.empty(); if (!prev) @@ -82,6 +83,7 @@ sp_pcontext::destroy() delete_dynamic(&m_pvar); delete_dynamic(&m_cond); delete_dynamic(&m_cursor); + delete_dynamic(&m_handler); } sp_pcontext * @@ -258,6 +260,41 @@ sp_pcontext::find_cond(LEX_STRING *name, my_bool scoped) return NULL; } +/* + * This only searches the current context, for error checking of + * duplicates. + * Returns TRUE if found. + */ +bool +sp_pcontext::find_handler(sp_cond_type_t *cond) +{ + uint i= m_handler.elements; + + while (i--) + { + sp_cond_type_t *p; + + get_dynamic(&m_handler, (gptr)&p, i); + if (cond->type == p->type) + { + switch (p->type) + { + case sp_cond_type_t::number: + if (cond->mysqlerr == p->mysqlerr) + return TRUE; + break; + case sp_cond_type_t::state: + if (strcmp(cond->sqlstate, p->sqlstate) == 0) + return TRUE; + break; + default: + return TRUE; + } + } + } + return FALSE; +} + void sp_pcontext::push_cursor(LEX_STRING *name) { diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 42d8140b78c..dbce191975a 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -241,6 +241,15 @@ class sp_pcontext : public Sql_alloc m_handlers+= 1; } + inline void + push_handler(sp_cond_type_t *cond) + { + insert_dynamic(&m_handler, (gptr)&cond); + } + + bool + find_handler(sp_cond_type *cond); + inline uint max_handlers() { @@ -293,6 +302,7 @@ private: DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_cond; // Conditions DYNAMIC_ARRAY m_cursor; // Cursors + DYNAMIC_ARRAY m_handler; // Handlers, for checking of duplicates List<sp_label_t> m_label; // The label list diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 9266ab69790..9ff7f4449b2 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1774,19 +1774,43 @@ sp_hcond_list: { LEX *lex= Lex; sp_head *sp= lex->sphead; - sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction(); + sp_pcontext *ctx= lex->spcont; - i->add_condition($1); - $$= 1; + if (ctx->find_handler($1)) + { + my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0)); + YYABORT; + } + else + { + sp_instr_hpush_jump *i= + (sp_instr_hpush_jump *)sp->last_instruction(); + + i->add_condition($1); + ctx->push_handler($1); + $$= 1; + } } | sp_hcond_list ',' sp_hcond { LEX *lex= Lex; sp_head *sp= lex->sphead; - sp_instr_hpush_jump *i= (sp_instr_hpush_jump *)sp->last_instruction(); + sp_pcontext *ctx= lex->spcont; - i->add_condition($3); - $$= $1 + 1; + if (ctx->find_handler($3)) + { + my_message(ER_SP_DUP_HANDLER, ER(ER_SP_DUP_HANDLER), MYF(0)); + YYABORT; + } + else + { + sp_instr_hpush_jump *i= + (sp_instr_hpush_jump *)sp->last_instruction(); + + i->add_condition($3); + ctx->push_handler($3); + $$= $1 + 1; + } } ; |