Commit 4b614955 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-10411 Providing compatibility for basic PL/SQL constructs

Part 9: EXCEPTION handlers

EXCEPTION is now supported in inner blocks.
parent d2b007d6
SET sql_mode=ORACLE; SET sql_mode=ORACLE;
#
# Testing exceptions in the top-level blocks
#
# No HANDLER declarations, no exceptions # No HANDLER declarations, no exceptions
CREATE FUNCTION f1 RETURN INT CREATE FUNCTION f1 RETURN INT
AS AS
...@@ -175,3 +178,221 @@ Pos Instruction ...@@ -175,3 +178,221 @@ Pos Instruction
11 jump 6 11 jump 6
12 hpop 3 12 hpop 3
DROP PROCEDURE p1; DROP PROCEDURE p1;
#
# Testing EXCEPTIONS in internal blocks
#
# No HANDLER declarations, no code, no exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 jump 5
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
123
DROP PROCEDURE p1;
# No HANDLER declarations, no code, some exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 jump 2
2 hpush_jump 5 1 EXIT
3 set v@0 335
4 hreturn 0 5
5 hpop 1
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
123
DROP PROCEDURE p1;
# No HANDLER declarations, some code, no exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
v:=223;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 set v@0 223
2 jump 6
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
223
DROP PROCEDURE p1;
# No HANDLER declarations, some code, some exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
v:=223;
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 jump 4
2 set v@0 223
3 jump 7
4 hpush_jump 2 1 EXIT
5 set v@0 335
6 hreturn 0 7
7 hpop 1
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
223
DROP PROCEDURE p1;
# Some HANDLER declarations, no code, no exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 hpush_jump 4 1 EXIT
2 set v@0 323
3 hreturn 0 4
4 hpop 1
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
123
DROP PROCEDURE p1;
# Some HANDLER declarations, no code, some exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 hpush_jump 4 1 EXIT
2 set v@0 323
3 hreturn 0 7
4 hpush_jump 7 1 EXIT
5 set v@0 335
6 hreturn 0 7
7 hpop 2
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
123
DROP PROCEDURE p1;
# Some HANDLER declarations, some code, no exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
v:= 324;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 hpush_jump 4 1 EXIT
2 set v@0 323
3 hreturn 0 5
4 set v@0 324
5 hpop 1
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
324
DROP PROCEDURE p1;
# Some HANDLER declarations, some code, some exceptions
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
v:= 324;
EXCEPTION WHEN 2002 THEN v:= 325;
END;
END;
/
SHOW PROCEDURE CODE p1;
Pos Instruction
0 set v@0 123
1 hpush_jump 6 1 EXIT
2 set v@0 323
3 hreturn 0 9
4 set v@0 324
5 jump 9
6 hpush_jump 4 1 EXIT
7 set v@0 325
8 hreturn 0 9
9 hpop 2
SET @v=10;
CALL p1(@v);
SELECT @v;
@v
324
DROP PROCEDURE p1;
...@@ -465,3 +465,31 @@ SELECT @v; ...@@ -465,3 +465,31 @@ SELECT @v;
@v @v
113 113
DROP PROCEDURE sp1; DROP PROCEDURE sp1;
CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
IS
BEGIN
BEGIN
BEGIN
SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
v:= 223;
EXCEPTION
WHEN 30001 THEN
BEGIN
v:= 113;
END;
END;
END;
END;
/
SET @v=10;
CALL sp1(@v, 30001);
SELECT @v;
@v
113
SET @v=10;
CALL sp1(@v, 30002);
ERROR 45000: User defined error!
SELECT @v;
@v
10
DROP PROCEDURE sp1;
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
SET sql_mode=ORACLE; SET sql_mode=ORACLE;
--echo #
--echo # Testing exceptions in the top-level blocks
--echo #
--echo # No HANDLER declarations, no exceptions --echo # No HANDLER declarations, no exceptions
DELIMITER /; DELIMITER /;
CREATE FUNCTION f1 RETURN INT CREATE FUNCTION f1 RETURN INT
...@@ -143,3 +147,175 @@ END; ...@@ -143,3 +147,175 @@ END;
DELIMITER ;/ DELIMITER ;/
SHOW PROCEDURE CODE p1; SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1; DROP PROCEDURE p1;
--echo #
--echo # Testing EXCEPTIONS in internal blocks
--echo #
--echo # No HANDLER declarations, no code, no exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # No HANDLER declarations, no code, some exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # No HANDLER declarations, some code, no exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
v:=223;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # No HANDLER declarations, some code, some exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
BEGIN
v:=223;
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # Some HANDLER declarations, no code, no exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # Some HANDLER declarations, no code, some exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
EXCEPTION
WHEN 20002 THEN v:=335;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # Some HANDLER declarations, some code, no exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
v:= 324;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
--echo # Some HANDLER declarations, some code, some exceptions
DELIMITER /;
CREATE PROCEDURE p1 (v IN OUT INT)
IS
BEGIN
v:=123;
DECLARE
EXIT HANDLER FOR 1000
BEGIN
v:=323;
END;
BEGIN
v:= 324;
EXCEPTION WHEN 2002 THEN v:= 325;
END;
END;
/
DELIMITER ;/
SHOW PROCEDURE CODE p1;
SET @v=10;
CALL p1(@v);
SELECT @v;
DROP PROCEDURE p1;
...@@ -497,3 +497,31 @@ CALL sp1(@v, 30001); ...@@ -497,3 +497,31 @@ CALL sp1(@v, 30001);
CALL sp1(@v, 30002); CALL sp1(@v, 30002);
SELECT @v; SELECT @v;
DROP PROCEDURE sp1; DROP PROCEDURE sp1;
DELIMITER /;
CREATE PROCEDURE sp1 (v IN OUT INT, error IN INT)
IS
BEGIN
BEGIN
BEGIN
SIGNAL SQLSTATE '45000' SET MYSQL_ERRNO=error, MESSAGE_TEXT='User defined error!';
v:= 223;
EXCEPTION
WHEN 30001 THEN
BEGIN
v:= 113;
END;
END;
END;
END;
/
DELIMITER ;/
SET @v=10;
CALL sp1(@v, 30001);
SELECT @v;
SET @v=10;
--error 30002
CALL sp1(@v, 30002);
SELECT @v;
DROP PROCEDURE sp1;
...@@ -832,6 +832,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) ...@@ -832,6 +832,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
ulong ulong_num; ulong ulong_num;
ulonglong ulonglong_number; ulonglong ulonglong_number;
longlong longlong_number; longlong longlong_number;
uint sp_instr_addr;
/* structs */ /* structs */
LEX_STRING lex_str; LEX_STRING lex_str;
...@@ -839,6 +840,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr) ...@@ -839,6 +840,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
Lex_string_with_metadata_st lex_string_with_metadata; Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable; struct sys_var_with_base variable;
Lex_spblock_st spblock; Lex_spblock_st spblock;
Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec; Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type; Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type; Lex_field_type_st Lex_field_type;
......
...@@ -215,6 +215,7 @@ static bool push_sp_empty_label(THD *thd) ...@@ -215,6 +215,7 @@ static bool push_sp_empty_label(THD *thd)
Lex_string_with_metadata_st lex_string_with_metadata; Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable; struct sys_var_with_base variable;
Lex_spblock_st spblock; Lex_spblock_st spblock;
Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec; Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type; Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type; Lex_field_type_st Lex_field_type;
...@@ -1311,9 +1312,9 @@ END_OF_INPUT ...@@ -1311,9 +1312,9 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list %type <num> sp_decl_idents sp_handler_type sp_hcond_list
%type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value %type <spcondvalue> sp_cond sp_hcond sqlstate signal_value opt_signal_value
%type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list %type <spblock> sp_decl_body sp_decl_body_list opt_sp_decl_body_list
%type <spblock_handlers> sp_block_statements_and_exceptions
%type <sp_instr_addr> sp_instr_addr %type <sp_instr_addr> sp_instr_addr
%type <num> opt_exception_clause exception_handlers %type <num> opt_exception_clause exception_handlers
%type <num> sp_block_statements_and_exceptions
%type <lex> sp_cursor_stmt %type <lex> sp_cursor_stmt
%type <spname> sp_name %type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type %type <spvar> sp_param_name sp_param_name_and_type
...@@ -3407,12 +3408,14 @@ sp_labeled_block: ...@@ -3407,12 +3408,14 @@ sp_labeled_block:
BEGIN_SYM BEGIN_SYM
{ {
Lex->sp_block_init(thd, $1); Lex->sp_block_init(thd, $1);
if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
MYSQL_YYABORT;
} }
sp_proc_stmts sp_block_statements_and_exceptions
END END
sp_opt_label sp_opt_label
{ {
if (Lex->sp_block_finalize(thd, $6)) if (Lex->sp_block_finalize(thd, Lex_spblock($4), $6))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| sp_block_label | sp_block_label
...@@ -3421,12 +3424,17 @@ sp_labeled_block: ...@@ -3421,12 +3424,17 @@ sp_labeled_block:
Lex->sp_block_init(thd, $1); Lex->sp_block_init(thd, $1);
} }
sp_decl_body_list sp_decl_body_list
{
if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
MYSQL_YYABORT;
}
BEGIN_SYM BEGIN_SYM
sp_proc_stmts sp_block_statements_and_exceptions
END END
sp_opt_label sp_opt_label
{ {
if (Lex->sp_block_finalize(thd, $4, $8)) $4.hndlrs+= $7.hndlrs;
if (Lex->sp_block_finalize(thd, $4, $9))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
; ;
...@@ -3435,11 +3443,13 @@ sp_unlabeled_block: ...@@ -3435,11 +3443,13 @@ sp_unlabeled_block:
BEGIN_SYM BEGIN_SYM
{ {
Lex->sp_block_init(thd); Lex->sp_block_init(thd);
if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
MYSQL_YYABORT;
} }
sp_proc_stmts sp_block_statements_and_exceptions
END END
{ {
if (Lex->sp_block_finalize(thd)) if (Lex->sp_block_finalize(thd, Lex_spblock($3)))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
| DECLARE_SYM | DECLARE_SYM
...@@ -3447,10 +3457,15 @@ sp_unlabeled_block: ...@@ -3447,10 +3457,15 @@ sp_unlabeled_block:
Lex->sp_block_init(thd); Lex->sp_block_init(thd);
} }
sp_decl_body_list sp_decl_body_list
{
if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
MYSQL_YYABORT;
}
BEGIN_SYM BEGIN_SYM
sp_proc_stmts sp_block_statements_and_exceptions
END END
{ {
$3.hndlrs+= $6.hndlrs;
if (Lex->sp_block_finalize(thd, $3)) if (Lex->sp_block_finalize(thd, $3))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -3472,7 +3487,7 @@ sp_body: ...@@ -3472,7 +3487,7 @@ sp_body:
BEGIN_SYM BEGIN_SYM
sp_block_statements_and_exceptions sp_block_statements_and_exceptions
{ {
$2.hndlrs+= $5; $2.hndlrs+= $5.hndlrs;
if (Lex->sp_block_finalize(thd, $2)) if (Lex->sp_block_finalize(thd, $2))
MYSQL_YYABORT; MYSQL_YYABORT;
} }
...@@ -3491,7 +3506,7 @@ sp_block_statements_and_exceptions: ...@@ -3491,7 +3506,7 @@ sp_block_statements_and_exceptions:
{ {
if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4)) if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4))
MYSQL_YYABORT; MYSQL_YYABORT;
$$= $4; $$.init($4);
} }
; ;
......
...@@ -628,12 +628,20 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st ...@@ -628,12 +628,20 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st
int dyncol_type() const { return m_type; } int dyncol_type() const { return m_type; }
}; };
struct Lex_spblock_st
struct Lex_spblock_handlers_st
{
public:
int hndlrs;
void init(int count) { hndlrs= count; }
};
struct Lex_spblock_st: public Lex_spblock_handlers_st
{ {
public: public:
int vars; int vars;
int conds; int conds;
int hndlrs;
int curs; int curs;
void init() void init()
{ {
...@@ -653,6 +661,11 @@ class Lex_spblock: public Lex_spblock_st ...@@ -653,6 +661,11 @@ class Lex_spblock: public Lex_spblock_st
{ {
public: public:
Lex_spblock() { init(); } Lex_spblock() { init(); }
Lex_spblock(const Lex_spblock_handlers_st &other)
{
vars= conds= curs= 0;
hndlrs= other.hndlrs;
}
}; };
#endif /* STRUCTS_INCLUDED */ #endif /* STRUCTS_INCLUDED */
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