diff --git a/mysql-test/suite/compat/oracle/r/exception.result b/mysql-test/suite/compat/oracle/r/exception.result index 28e31eb533f..7366f147f2a 100644 --- a/mysql-test/suite/compat/oracle/r/exception.result +++ b/mysql-test/suite/compat/oracle/r/exception.result @@ -199,5 +199,24 @@ ERROR 24000: Cursor is not open DROP PROCEDURE p1; DROP TABLE t1; # +# Testing that warning-alike errors are caught by OTHERS +# +CREATE TABLE t1 (a INT); +CREATE FUNCTION f1 RETURN VARCHAR +AS +a INT:=10; +BEGIN +SELECT a INTO a FROM t1; +RETURN 'OK'; +EXCEPTION +WHEN OTHERS THEN RETURN 'Exception'; +END; +$$ +SELECT f1() FROM DUAL; +f1() +Exception +DROP FUNCTION f1; +DROP TABLE t1; +# # End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions # diff --git a/mysql-test/suite/compat/oracle/t/exception.test b/mysql-test/suite/compat/oracle/t/exception.test index 52a300dffe6..2bb27433a4d 100644 --- a/mysql-test/suite/compat/oracle/t/exception.test +++ b/mysql-test/suite/compat/oracle/t/exception.test @@ -239,6 +239,27 @@ CALL p1(); DROP PROCEDURE p1; DROP TABLE t1; +--echo # +--echo # Testing that warning-alike errors are caught by OTHERS +--echo # + +CREATE TABLE t1 (a INT); +DELIMITER $$; +CREATE FUNCTION f1 RETURN VARCHAR +AS + a INT:=10; +BEGIN + SELECT a INTO a FROM t1; + RETURN 'OK'; +EXCEPTION + WHEN OTHERS THEN RETURN 'Exception'; +END; +$$ +DELIMITER ;$$ +SELECT f1() FROM DUAL; +DROP FUNCTION f1; +DROP TABLE t1; + --echo # --echo # End of MDEV-10840 sql_mode=ORACLE: RAISE statement for predefined exceptions diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 20ff92e3cf1..87ec5f98557 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -410,8 +410,16 @@ sp_pcontext::find_handler(const char *sql_state, break; case sp_condition_value::EXCEPTION: - if (is_sqlstate_exception(sql_state) && - level == Sql_condition::WARN_LEVEL_ERROR && !found_cv) + /* + In sql_mode=ORACLE this construct should catch errors and warnings: + EXCEPTION + WHEN OTHERS THEN ...; + E.g. NO_DATA_FOUND is more like a warning than an error, + and it should be caught. + */ + if (((current_thd->variables.sql_mode & MODE_ORACLE) || + (is_sqlstate_exception(sql_state) && + level == Sql_condition::WARN_LEVEL_ERROR)) && !found_cv) { found_cv= cv; found_handler= h;