mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-10411 Providing compatibility for basic PL/SQL constructs
Part 5: EXIT statement Adding unconditional EXIT statement: EXIT [ label ] Conditional EXIT statements with WHERE clause will be added in a separate patch.
This commit is contained in:
@ -396,3 +396,113 @@ SELECT @v;
|
|||||||
@v
|
@v
|
||||||
324
|
324
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
#
|
||||||
|
# Testing EXIT statement
|
||||||
|
#
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
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(1) (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
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN i:= 1000;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
RETURN i;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
SHOW FUNCTION CODE f1;
|
||||||
|
Pos Instruction
|
||||||
|
0 set i@0 0
|
||||||
|
1 jump 5
|
||||||
|
2 set i@0 (i@0 + 1)
|
||||||
|
3 jump_if_not 8(8) (i@0 >= 5)
|
||||||
|
4 jump 10
|
||||||
|
5 hpush_jump 2 1 EXIT
|
||||||
|
6 set i@0 1000
|
||||||
|
7 hreturn 0 8
|
||||||
|
8 hpop 1
|
||||||
|
9 jump 5
|
||||||
|
10 freturn 3 i@0
|
||||||
|
SELECT f1() FROM DUAL;
|
||||||
|
f1()
|
||||||
|
5
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
CREATE PROCEDURE p1(a IN OUT INT)
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
LOOP
|
||||||
|
BEGIN
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >=5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN a:=1000;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
i:= i + 100;
|
||||||
|
EXIT;
|
||||||
|
END LOOP;
|
||||||
|
a:= i;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN a:=11;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
SHOW PROCEDURE CODE p1;
|
||||||
|
Pos Instruction
|
||||||
|
0 set i@1 0
|
||||||
|
1 jump 14
|
||||||
|
2 set i@1 (i@1 + 1)
|
||||||
|
3 jump_if_not 8(8) (i@1 >= 5)
|
||||||
|
4 jump 10
|
||||||
|
5 hpush_jump 2 2 EXIT
|
||||||
|
6 set a@0 1000
|
||||||
|
7 hreturn 0 8
|
||||||
|
8 hpop 1
|
||||||
|
9 jump 5
|
||||||
|
10 set i@1 (i@1 + 100)
|
||||||
|
11 jump 12
|
||||||
|
12 set a@0 i@1
|
||||||
|
13 jump 17
|
||||||
|
14 hpush_jump 5 2 EXIT
|
||||||
|
15 set a@0 11
|
||||||
|
16 hreturn 0 17
|
||||||
|
17 hpop 1
|
||||||
|
set @v= 10;
|
||||||
|
CALL p1(@v);
|
||||||
|
SELECT @v;
|
||||||
|
@v
|
||||||
|
105
|
||||||
|
DROP PROCEDURE p1;
|
||||||
|
@ -493,3 +493,95 @@ SELECT @v;
|
|||||||
@v
|
@v
|
||||||
10
|
10
|
||||||
DROP PROCEDURE sp1;
|
DROP PROCEDURE sp1;
|
||||||
|
#
|
||||||
|
# Testing EXIT statement
|
||||||
|
#
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
EXIT;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
ERROR 42000: EXIT with no matching label:
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
<<lable1>>
|
||||||
|
BEGIN
|
||||||
|
<<label2>>
|
||||||
|
LOOP
|
||||||
|
EXIT label1;
|
||||||
|
END LOOP;
|
||||||
|
END;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
ERROR 42000: EXIT with no matching label: label1
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
LOOP
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
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;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT label2;
|
||||||
|
END IF;
|
||||||
|
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;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT label1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
i:= i + 100;
|
||||||
|
EXIT;
|
||||||
|
END LOOP;
|
||||||
|
RETURN i;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
SELECT f1() FROM DUAL;
|
||||||
|
f1()
|
||||||
|
5
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
@ -319,3 +319,81 @@ SET @v=10;
|
|||||||
CALL p1(@v);
|
CALL p1(@v);
|
||||||
SELECT @v;
|
SELECT @v;
|
||||||
DROP PROCEDURE p1;
|
DROP PROCEDURE p1;
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing EXIT statement
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
RETURN i;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
SHOW FUNCTION CODE f1;
|
||||||
|
SELECT f1() FROM DUAL;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
BEGIN
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN i:= 1000;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
RETURN i;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
SHOW FUNCTION CODE f1;
|
||||||
|
SELECT f1() FROM DUAL;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
CREATE PROCEDURE p1(a IN OUT INT)
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
LOOP
|
||||||
|
BEGIN
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >=5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN a:=1000;
|
||||||
|
END;
|
||||||
|
END LOOP;
|
||||||
|
i:= i + 100;
|
||||||
|
EXIT;
|
||||||
|
END LOOP;
|
||||||
|
a:= i;
|
||||||
|
EXCEPTION
|
||||||
|
WHEN OTHERS THEN a:=11;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
SHOW PROCEDURE CODE p1;
|
||||||
|
set @v= 10;
|
||||||
|
CALL p1(@v);
|
||||||
|
SELECT @v;
|
||||||
|
DROP PROCEDURE p1;
|
||||||
|
@ -525,3 +525,110 @@ SET @v=10;
|
|||||||
CALL sp1(@v, 30002);
|
CALL sp1(@v, 30002);
|
||||||
SELECT @v;
|
SELECT @v;
|
||||||
DROP PROCEDURE sp1;
|
DROP PROCEDURE sp1;
|
||||||
|
|
||||||
|
|
||||||
|
--echo #
|
||||||
|
--echo # Testing EXIT statement
|
||||||
|
--echo #
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
--error ER_SP_LILABEL_MISMATCH
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
EXIT;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
--error ER_SP_LILABEL_MISMATCH
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
<<lable1>>
|
||||||
|
BEGIN
|
||||||
|
<<label2>>
|
||||||
|
LOOP
|
||||||
|
EXIT label1;
|
||||||
|
END LOOP;
|
||||||
|
END;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
|
||||||
|
|
||||||
|
DELIMITER /;
|
||||||
|
CREATE FUNCTION f1 RETURN INT
|
||||||
|
IS
|
||||||
|
i INT := 0;
|
||||||
|
BEGIN
|
||||||
|
LOOP
|
||||||
|
LOOP
|
||||||
|
i:= i + 1;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT;
|
||||||
|
END IF;
|
||||||
|
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;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT label2;
|
||||||
|
END IF;
|
||||||
|
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;
|
||||||
|
IF i >= 5 THEN
|
||||||
|
EXIT label1;
|
||||||
|
END IF;
|
||||||
|
END LOOP;
|
||||||
|
i:= i + 100;
|
||||||
|
EXIT;
|
||||||
|
END LOOP;
|
||||||
|
RETURN i;
|
||||||
|
END;
|
||||||
|
/
|
||||||
|
DELIMITER ;/
|
||||||
|
SELECT f1() FROM DUAL;
|
||||||
|
DROP FUNCTION f1;
|
||||||
|
@ -197,10 +197,11 @@ sp_variable *sp_pcontext::add_variable(THD *thd, LEX_STRING name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip)
|
sp_label *sp_pcontext::push_label(THD *thd, LEX_STRING name, uint ip,
|
||||||
|
sp_label::enum_type type)
|
||||||
{
|
{
|
||||||
sp_label *label=
|
sp_label *label=
|
||||||
new (thd->mem_root) sp_label(name, ip, sp_label::IMPLICIT, this);
|
new (thd->mem_root) sp_label(name, ip, type, this);
|
||||||
|
|
||||||
if (!label)
|
if (!label)
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -236,6 +237,23 @@ sp_label *sp_pcontext::find_label(const LEX_STRING name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sp_label *sp_pcontext::find_label_current_loop_start()
|
||||||
|
{
|
||||||
|
List_iterator_fast<sp_label> li(m_labels);
|
||||||
|
sp_label *lab;
|
||||||
|
|
||||||
|
while ((lab= li++))
|
||||||
|
{
|
||||||
|
if (lab->type == sp_label::ITERATION)
|
||||||
|
return lab;
|
||||||
|
}
|
||||||
|
// See a comment in sp_pcontext::find_label()
|
||||||
|
return (m_parent && (m_scope == REGULAR_SCOPE)) ?
|
||||||
|
m_parent->find_label_current_loop_start() :
|
||||||
|
NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool sp_pcontext::add_condition(THD *thd,
|
bool sp_pcontext::add_condition(THD *thd,
|
||||||
LEX_STRING name,
|
LEX_STRING name,
|
||||||
sp_condition_value *value)
|
sp_condition_value *value)
|
||||||
|
@ -402,10 +402,18 @@ public:
|
|||||||
// Labels.
|
// Labels.
|
||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
sp_label *push_label(THD *thd, const LEX_STRING name, uint ip);
|
sp_label *push_label(THD *thd, const LEX_STRING name, uint ip,
|
||||||
|
sp_label::enum_type type);
|
||||||
|
|
||||||
|
sp_label *push_label(THD *thd, const LEX_STRING name, uint ip)
|
||||||
|
{
|
||||||
|
return push_label(thd, name, ip, sp_label::IMPLICIT);
|
||||||
|
}
|
||||||
|
|
||||||
sp_label *find_label(const LEX_STRING name);
|
sp_label *find_label(const LEX_STRING name);
|
||||||
|
|
||||||
|
sp_label *find_label_current_loop_start();
|
||||||
|
|
||||||
sp_label *last_label()
|
sp_label *last_label()
|
||||||
{
|
{
|
||||||
sp_label *label= m_labels.head();
|
sp_label *label= m_labels.head();
|
||||||
|
@ -5312,8 +5312,7 @@ bool LEX::sp_handler_declaration_finalize(THD *thd, int type)
|
|||||||
|
|
||||||
void LEX::sp_block_init(THD *thd, const LEX_STRING label)
|
void LEX::sp_block_init(THD *thd, const LEX_STRING label)
|
||||||
{
|
{
|
||||||
sp_label *lab= spcont->push_label(thd, label, sphead->instructions());
|
spcont->push_label(thd, label, sphead->instructions(), sp_label::BEGIN);
|
||||||
lab->type= sp_label::BEGIN;
|
|
||||||
spcont= spcont->push_context(thd, sp_pcontext::REGULAR_SCOPE);
|
spcont= spcont->push_context(thd, sp_pcontext::REGULAR_SCOPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5478,7 +5477,12 @@ 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_exit_block(THD *thd, sp_label *lab)
|
||||||
|
{
|
||||||
/*
|
/*
|
||||||
When jumping to a BEGIN-END block end, the target jump
|
When jumping to a BEGIN-END block end, the target jump
|
||||||
points to the block hpop/cpop cleanup instructions,
|
points to the block hpop/cpop cleanup instructions,
|
||||||
@ -5493,6 +5497,31 @@ bool LEX::sp_leave_statement(THD *thd, const LEX_STRING label_name)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_exit_statement(THD *thd)
|
||||||
|
{
|
||||||
|
sp_label *lab= spcont->find_label_current_loop_start();
|
||||||
|
if (!lab)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", "");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
DBUG_ASSERT(lab->type == sp_label::ITERATION);
|
||||||
|
return sp_exit_block(thd, lab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LEX::sp_exit_statement(THD *thd, const LEX_STRING label_name)
|
||||||
|
{
|
||||||
|
sp_label *lab= spcont->find_label(label_name);
|
||||||
|
if (!lab || lab->type != sp_label::ITERATION)
|
||||||
|
{
|
||||||
|
my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "EXIT", label_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return sp_exit_block(thd, lab);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
|
bool LEX::sp_iterate_statement(THD *thd, const LEX_STRING label_name)
|
||||||
{
|
{
|
||||||
sp_label *lab= spcont->find_label(label_name);
|
sp_label *lab= spcont->find_label(label_name);
|
||||||
@ -5527,8 +5556,8 @@ bool LEX::sp_push_loop_label(THD *thd, const LEX_STRING label_name)
|
|||||||
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name.str);
|
my_error(ER_SP_LABEL_REDEFINE, MYF(0), label_name.str);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
lab= spcont->push_label(thd, label_name, sphead->instructions());
|
spcont->push_label(thd, label_name, sphead->instructions(),
|
||||||
lab->type= sp_label::ITERATION;
|
sp_label::ITERATION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5538,7 +5567,8 @@ bool LEX::sp_push_loop_empty_label(THD *thd)
|
|||||||
if (maybe_start_compound_statement(thd))
|
if (maybe_start_compound_statement(thd))
|
||||||
return true;
|
return true;
|
||||||
/* Unlabeled controls get an empty label. */
|
/* Unlabeled controls get an empty label. */
|
||||||
spcont->push_label(thd, empty_lex_str, sphead->instructions());
|
spcont->push_label(thd, empty_lex_str, sphead->instructions(),
|
||||||
|
sp_label::ITERATION);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3152,6 +3152,9 @@ public:
|
|||||||
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_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_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);
|
||||||
|
|
||||||
|
@ -1260,6 +1260,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_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
|
||||||
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
|
%type <NONE> sp_proc_stmt_open sp_proc_stmt_fetch sp_proc_stmt_close
|
||||||
@ -2858,6 +2859,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_exit
|
||||||
| sp_proc_stmt_leave
|
| sp_proc_stmt_leave
|
||||||
| sp_proc_stmt_iterate
|
| sp_proc_stmt_iterate
|
||||||
| sp_proc_stmt_open
|
| sp_proc_stmt_open
|
||||||
@ -2961,6 +2963,19 @@ sp_proc_stmt_return:
|
|||||||
}
|
}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
sp_proc_stmt_exit:
|
||||||
|
EXIT_SYM
|
||||||
|
{
|
||||||
|
if (Lex->sp_exit_statement(thd))
|
||||||
|
MYSQL_YYABORT;
|
||||||
|
}
|
||||||
|
| EXIT_SYM label_ident
|
||||||
|
{
|
||||||
|
if (Lex->sp_exit_statement(thd, $2))
|
||||||
|
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