summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Barkov <bar@mariadb.org>2016-08-16 10:24:12 +0400
committerAlexander Barkov <bar@mariadb.org>2017-04-05 15:02:43 +0400
commit4b61495576bc240392d7aaaec38ecac8631e447c (patch)
tree709a45ba786bcc894ed9752ea7fb603f1b9da866
parentd2b007d6bc8458d3451bb28cc7319e39dae00e7d (diff)
downloadmariadb-git-4b61495576bc240392d7aaaec38ecac8631e447c.tar.gz
MDEV-10411 Providing compatibility for basic PL/SQL constructs
Part 9: EXCEPTION handlers EXCEPTION is now supported in inner blocks.
-rw-r--r--mysql-test/suite/compat/oracle/r/sp-code.result221
-rw-r--r--mysql-test/suite/compat/oracle/r/sp.result28
-rw-r--r--mysql-test/suite/compat/oracle/t/sp-code.test176
-rw-r--r--mysql-test/suite/compat/oracle/t/sp.test28
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/sql_yacc_ora.yy35
-rw-r--r--sql/structs.h17
7 files changed, 495 insertions, 12 deletions
diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result
index 42e0fb41aaa..8e6d6d940e4 100644
--- a/mysql-test/suite/compat/oracle/r/sp-code.result
+++ b/mysql-test/suite/compat/oracle/r/sp-code.result
@@ -1,4 +1,7 @@
SET sql_mode=ORACLE;
+#
+# Testing exceptions in the top-level blocks
+#
# No HANDLER declarations, no exceptions
CREATE FUNCTION f1 RETURN INT
AS
@@ -175,3 +178,221 @@ Pos Instruction
11 jump 6
12 hpop 3
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;
diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result
index 42416b6ca33..d0fb26b04ae 100644
--- a/mysql-test/suite/compat/oracle/r/sp.result
+++ b/mysql-test/suite/compat/oracle/r/sp.result
@@ -465,3 +465,31 @@ SELECT @v;
@v
113
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;
diff --git a/mysql-test/suite/compat/oracle/t/sp-code.test b/mysql-test/suite/compat/oracle/t/sp-code.test
index ff78410540c..dffd1a19fd2 100644
--- a/mysql-test/suite/compat/oracle/t/sp-code.test
+++ b/mysql-test/suite/compat/oracle/t/sp-code.test
@@ -2,6 +2,10 @@
SET sql_mode=ORACLE;
+--echo #
+--echo # Testing exceptions in the top-level blocks
+--echo #
+
--echo # No HANDLER declarations, no exceptions
DELIMITER /;
CREATE FUNCTION f1 RETURN INT
@@ -143,3 +147,175 @@ END;
DELIMITER ;/
SHOW PROCEDURE CODE 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;
diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test
index a838a74d2da..6b47ab4f7d6 100644
--- a/mysql-test/suite/compat/oracle/t/sp.test
+++ b/mysql-test/suite/compat/oracle/t/sp.test
@@ -497,3 +497,31 @@ CALL sp1(@v, 30001);
CALL sp1(@v, 30002);
SELECT @v;
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;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 1b2b1854c7e..1d637276f3d 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -832,6 +832,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
ulong ulong_num;
ulonglong ulonglong_number;
longlong longlong_number;
+ uint sp_instr_addr;
/* structs */
LEX_STRING lex_str;
@@ -839,6 +840,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable;
Lex_spblock_st spblock;
+ Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index d322770857d..ada471b880d 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -215,6 +215,7 @@ static bool push_sp_empty_label(THD *thd)
Lex_string_with_metadata_st lex_string_with_metadata;
struct sys_var_with_base variable;
Lex_spblock_st spblock;
+ Lex_spblock_handlers_st spblock_handlers;
Lex_length_and_dec_st Lex_length_and_dec;
Lex_cast_type_st Lex_cast_type;
Lex_field_type_st Lex_field_type;
@@ -1311,9 +1312,9 @@ END_OF_INPUT
%type <num> sp_decl_idents sp_handler_type sp_hcond_list
%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_handlers> sp_block_statements_and_exceptions
%type <sp_instr_addr> sp_instr_addr
%type <num> opt_exception_clause exception_handlers
-%type <num> sp_block_statements_and_exceptions
%type <lex> sp_cursor_stmt
%type <spname> sp_name
%type <spvar> sp_param_name sp_param_name_and_type
@@ -3407,12 +3408,14 @@ sp_labeled_block:
BEGIN_SYM
{
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
sp_opt_label
{
- if (Lex->sp_block_finalize(thd, $6))
+ if (Lex->sp_block_finalize(thd, Lex_spblock($4), $6))
MYSQL_YYABORT;
}
| sp_block_label
@@ -3421,12 +3424,17 @@ sp_labeled_block:
Lex->sp_block_init(thd, $1);
}
sp_decl_body_list
+ {
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
BEGIN_SYM
- sp_proc_stmts
+ sp_block_statements_and_exceptions
END
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;
}
;
@@ -3435,11 +3443,13 @@ sp_unlabeled_block:
BEGIN_SYM
{
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
{
- if (Lex->sp_block_finalize(thd))
+ if (Lex->sp_block_finalize(thd, Lex_spblock($3)))
MYSQL_YYABORT;
}
| DECLARE_SYM
@@ -3447,10 +3457,15 @@ sp_unlabeled_block:
Lex->sp_block_init(thd);
}
sp_decl_body_list
+ {
+ if (Lex->sp_block_with_exceptions_finalize_declarations(thd))
+ MYSQL_YYABORT;
+ }
BEGIN_SYM
- sp_proc_stmts
+ sp_block_statements_and_exceptions
END
{
+ $3.hndlrs+= $6.hndlrs;
if (Lex->sp_block_finalize(thd, $3))
MYSQL_YYABORT;
}
@@ -3472,7 +3487,7 @@ sp_body:
BEGIN_SYM
sp_block_statements_and_exceptions
{
- $2.hndlrs+= $5;
+ $2.hndlrs+= $5.hndlrs;
if (Lex->sp_block_finalize(thd, $2))
MYSQL_YYABORT;
}
@@ -3491,7 +3506,7 @@ sp_block_statements_and_exceptions:
{
if (Lex->sp_block_with_exceptions_finalize_exceptions(thd, $1, $4))
MYSQL_YYABORT;
- $$= $4;
+ $$.init($4);
}
;
diff --git a/sql/structs.h b/sql/structs.h
index 24a96276c4e..f0c3926e424 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -628,12 +628,20 @@ public:
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:
int vars;
int conds;
- int hndlrs;
int curs;
void init()
{
@@ -653,6 +661,11 @@ class Lex_spblock: public Lex_spblock_st
{
public:
Lex_spblock() { init(); }
+ Lex_spblock(const Lex_spblock_handlers_st &other)
+ {
+ vars= conds= curs= 0;
+ hndlrs= other.hndlrs;
+ }
};
#endif /* STRUCTS_INCLUDED */