mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
MDEV-10411 Providing compatibility for basic PL/SQL constructs
Part 19: CONTINUE statement
This commit is contained in:
@ -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;
|
|||||||
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 ;/
|
|||||||
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 ;/
|
|||||||
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)
|
|||||||
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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 @@ private:
|
|||||||
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 @@ public:
|
|||||||
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
|
|||||||
%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:
|
|||||||
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:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
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
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user