mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
MDEV-10411 Providing compatibility for basic PL/SQL constructs
Part 5: EXIT statement Adding optional WHEN clause: EXIT [label] [WHEN expr]
This commit is contained in:
@ -428,6 +428,28 @@ IS
|
||||
i INT := 0;
|
||||
BEGIN
|
||||
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
|
||||
i:= i + 1;
|
||||
IF i >= 5 THEN
|
||||
|
@ -585,3 +585,60 @@ SELECT f1() FROM DUAL;
|
||||
f1()
|
||||
5
|
||||
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;
|
||||
SELECT f1() FROM DUAL;
|
||||
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 /;
|
||||
CREATE FUNCTION f1 RETURN INT
|
||||
IS
|
||||
|
@ -632,3 +632,66 @@ END;
|
||||
DELIMITER ;/
|
||||
SELECT f1() FROM DUAL;
|
||||
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)
|
||||
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", label_name.str);
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
if (!lab)
|
||||
@ -5506,11 +5528,11 @@ bool LEX::sp_exit_statement(THD *thd)
|
||||
return true;
|
||||
}
|
||||
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);
|
||||
if (!lab || lab->type != sp_label::ITERATION)
|
||||
@ -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);
|
||||
return true;
|
||||
}
|
||||
return sp_exit_block(thd, lab);
|
||||
return sp_exit_block(thd, lab, item);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2630,6 +2630,9 @@ private:
|
||||
void parse_error();
|
||||
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
|
||||
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:
|
||||
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
|
||||
bool set_arena_for_set_stmt(Query_arena *backup);
|
||||
@ -3151,10 +3154,8 @@ public:
|
||||
bool sp_block_with_exceptions_finalize_exceptions(THD *thd,
|
||||
uint executable_section_ip,
|
||||
uint exception_count);
|
||||
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
|
||||
bool sp_exit_block(THD *thd, sp_label *lab);
|
||||
bool sp_exit_statement(THD *thd);
|
||||
bool sp_exit_statement(THD *thd, const LEX_STRING label_name);
|
||||
bool sp_exit_statement(THD *thd, Item *when);
|
||||
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_iterate_statement(THD *thd, const LEX_STRING label_name);
|
||||
|
||||
|
@ -1094,6 +1094,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
|
||||
signal_allowed_expr
|
||||
simple_target_specification
|
||||
condition_number
|
||||
opt_sp_proc_stmt_exit_when_clause
|
||||
|
||||
%type <item_param> param_marker
|
||||
|
||||
@ -2963,17 +2964,22 @@ sp_proc_stmt_return:
|
||||
}
|
||||
;
|
||||
|
||||
opt_sp_proc_stmt_exit_when_clause:
|
||||
/* Empty */ { $$= NULL; }
|
||||
| WHEN_SYM expr { $$= $2; }
|
||||
;
|
||||
|
||||
sp_proc_stmt_exit:
|
||||
EXIT_SYM
|
||||
{
|
||||
if (Lex->sp_exit_statement(thd))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| EXIT_SYM label_ident
|
||||
EXIT_SYM opt_sp_proc_stmt_exit_when_clause
|
||||
{
|
||||
if (Lex->sp_exit_statement(thd, $2))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
| EXIT_SYM label_ident opt_sp_proc_stmt_exit_when_clause
|
||||
{
|
||||
if (Lex->sp_exit_statement(thd, $2, $3))
|
||||
MYSQL_YYABORT;
|
||||
}
|
||||
;
|
||||
|
||||
sp_proc_stmt_leave:
|
||||
|
Reference in New Issue
Block a user