Loading mysql-test/r/sp-error.result +48 −0 Original line number Diff line number Diff line Loading @@ -1579,3 +1579,51 @@ drop function f2; drop table t2; ERROR 42S02: Unknown table 't2' End of 5.1 tests drop procedure if exists proc_33983_a; drop procedure if exists proc_33983_b; drop procedure if exists proc_33983_c; drop procedure if exists proc_33983_d; create procedure proc_33983_a() begin label1: begin label2: begin select 1; end label1; end; end| ERROR 42000: End-label label1 without match create procedure proc_33983_b() begin label1: repeat label2: repeat select 1; until FALSE end repeat label1; until FALSE end repeat; end| ERROR 42000: End-label label1 without match create procedure proc_33983_c() begin label1: while TRUE do label2: while TRUE do select 1; end while label1; end while; end| ERROR 42000: End-label label1 without match create procedure proc_33983_d() begin label1: loop label2: loop select 1; end loop label1; end loop; end| ERROR 42000: End-label label1 without match mysql-test/r/sp.result +35 −0 Original line number Diff line number Diff line Loading @@ -6827,6 +6827,41 @@ SELECT @state, @exception; run NULL DROP TABLE t1; DROP PROCEDURE bug29770; use test; drop table if exists t_33618; drop procedure if exists proc_33618; create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); create procedure proc_33618(num int) begin declare count1 int default '0'; declare vb varchar(30); declare last_row int; while(num>=1) do set num=num-1; begin declare cur1 cursor for select `a` from t_33618; declare continue handler for not found set last_row = 1; set last_row:=0; open cur1; rep1: repeat begin declare exit handler for 1062 begin end; fetch cur1 into vb; if (last_row = 1) then leave rep1; end if; end; until last_row=1 end repeat; close cur1; end; end while; end// call proc_33618(20); drop table t_33618; drop procedure proc_33618; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ Loading mysql-test/t/sp-error.test +63 −0 Original line number Diff line number Diff line Loading @@ -2305,6 +2305,69 @@ drop table t2; --echo End of 5.1 tests # # Bug#33983 (Stored Procedures: wrong end <label> syntax is accepted) # --disable_warnings drop procedure if exists proc_33983_a; drop procedure if exists proc_33983_b; drop procedure if exists proc_33983_c; drop procedure if exists proc_33983_d; --enable_warnings delimiter |; --error ER_SP_LABEL_MISMATCH create procedure proc_33983_a() begin label1: begin label2: begin select 1; end label1; end; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_b() begin label1: repeat label2: repeat select 1; until FALSE end repeat label1; until FALSE end repeat; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_c() begin label1: while TRUE do label2: while TRUE do select 1; end while label1; end while; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_d() begin label1: loop label2: loop select 1; end loop label1; end loop; end| delimiter ;| # # BUG#NNNN: New bug synopsis # Loading mysql-test/t/sp.test +52 −0 Original line number Diff line number Diff line Loading @@ -7925,6 +7925,58 @@ SELECT @state, @exception; DROP TABLE t1; DROP PROCEDURE bug29770; # # Bug#33618 Crash in sp_rcontext # use test; --disable_warnings drop table if exists t_33618; drop procedure if exists proc_33618; --enable_warnings create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); delimiter //; create procedure proc_33618(num int) begin declare count1 int default '0'; declare vb varchar(30); declare last_row int; while(num>=1) do set num=num-1; begin declare cur1 cursor for select `a` from t_33618; declare continue handler for not found set last_row = 1; set last_row:=0; open cur1; rep1: repeat begin declare exit handler for 1062 begin end; fetch cur1 into vb; if (last_row = 1) then leave rep1; end if; end; until last_row=1 end repeat; close cur1; end; end while; end// delimiter ;// call proc_33618(20); drop table t_33618; drop procedure proc_33618; ########################################################################### --echo # ------------------------------------------------------------------ Loading sql/sql_yacc.yy +99 −17 Original line number Diff line number Diff line Loading @@ -1284,7 +1284,9 @@ END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt %type <NONE> sp_proc_stmt_statement sp_proc_stmt_return %type <NONE> sp_proc_stmt_if %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled %type <NONE> sp_labeled_block sp_unlabeled_block %type <NONE> sp_proc_stmt_leave %type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt Loading Loading @@ -1945,6 +1947,8 @@ ev_sql_stmt_inner: | sp_proc_stmt_return | sp_proc_stmt_if | case_stmt_specification | sp_labeled_block | sp_unlabeled_block | sp_labeled_control | sp_proc_stmt_unlabeled | sp_proc_stmt_leave Loading Loading @@ -2519,6 +2523,8 @@ sp_proc_stmt: | sp_proc_stmt_return | sp_proc_stmt_if | case_stmt_specification | sp_labeled_block | sp_unlabeled_block | sp_labeled_control | sp_proc_stmt_unlabeled | sp_proc_stmt_leave Loading Loading @@ -2645,14 +2651,35 @@ sp_proc_stmt_leave: sp_instr_jump *i; uint ip= sp->instructions(); uint n; /* When jumping to a BEGIN-END block end, the target jump points to the block hpop/cpop cleanup instructions, so we should exclude the block context here. When jumping to something else (i.e., SP_LAB_ITER), there are no hpop/cpop at the jump destination, so we should include the block context here for cleanup. */ bool exclusive= (lab->type == SP_LAB_BEGIN); n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_handlers(lab->ctx, exclusive); if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); if (hpop == NULL) MYSQL_YYABORT; sp->add_instr(hpop); } n= ctx->diff_cursors(lab->ctx, exclusive); if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); if (cpop == NULL) MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx); if (i == NULL) MYSQL_YYABORT; sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); } Loading Loading @@ -2680,10 +2707,20 @@ sp_proc_stmt_iterate: n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); if (hpop == NULL) MYSQL_YYABORT; sp->add_instr(hpop); } n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); if (cpop == NULL) MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ sp->add_instr(i); } Loading Loading @@ -2967,19 +3004,17 @@ sp_labeled_control: sp_unlabeled_control sp_opt_label { LEX *lex= Lex; sp_label_t *lab= lex->spcont->pop_label(); if ($5.str) { sp_label_t *lab= lex->spcont->find_label($5.str); if (!lab || my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); MYSQL_YYABORT; } } lex->sphead->backpatch(lex->spcont->pop_label()); lex->sphead->backpatch(lab); } ; Loading @@ -2988,15 +3023,59 @@ sp_opt_label: | label_ident { $$= $1; } ; sp_unlabeled_control: sp_labeled_block: label_ident ':' { LEX *lex= Lex; sp_pcontext *ctx= lex->spcont; sp_label_t *lab= ctx->find_label($1.str); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str); MYSQL_YYABORT; } lab= lex->spcont->push_label($1.str, lex->sphead->instructions()); lab->type= SP_LAB_BEGIN; } sp_block_content sp_opt_label { LEX *lex= Lex; sp_label_t *lab= lex->spcont->pop_label(); if ($5.str) { if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); MYSQL_YYABORT; } } } ; sp_unlabeled_block: { /* Unlabeled blocks get a secret label. */ LEX *lex= Lex; uint ip= lex->sphead->instructions(); sp_label_t *lab= lex->spcont->push_label((char *)"", ip); lab->type= SP_LAB_BEGIN; } sp_block_content { LEX *lex= Lex; lex->spcont->pop_label(); } ; sp_block_content: BEGIN_SYM { /* QQ This is just a dummy for grouping declarations and statements together. No [[NOT] ATOMIC] yet, and we need to figure out how make it coexist with the existing BEGIN COMMIT/ROLLBACK. */ LEX *lex= Lex; sp_label_t *lab= lex->spcont->last_label(); lab->type= SP_LAB_BEGIN; lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE); } sp_decls Loading @@ -3016,7 +3095,10 @@ sp_unlabeled_control: $3.curs)); lex->spcont= ctx->pop_context(); } | LOOP_SYM ; sp_unlabeled_control: LOOP_SYM sp_proc_stmts1 END LOOP_SYM { LEX *lex= Lex; Loading Loading
mysql-test/r/sp-error.result +48 −0 Original line number Diff line number Diff line Loading @@ -1579,3 +1579,51 @@ drop function f2; drop table t2; ERROR 42S02: Unknown table 't2' End of 5.1 tests drop procedure if exists proc_33983_a; drop procedure if exists proc_33983_b; drop procedure if exists proc_33983_c; drop procedure if exists proc_33983_d; create procedure proc_33983_a() begin label1: begin label2: begin select 1; end label1; end; end| ERROR 42000: End-label label1 without match create procedure proc_33983_b() begin label1: repeat label2: repeat select 1; until FALSE end repeat label1; until FALSE end repeat; end| ERROR 42000: End-label label1 without match create procedure proc_33983_c() begin label1: while TRUE do label2: while TRUE do select 1; end while label1; end while; end| ERROR 42000: End-label label1 without match create procedure proc_33983_d() begin label1: loop label2: loop select 1; end loop label1; end loop; end| ERROR 42000: End-label label1 without match
mysql-test/r/sp.result +35 −0 Original line number Diff line number Diff line Loading @@ -6827,6 +6827,41 @@ SELECT @state, @exception; run NULL DROP TABLE t1; DROP PROCEDURE bug29770; use test; drop table if exists t_33618; drop procedure if exists proc_33618; create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); create procedure proc_33618(num int) begin declare count1 int default '0'; declare vb varchar(30); declare last_row int; while(num>=1) do set num=num-1; begin declare cur1 cursor for select `a` from t_33618; declare continue handler for not found set last_row = 1; set last_row:=0; open cur1; rep1: repeat begin declare exit handler for 1062 begin end; fetch cur1 into vb; if (last_row = 1) then leave rep1; end if; end; until last_row=1 end repeat; close cur1; end; end while; end// call proc_33618(20); drop table t_33618; drop procedure proc_33618; # ------------------------------------------------------------------ # -- End of 5.0 tests # ------------------------------------------------------------------ Loading
mysql-test/t/sp-error.test +63 −0 Original line number Diff line number Diff line Loading @@ -2305,6 +2305,69 @@ drop table t2; --echo End of 5.1 tests # # Bug#33983 (Stored Procedures: wrong end <label> syntax is accepted) # --disable_warnings drop procedure if exists proc_33983_a; drop procedure if exists proc_33983_b; drop procedure if exists proc_33983_c; drop procedure if exists proc_33983_d; --enable_warnings delimiter |; --error ER_SP_LABEL_MISMATCH create procedure proc_33983_a() begin label1: begin label2: begin select 1; end label1; end; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_b() begin label1: repeat label2: repeat select 1; until FALSE end repeat label1; until FALSE end repeat; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_c() begin label1: while TRUE do label2: while TRUE do select 1; end while label1; end while; end| --error ER_SP_LABEL_MISMATCH create procedure proc_33983_d() begin label1: loop label2: loop select 1; end loop label1; end loop; end| delimiter ;| # # BUG#NNNN: New bug synopsis # Loading
mysql-test/t/sp.test +52 −0 Original line number Diff line number Diff line Loading @@ -7925,6 +7925,58 @@ SELECT @state, @exception; DROP TABLE t1; DROP PROCEDURE bug29770; # # Bug#33618 Crash in sp_rcontext # use test; --disable_warnings drop table if exists t_33618; drop procedure if exists proc_33618; --enable_warnings create table t_33618 (`a` int, unique(`a`), `b` varchar(30)) engine=myisam; insert into t_33618 (`a`,`b`) values (1,'1'),(2,'2'); delimiter //; create procedure proc_33618(num int) begin declare count1 int default '0'; declare vb varchar(30); declare last_row int; while(num>=1) do set num=num-1; begin declare cur1 cursor for select `a` from t_33618; declare continue handler for not found set last_row = 1; set last_row:=0; open cur1; rep1: repeat begin declare exit handler for 1062 begin end; fetch cur1 into vb; if (last_row = 1) then leave rep1; end if; end; until last_row=1 end repeat; close cur1; end; end while; end// delimiter ;// call proc_33618(20); drop table t_33618; drop procedure proc_33618; ########################################################################### --echo # ------------------------------------------------------------------ Loading
sql/sql_yacc.yy +99 −17 Original line number Diff line number Diff line Loading @@ -1284,7 +1284,9 @@ END_OF_INPUT %type <NONE> call sp_proc_stmts sp_proc_stmts1 sp_proc_stmt %type <NONE> sp_proc_stmt_statement sp_proc_stmt_return %type <NONE> sp_proc_stmt_if %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled sp_proc_stmt_leave %type <NONE> sp_labeled_control sp_proc_stmt_unlabeled %type <NONE> sp_labeled_block sp_unlabeled_block %type <NONE> sp_proc_stmt_leave %type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close %type <NONE> case_stmt_specification simple_case_stmt searched_case_stmt Loading Loading @@ -1945,6 +1947,8 @@ ev_sql_stmt_inner: | sp_proc_stmt_return | sp_proc_stmt_if | case_stmt_specification | sp_labeled_block | sp_unlabeled_block | sp_labeled_control | sp_proc_stmt_unlabeled | sp_proc_stmt_leave Loading Loading @@ -2519,6 +2523,8 @@ sp_proc_stmt: | sp_proc_stmt_return | sp_proc_stmt_if | case_stmt_specification | sp_labeled_block | sp_unlabeled_block | sp_labeled_control | sp_proc_stmt_unlabeled | sp_proc_stmt_leave Loading Loading @@ -2645,14 +2651,35 @@ sp_proc_stmt_leave: sp_instr_jump *i; uint ip= sp->instructions(); uint n; /* When jumping to a BEGIN-END block end, the target jump points to the block hpop/cpop cleanup instructions, so we should exclude the block context here. When jumping to something else (i.e., SP_LAB_ITER), there are no hpop/cpop at the jump destination, so we should include the block context here for cleanup. */ bool exclusive= (lab->type == SP_LAB_BEGIN); n= ctx->diff_handlers(lab->ctx, TRUE); /* Exclusive the dest. */ n= ctx->diff_handlers(lab->ctx, exclusive); if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); n= ctx->diff_cursors(lab->ctx, TRUE); /* Exclusive the dest. */ { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); if (hpop == NULL) MYSQL_YYABORT; sp->add_instr(hpop); } n= ctx->diff_cursors(lab->ctx, exclusive); if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); if (cpop == NULL) MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx); if (i == NULL) MYSQL_YYABORT; sp->push_backpatch(i, lab); /* Jumping forward */ sp->add_instr(i); } Loading Loading @@ -2680,10 +2707,20 @@ sp_proc_stmt_iterate: n= ctx->diff_handlers(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_hpop(ip++, ctx, n)); { sp_instr_hpop *hpop= new sp_instr_hpop(ip++, ctx, n); if (hpop == NULL) MYSQL_YYABORT; sp->add_instr(hpop); } n= ctx->diff_cursors(lab->ctx, FALSE); /* Inclusive the dest. */ if (n) sp->add_instr(new sp_instr_cpop(ip++, ctx, n)); { sp_instr_cpop *cpop= new sp_instr_cpop(ip++, ctx, n); if (cpop == NULL) MYSQL_YYABORT; sp->add_instr(cpop); } i= new sp_instr_jump(ip, ctx, lab->ip); /* Jump back */ sp->add_instr(i); } Loading Loading @@ -2967,19 +3004,17 @@ sp_labeled_control: sp_unlabeled_control sp_opt_label { LEX *lex= Lex; sp_label_t *lab= lex->spcont->pop_label(); if ($5.str) { sp_label_t *lab= lex->spcont->find_label($5.str); if (!lab || my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); MYSQL_YYABORT; } } lex->sphead->backpatch(lex->spcont->pop_label()); lex->sphead->backpatch(lab); } ; Loading @@ -2988,15 +3023,59 @@ sp_opt_label: | label_ident { $$= $1; } ; sp_unlabeled_control: sp_labeled_block: label_ident ':' { LEX *lex= Lex; sp_pcontext *ctx= lex->spcont; sp_label_t *lab= ctx->find_label($1.str); if (lab) { my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str); MYSQL_YYABORT; } lab= lex->spcont->push_label($1.str, lex->sphead->instructions()); lab->type= SP_LAB_BEGIN; } sp_block_content sp_opt_label { LEX *lex= Lex; sp_label_t *lab= lex->spcont->pop_label(); if ($5.str) { if (my_strcasecmp(system_charset_info, $5.str, lab->name) != 0) { my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str); MYSQL_YYABORT; } } } ; sp_unlabeled_block: { /* Unlabeled blocks get a secret label. */ LEX *lex= Lex; uint ip= lex->sphead->instructions(); sp_label_t *lab= lex->spcont->push_label((char *)"", ip); lab->type= SP_LAB_BEGIN; } sp_block_content { LEX *lex= Lex; lex->spcont->pop_label(); } ; sp_block_content: BEGIN_SYM { /* QQ This is just a dummy for grouping declarations and statements together. No [[NOT] ATOMIC] yet, and we need to figure out how make it coexist with the existing BEGIN COMMIT/ROLLBACK. */ LEX *lex= Lex; sp_label_t *lab= lex->spcont->last_label(); lab->type= SP_LAB_BEGIN; lex->spcont= lex->spcont->push_context(LABEL_DEFAULT_SCOPE); } sp_decls Loading @@ -3016,7 +3095,10 @@ sp_unlabeled_control: $3.curs)); lex->spcont= ctx->pop_context(); } | LOOP_SYM ; sp_unlabeled_control: LOOP_SYM sp_proc_stmts1 END LOOP_SYM { LEX *lex= Lex; Loading