diff --git a/mysql-test/suite/compat/oracle/r/sp-code.result b/mysql-test/suite/compat/oracle/r/sp-code.result index 42e0fb41aaae0..8e6d6d940e46e 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 42416b6ca3364..d0fb26b04ae66 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 ff78410540c7e..dffd1a19fd205 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 a838a74d2dafe..6b47ab4f7d620 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 1b2b1854c7e17..1d637276f3d20 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 d322770857d1a..ada471b880d7b 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 sp_decl_idents sp_handler_type sp_hcond_list %type sp_cond sp_hcond sqlstate signal_value opt_signal_value %type sp_decl_body sp_decl_body_list opt_sp_decl_body_list +%type sp_block_statements_and_exceptions %type sp_instr_addr %type opt_exception_clause exception_handlers -%type sp_block_statements_and_exceptions %type sp_cursor_stmt %type sp_name %type 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 24a96276c4ea5..f0c3926e42416 100644 --- a/sql/structs.h +++ b/sql/structs.h @@ -628,12 +628,20 @@ struct Lex_dyncol_type_st: public Lex_length_and_dec_st 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 */