diff --git a/mysql-test/suite/compat/oracle/r/sp.result b/mysql-test/suite/compat/oracle/r/sp.result index 53ca49c8ef1..f2e9eb6f226 100644 --- a/mysql-test/suite/compat/oracle/r/sp.result +++ b/mysql-test/suite/compat/oracle/r/sp.result @@ -350,3 +350,23 @@ i 4 i 3 +# Testing exceptions +CREATE TABLE t1 (c1 INT); +CREATE PROCEDURE sp1 (p1 IN VARCHAR2(20), p2 OUT VARCHAR2(30)) +IS +v1 INT; +BEGIN +EXCEPTION WHEN NOT FOUND THEN +BEGIN +p2 := 'def'; +END; +SELECT c1 INTO v1 FROM t1; +p2 := p1; +END; +/ +CALL sp1('abc', @a); +SELECT @a; +@a +def +DROP PROCEDURE sp1; +DROP TABLE t1; diff --git a/mysql-test/suite/compat/oracle/t/sp.test b/mysql-test/suite/compat/oracle/t/sp.test index 3ea9c2a9276..1880f153f2a 100644 --- a/mysql-test/suite/compat/oracle/t/sp.test +++ b/mysql-test/suite/compat/oracle/t/sp.test @@ -377,3 +377,31 @@ BEGIN NOT ATOMIC END / DELIMITER ;/ + + +--echo # Testing exceptions + +CREATE TABLE t1 (c1 INT); + +DELIMITER /; + +CREATE PROCEDURE sp1 (p1 IN VARCHAR2(20), p2 OUT VARCHAR2(30)) +IS + v1 INT; +BEGIN + EXCEPTION WHEN NOT FOUND THEN + BEGIN + p2 := 'def'; + END; + SELECT c1 INTO v1 FROM t1; + p2 := p1; +END; +/ + +DELIMITER ;/ + +CALL sp1('abc', @a); +SELECT @a; + +DROP PROCEDURE sp1; +DROP TABLE t1; diff --git a/sql/lex.h b/sql/lex.h index a83ef373642..b1259eab42b 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -222,6 +222,7 @@ static SYMBOL symbols[] = { { "EXCHANGE", SYM(EXCHANGE_SYM)}, { "EXCLUDE", SYM(EXCLUDE_SYM)}, { "EXECUTE", SYM(EXECUTE_SYM)}, + { "EXCEPTION", SYM(EXCEPTION_SYM)}, { "EXISTS", SYM(EXISTS)}, { "EXIT", SYM(EXIT_SYM)}, { "EXPANSION", SYM(EXPANSION_SYM)}, diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 2f30ffdd927..280262ac5f7 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1150,6 +1150,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token EXCEPT_SYM /* SQL-2003-R */ %token EXCLUDE_SYM /* SQL-2011-N */ %token EXECUTE_SYM /* SQL-2003-R */ +%token EXCEPTION_SYM /* SQL-2003-N */ %token EXISTS /* SQL-2003-R */ %token EXIT_SYM %token EXPANSION_SYM @@ -14471,6 +14472,7 @@ keyword_sp: | EVENT_SYM {} | EVENTS_SYM {} | EVERY_SYM {} + | EXCEPTION_SYM {} | EXCHANGE_SYM {} | EXPANSION_SYM {} | EXPORT_SYM {} diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy index 50341022b23..0eec0946a30 100644 --- a/sql/sql_yacc_ora.yy +++ b/sql/sql_yacc_ora.yy @@ -525,6 +525,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize); %token EXCEPT_SYM /* SQL-2003-R */ %token EXCLUDE_SYM /* SQL-2011-N */ %token EXECUTE_SYM /* SQL-2003-R */ +%token EXCEPTION_SYM /* SQL-2003-N */ %token EXISTS /* SQL-2003-R */ %token EXIT_SYM %token EXPANSION_SYM @@ -1330,6 +1331,7 @@ 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 opt_exception_clause exception_handlers %type sp_cursor_stmt %type sp_name %type sp_param_name sp_param_name_and_type @@ -2523,7 +2525,7 @@ sp_hcond: if ($$ == NULL) MYSQL_YYABORT; } - | SQLEXCEPTION_SYM /* All other SQLSTATEs */ + | OTHERS_SYM /* All other SQLSTATEs */ { $$= new (thd->mem_root) sp_condition_value(sp_condition_value::EXCEPTION); if ($$ == NULL) @@ -3432,6 +3434,10 @@ sp_body: } opt_sp_decl_body_list BEGIN_SYM + opt_exception_clause + { + $2.hndlrs+= $4; + } sp_proc_stmts END { @@ -3455,6 +3461,31 @@ sp_unlabeled_block_not_atomic: } ; +opt_exception_clause: + /* Empty */ { $$= 0; } + | EXCEPTION_SYM exception_handlers { $$= $2; } + ; + +exception_handlers: + exception_handler ';' { $$= 1; } + | exception_handlers exception_handler ';' { $$= $1 + 1; } + ; + +exception_handler: + WHEN_SYM + { + if (Lex->sp_handler_declaration_init(thd, sp_handler::EXIT)) + MYSQL_YYABORT; + } + sp_hcond_list + THEN_SYM + sp_proc_stmt + { + if (Lex->sp_handler_declaration_finalize(thd, sp_handler::EXIT)) + MYSQL_YYABORT; + } + ; + loop_body: sp_proc_stmts1 END LOOP_SYM {