Commit a83d0aee authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10411 Providing compatibility for basic PL/SQL constructs

Part 5: EXIT statement

Adding optional WHEN clause:

EXIT [label] [WHEN expr]
parent 8feb9842
...@@ -428,6 +428,28 @@ IS ...@@ -428,6 +428,28 @@ IS
i INT := 0; i INT := 0;
BEGIN BEGIN
LOOP LOOP
i:= i + 1;
EXIT WHEN i >=5;
END LOOP;
RETURN i;
END;
/
SHOW FUNCTION CODE f1;
Pos Instruction
0 set i@0 0
1 set i@0 (i@0 + 1)
2 jump_if_not 1(0) (i@0 >= 5)
3 jump 4
4 freturn 3 i@0
SELECT f1() FROM DUAL;
f1()
5
DROP FUNCTION f1;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
LOOP
BEGIN BEGIN
i:= i + 1; i:= i + 1;
IF i >= 5 THEN IF i >= 5 THEN
......
...@@ -585,3 +585,60 @@ SELECT f1() FROM DUAL; ...@@ -585,3 +585,60 @@ SELECT f1() FROM DUAL;
f1() f1()
5 5
DROP FUNCTION f1; DROP FUNCTION f1;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
LOOP
i:= i + 1;
EXIT WHEN i >=5;
END LOOP;
RETURN i;
END;
/
SELECT f1() FROM DUAL;
f1()
5
DROP FUNCTION f1;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
<<label1>>
LOOP
<<label2>>
LOOP
i:= i + 1;
EXIT label2 WHEN i >= 5;
END LOOP;
i:= i + 100;
EXIT;
END LOOP;
RETURN i;
END;
/
SELECT f1() FROM DUAL;
f1()
105
DROP FUNCTION f1;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
<<label1>>
LOOP
<<label2>>
LOOP
i:= i + 1;
EXIT label1 WHEN i >= 5;
END LOOP;
i:= i + 100;
EXIT;
END LOOP;
RETURN i;
END;
/
SELECT f1() FROM DUAL;
f1()
5
DROP FUNCTION f1;
...@@ -343,6 +343,25 @@ SHOW FUNCTION CODE f1; ...@@ -343,6 +343,25 @@ SHOW FUNCTION CODE f1;
SELECT f1() FROM DUAL; SELECT f1() FROM DUAL;
DROP FUNCTION f1; DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
LOOP
i:= i + 1;
EXIT WHEN i >=5;
END LOOP;
RETURN i;
END;
/
DELIMITER ;/
SHOW FUNCTION CODE f1;
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
DELIMITER /; DELIMITER /;
CREATE FUNCTION f1 RETURN INT CREATE FUNCTION f1 RETURN INT
IS IS
......
...@@ -632,3 +632,66 @@ END; ...@@ -632,3 +632,66 @@ END;
DELIMITER ;/ DELIMITER ;/
SELECT f1() FROM DUAL; SELECT f1() FROM DUAL;
DROP FUNCTION f1; DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
LOOP
i:= i + 1;
EXIT WHEN i >=5;
END LOOP;
RETURN i;
END;
/
DELIMITER ;/
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
<<label1>>
LOOP
<<label2>>
LOOP
i:= i + 1;
EXIT label2 WHEN i >= 5;
END LOOP;
i:= i + 100;
EXIT;
END LOOP;
RETURN i;
END;
/
DELIMITER ;/
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
DELIMITER /;
CREATE FUNCTION f1 RETURN INT
IS
i INT := 0;
BEGIN
<<label1>>
LOOP
<<label2>>
LOOP
i:= i + 1;
EXIT label1 WHEN i >= 5;
END LOOP;
i:= i + 100;
EXIT;
END LOOP;
RETURN i;
END;
/
DELIMITER ;/
SELECT f1() FROM DUAL;
DROP FUNCTION f1;
...@@ -5477,7 +5477,7 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name) ...@@ -5477,7 +5477,7 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name)
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name.str); my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name.str);
return true; return true;
} }
return sp_exit_block(thd, lab); return sp_exit_block(thd, lab, NULL);
} }
...@@ -5497,7 +5497,29 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab) ...@@ -5497,7 +5497,29 @@ bool LEX::sp_exit_block(THD *thd, sp_label *lab)
} }
bool LEX::sp_exit_statement(THD *thd) bool LEX::sp_exit_block(THD *thd, sp_label *lab, Item *when)
{
if (!when)
return sp_exit_block(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_exit_block(thd, lab))
return true;
i->backpatch(sphead->instructions(), spcont);
return false;
}
bool LEX::sp_exit_statement(THD *thd, Item *item)
{ {
sp_label *lab= spcont->find_label_current_loop_start(); sp_label *lab= spcont->find_label_current_loop_start();
if (!lab) if (!lab)
...@@ -5506,11 +5528,11 @@ bool LEX::sp_exit_statement(THD *thd) ...@@ -5506,11 +5528,11 @@ bool LEX::sp_exit_statement(THD *thd)
return true; return true;
} }
DBUG_ASSERT(lab->type == sp_label::ITERATION); DBUG_ASSERT(lab->type == sp_label::ITERATION);
return sp_exit_block(thd, lab); return sp_exit_block(thd, lab, item);
} }
bool LEX::sp_exit_statement(THD *thd, const LEX_STRING label_name) bool LEX::sp_exit_statement(THD *thd, const LEX_STRING label_name, Item *item)
{ {
sp_label *lab= spcont->find_label(label_name); sp_label *lab= spcont->find_label(label_name);
if (!lab || lab->type != sp_label::ITERATION) if (!lab || lab->type != sp_label::ITERATION)
...@@ -5518,7 +5540,7 @@ bool LEX::sp_exit_statement(THD *thd, const LEX_STRING label_name) ...@@ -5518,7 +5540,7 @@ bool LEX::sp_exit_statement(THD *thd, const LEX_STRING label_name)
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name); my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name);
return true; return true;
} }
return sp_exit_block(thd, lab); return sp_exit_block(thd, lab, item);
} }
......
...@@ -2630,6 +2630,9 @@ struct LEX: public Query_tables_list ...@@ -2630,6 +2630,9 @@ struct LEX: public Query_tables_list
void parse_error(); void parse_error();
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock, bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
class sp_label **splabel); class sp_label **splabel);
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
bool sp_exit_block(THD *thd, sp_label *lab);
bool sp_exit_block(THD *thd, sp_label *lab, Item *when);
public: public:
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;} inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
bool set_arena_for_set_stmt(Query_arena *backup); bool set_arena_for_set_stmt(Query_arena *backup);
...@@ -3151,10 +3154,8 @@ struct LEX: public Query_tables_list ...@@ -3151,10 +3154,8 @@ struct LEX: public Query_tables_list
bool sp_block_with_exceptions_finalize_exceptions(THD *thd, bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
uint executable_section_ip, uint executable_section_ip,
uint exception_count); uint exception_count);
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive); bool sp_exit_statement(THD *thd, Item *when);
bool sp_exit_block(THD *thd, sp_label *lab); bool sp_exit_statement(THD *thd, const LEX_STRING label_name, Item *item);
bool sp_exit_statement(THD *thd);
bool sp_exit_statement(THD *thd, const LEX_STRING label_name);
bool sp_leave_statement(THD *thd, const LEX_STRING label_name); bool sp_leave_statement(THD *thd, const LEX_STRING label_name);
bool sp_iterate_statement(THD *thd, const LEX_STRING label_name); bool sp_iterate_statement(THD *thd, const LEX_STRING label_name);
......
...@@ -1094,6 +1094,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); ...@@ -1094,6 +1094,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
signal_allowed_expr signal_allowed_expr
simple_target_specification simple_target_specification
condition_number condition_number
opt_sp_proc_stmt_exit_when_clause
%type <item_param> param_marker %type <item_param> param_marker
...@@ -2963,15 +2964,20 @@ sp_proc_stmt_return: ...@@ -2963,15 +2964,20 @@ sp_proc_stmt_return:
} }
; ;
opt_sp_proc_stmt_exit_when_clause:
/* Empty */ { $$= NULL; }
| WHEN_SYM expr { $$= $2; }
;
sp_proc_stmt_exit: sp_proc_stmt_exit:
EXIT_SYM EXIT_SYM opt_sp_proc_stmt_exit_when_clause
{ {
if (Lex->sp_exit_statement(thd)) if (Lex->sp_exit_statement(thd, $2))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| EXIT_SYM label_ident | EXIT_SYM label_ident opt_sp_proc_stmt_exit_when_clause
{ {
if (Lex->sp_exit_statement(thd, $2)) if (Lex->sp_exit_statement(thd, $2, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
......
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