Commit ca242117 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10411 Providing compatibility for basic PL/SQL constructs

Part 19: CONTINUE statement
parent 442ea81e
...@@ -797,3 +797,33 @@ SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; ...@@ -797,3 +797,33 @@ SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
f1(3) f1(4) f1(5) f1(6) f1(3) f1(4) f1(5) f1(6)
6006 8008 10008 12010 6006 8008 10008 12010
DROP FUNCTION f1; DROP FUNCTION f1;
# Testing CONTINUE statement
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
FOR i IN 1 .. a
LOOP
CONTINUE WHEN i=5;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
SHOW FUNCTION CODE f1;
Pos Instruction
0 set total@1 0
1 set i@2 1
2 set [upper_bound]@3 a@0
3 jump_if_not 10(10) (i@2 <= [upper_bound]@3)
4 jump_if_not 7(0) (i@2 = 5)
5 set i@2 (i@2 + 1)
6 jump 3
7 set total@1 (total@1 + 1)
8 set i@2 (i@2 + 1)
9 jump 3
10 freturn 3 total@1
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
f1(3) f1(4) f1(5) f1(6)
3 4 4 5
DROP FUNCTION f1;
...@@ -946,3 +946,84 @@ SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL; ...@@ -946,3 +946,84 @@ SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL;
f1(3,3,0) f1(3,3,1) f1(3,3,2) f1(3,3,3) f1(3,3,4) f1(3,3,0) f1(3,3,1) f1(3,3,2) f1(3,3,3) f1(3,3,4)
3000 3003 3006 3009 3009 3000 3003 3006 3009 3009
DROP FUNCTION f1; DROP FUNCTION f1;
# Testing CONTINUE statement
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
FOR i IN 1 .. a
LOOP
IF i=5 THEN
CONTINUE;
END IF;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
f1(3) f1(4) f1(5) f1(6)
3 4 4 5
DROP FUNCTION f1;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
<<lj>>
FOR j IN 1 .. 2
LOOP
FOR i IN 1 .. a
LOOP
IF i=5 THEN
CONTINUE lj;
END IF;
total:= total + 1;
END LOOP;
END LOOP;
RETURN total;
END;
/
SELECT f1(3), f1(4), f1(5) FROM DUAL;
f1(3) f1(4) f1(5)
6 8 8
DROP FUNCTION f1;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
<<lj>>
FOR j IN 1 .. 2
LOOP
FOR i IN 1 .. a
LOOP
CONTINUE lj WHEN i=5;
total:= total + 1;
END LOOP;
END LOOP;
RETURN total;
END;
/
SELECT f1(3), f1(4), f1(5) FROM DUAL;
f1(3) f1(4) f1(5)
6 8 8
DROP FUNCTION f1;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
i INT:= 1;
BEGIN
WHILE i <= a
LOOP
i:= i + 1;
IF i=6 THEN
CONTINUE;
END IF;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
f1(3) f1(4) f1(5) f1(6)
3 4 4 5
DROP FUNCTION f1;
...@@ -593,3 +593,25 @@ DELIMITER ;/ ...@@ -593,3 +593,25 @@ DELIMITER ;/
SHOW FUNCTION CODE f1; SHOW FUNCTION CODE f1;
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL; SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
DROP FUNCTION f1; DROP FUNCTION f1;
--echo # Testing CONTINUE statement
DELIMITER /;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
FOR i IN 1 .. a
LOOP
CONTINUE WHEN i=5;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
DELIMITER ;/
SHOW FUNCTION CODE f1;
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
DROP FUNCTION f1;
...@@ -996,3 +996,93 @@ DELIMITER ;/ ...@@ -996,3 +996,93 @@ DELIMITER ;/
SHOW FUNCTION CODE f1; SHOW FUNCTION CODE f1;
SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL; SELECT f1(3,3,0), f1(3,3,1), f1(3,3,2), f1(3,3,3), f1(3,3,4) FROM DUAL;
DROP FUNCTION f1; DROP FUNCTION f1;
--echo # Testing CONTINUE statement
DELIMITER /;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
FOR i IN 1 .. a
LOOP
IF i=5 THEN
CONTINUE;
END IF;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
DELIMITER ;/
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
<<lj>>
FOR j IN 1 .. 2
LOOP
FOR i IN 1 .. a
LOOP
IF i=5 THEN
CONTINUE lj;
END IF;
total:= total + 1;
END LOOP;
END LOOP;
RETURN total;
END;
/
DELIMITER ;/
SELECT f1(3), f1(4), f1(5) FROM DUAL;
DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
BEGIN
<<lj>>
FOR j IN 1 .. 2
LOOP
FOR i IN 1 .. a
LOOP
CONTINUE lj WHEN i=5;
total:= total + 1;
END LOOP;
END LOOP;
RETURN total;
END;
/
DELIMITER ;/
SELECT f1(3), f1(4), f1(5) FROM DUAL;
DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1(a INT) RETURN INT
AS
total INT:= 0;
i INT:= 1;
BEGIN
WHILE i <= a
LOOP
i:= i + 1;
IF i=6 THEN
CONTINUE;
END IF;
total:= total + 1;
END LOOP;
RETURN total;
END;
/
DELIMITER ;/
SELECT f1(3), f1(4), f1(5), f1(6) FROM DUAL;
DROP FUNCTION f1;
...@@ -5675,6 +5675,12 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name) ...@@ -5675,6 +5675,12 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", label_name.str); my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", label_name.str);
return true; return true;
} }
return sp_continue_loop(thd, lab);
}
bool LEX::sp_continue_loop(THD *thd, sp_label *lab)
{
if (lab->ctx->for_loop().m_index) if (lab->ctx->for_loop().m_index)
{ {
// We're in a FOR loop, increment the index variable before backward jump // We're in a FOR loop, increment the index variable before backward jump
...@@ -5689,6 +5695,53 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name) ...@@ -5689,6 +5695,53 @@ bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
} }
bool LEX::sp_continue_loop(THD *thd, sp_label *lab, Item *when)
{
if (!when)
return sp_continue_loop(thd, lab);
sphead->reset_lex(thd); // This changes thd->lex
DBUG_ASSERT(sphead == thd->lex->sphead);
DBUG_ASSERT(spcont == thd->lex->spcont);
sp_instr_jump_if_not *i= new (thd->mem_root)
sp_instr_jump_if_not(sphead->instructions(),
spcont,
when, thd->lex);
if (i == NULL ||
sphead->add_instr(i) ||
sphead->restore_lex(thd) ||
sp_continue_loop(thd, lab))
return true;
i->backpatch(sphead->instructions(), spcont);
return false;
}
bool LEX::sp_continue_statement(THD *thd, Item *when)
{
sp_label *lab= spcont->find_label_current_loop_start();
if (!lab)
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", "");
return true;
}
DBUG_ASSERT(lab->type == sp_label::ITERATION);
return sp_continue_loop(thd, lab, when);
}
bool LEX::sp_continue_statement(THD *thd, const LEX_STRING label_name, Item *when)
{
sp_label *lab= spcont->find_label(label_name);
if (!lab || lab->type != sp_label::ITERATION)
{
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "CONTINUE", label_name);
return true;
}
return sp_continue_loop(thd, lab, when);
}
bool LEX::maybe_start_compound_statement(THD *thd) bool LEX::maybe_start_compound_statement(THD *thd)
{ {
if (!sphead) if (!sphead)
......
...@@ -2634,6 +2634,9 @@ struct LEX: public Query_tables_list ...@@ -2634,6 +2634,9 @@ struct LEX: public Query_tables_list
bool sp_exit_block(THD *thd, sp_label *lab); bool sp_exit_block(THD *thd, sp_label *lab);
bool sp_exit_block(THD *thd, sp_label *lab, Item *when); bool sp_exit_block(THD *thd, sp_label *lab, Item *when);
bool sp_continue_loop(THD *thd, sp_label *lab);
bool sp_continue_loop(THD *thd, sp_label *lab, Item *when);
bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_condition(THD *thd, const Lex_for_loop_st &loop);
bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop); bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop);
...@@ -3161,6 +3164,9 @@ struct LEX: public Query_tables_list ...@@ -3161,6 +3164,9 @@ struct LEX: public Query_tables_list
bool sp_exit_statement(THD *thd, Item *when); bool sp_exit_statement(THD *thd, Item *when);
bool sp_exit_statement(THD *thd, const LEX_STRING label_name, Item *item); bool sp_exit_statement(THD *thd, const LEX_STRING label_name, Item *item);
bool sp_leave_statement(THD *thd, const LEX_STRING label_name); bool sp_leave_statement(THD *thd, const LEX_STRING label_name);
bool sp_continue_statement(THD *thd, Item *when);
bool sp_continue_statement(THD *thd, const LEX_STRING label_name, Item *when);
bool sp_iterate_statement(THD *thd, const LEX_STRING label_name); bool sp_iterate_statement(THD *thd, const LEX_STRING label_name);
bool maybe_start_compound_statement(THD *thd); bool maybe_start_compound_statement(THD *thd);
......
...@@ -1264,6 +1264,7 @@ END_OF_INPUT ...@@ -1264,6 +1264,7 @@ END_OF_INPUT
%type <NONE> sp_proc_stmt_if %type <NONE> sp_proc_stmt_if
%type <NONE> sp_labeled_control sp_unlabeled_control %type <NONE> sp_labeled_control sp_unlabeled_control
%type <NONE> sp_labeled_block sp_unlabeled_block sp_unlabeled_block_not_atomic %type <NONE> sp_labeled_block sp_unlabeled_block sp_unlabeled_block_not_atomic
%type <NONE> sp_proc_stmt_continue
%type <NONE> sp_proc_stmt_exit %type <NONE> sp_proc_stmt_exit
%type <NONE> sp_proc_stmt_leave %type <NONE> sp_proc_stmt_leave
%type <NONE> sp_proc_stmt_iterate %type <NONE> sp_proc_stmt_iterate
...@@ -2866,6 +2867,7 @@ sp_proc_stmt_in_returns_clause: ...@@ -2866,6 +2867,7 @@ sp_proc_stmt_in_returns_clause:
sp_proc_stmt: sp_proc_stmt:
sp_proc_stmt_in_returns_clause sp_proc_stmt_in_returns_clause
| sp_proc_stmt_statement | sp_proc_stmt_statement
| sp_proc_stmt_continue
| sp_proc_stmt_exit | sp_proc_stmt_exit
| sp_proc_stmt_leave | sp_proc_stmt_leave
| sp_proc_stmt_iterate | sp_proc_stmt_iterate
...@@ -3004,6 +3006,20 @@ sp_proc_stmt_exit: ...@@ -3004,6 +3006,20 @@ sp_proc_stmt_exit:
} }
; ;
sp_proc_stmt_continue:
CONTINUE_SYM opt_sp_proc_stmt_exit_when_clause
{
if (Lex->sp_continue_statement(thd, $2))
MYSQL_YYABORT;
}
| CONTINUE_SYM label_ident opt_sp_proc_stmt_exit_when_clause
{
if (Lex->sp_continue_statement(thd, $2, $3))
MYSQL_YYABORT;
}
;
sp_proc_stmt_leave: sp_proc_stmt_leave:
LEAVE_SYM label_ident LEAVE_SYM label_ident
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment