diff options
author | Sergei Golubchik <sergii@pisem.net> | 2013-07-12 10:17:52 +0200 |
---|---|---|
committer | Sergei Golubchik <sergii@pisem.net> | 2013-07-12 10:17:52 +0200 |
commit | 3cd1861a81f5c858014c8bbb67440daaffb05cce (patch) | |
tree | 361f04d90380771c79ea35ac7290eca17a01c5d0 | |
parent | f0502cf87ce7f2795edfcf94d2dcad86ce3d190f (diff) | |
download | mariadb-git-3cd1861a81f5c858014c8bbb67440daaffb05cce.tar.gz |
merge bugfuxes for sp-error.test
-rw-r--r-- | mysql-test/r/signal.result | 14 | ||||
-rw-r--r-- | mysql-test/r/sp-error.result | 875 | ||||
-rw-r--r-- | mysql-test/t/signal.test | 11 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 970 | ||||
-rw-r--r-- | sql/sp_head.cc | 8 | ||||
-rw-r--r-- | sql/sp_rcontext.cc | 17 |
6 files changed, 1890 insertions, 5 deletions
diff --git a/mysql-test/r/signal.result b/mysql-test/r/signal.result index 407f5f21745..a5eb24442b4 100644 --- a/mysql-test/r/signal.result +++ b/mysql-test/r/signal.result @@ -1315,19 +1315,25 @@ drop procedure test_signal $$ # # Test where SIGNAL can be used # + +# RETURN statement clears Diagnostics Area, thus +# the warnings raised in a stored function are not +# visible outsidef the stored function. So, we're using +# @@warning_count variable to check that SIGNAL succeeded. + create function test_signal_func() returns integer begin +DECLARE v INT; DECLARE warn CONDITION FOR SQLSTATE "01XXX"; SIGNAL warn SET MESSAGE_TEXT = "This function SIGNAL a warning", MYSQL_ERRNO = 1012; -return 5; +SELECT @@warning_count INTO v; +return v; end $$ select test_signal_func() $$ test_signal_func() -5 -Warnings: -Warning 1012 This function SIGNAL a warning +1 drop function test_signal_func $$ create function test_signal_func() returns integer begin diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index 3862309873b..71fab8c9654 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -1993,3 +1993,878 @@ Error 1048 Column 'c' cannot be null DROP TABLE t1; DROP TABLE t2; DROP PROCEDURE p1; + +################################################################### +# Tests for the following bugs: +# - Bug#11763171: 55852 - Possibly inappropriate handler activation. +# - Bug#11749343: 38806 - Wrong scope for SQL HANDLERS in SP. +################################################################### + + +# -- Check that SQL-conditions thrown by Statement-blocks are +# -- handled by Handler-decl blocks properly. + +CREATE PROCEDURE p1() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H2' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should be handled by H2. +END| + +CALL p1()| +HandlerId +H2 + +# -- Check that SQL-conditions thrown by Statement-blocks are +# -- handled by Handler-decl blocks properly in case of nested +# -- SQL-blocks. + +CREATE PROCEDURE p2() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H2' AS HandlerId; +BEGIN +SELECT 'B1' AS BlockId; +BEGIN +SELECT 'B2' AS BlockId; +BEGIN +SELECT 'B3' AS BlockId; +SIGNAL SQLSTATE '01000'; # Should be handled by H2. +END; +END; +END; +END| + +CALL p2()| +BlockId +B1 +BlockId +B2 +BlockId +B3 +HandlerId +H2 + +# -- Check SQL-handler resolution rules. + +CREATE PROCEDURE p3() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H3' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should be handled by H3. +END| + +CALL p3()| +HandlerId +H3 + +CREATE PROCEDURE p4() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H3' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should be handled by H2. +END| + +CALL p4()| +HandlerId +H2 + +CREATE PROCEDURE p5() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H2' AS HandlerId; +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H3' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should be handled by H3. +END; +END| + +CALL p5()| +HandlerId +H3 + +# -- Check that handlers don't handle its own exceptions. + +CREATE PROCEDURE p6() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +SELECT 'H1' AS HandlerId; +SIGNAL SQLSTATE 'HY000'; # Should *not* be handled by H1. +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # Should be handled by H1. +END| + +CALL p6()| +SignalId +S1 +HandlerId +H1 +ERROR HY000: Unhandled user-defined exception condition + +# -- Check that handlers don't handle its own warnings. + +CREATE PROCEDURE p7() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +SELECT 'H1' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE '01000'; # Should be handled by H1. +END| + +CALL p7()| +SignalId +S1 +HandlerId +H1 +Warnings: +Warning 1642 Unhandled user-defined warning condition + +# -- Check that conditions for handlers are not handled by the handlers +# -- from the same block. + +CREATE PROCEDURE p8() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +SELECT 'H2' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. +END| + +CALL p8()| +SignalId +S1 +HandlerId +H2 +Warnings: +Warning 1642 Unhandled user-defined warning condition + +# -- Check that conditions for handlers are not handled by the handlers +# -- from the same block even if they are thrown deep down the stack. + +CREATE PROCEDURE p9() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H1:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H1:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H2:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H2:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H3:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H3:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H4:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H4:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H5:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H5:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H6:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H6:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +SELECT 'H2' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. +END; +SELECT 'S6' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S5' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S4' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S3' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S2' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. +END| + +CALL p9()| +SignalId +S1 +SignalId +S2 +SignalId +S3 +SignalId +S4 +SignalId +S5 +SignalId +S6 +HandlerId +H2 +Warnings: +Warning 1642 Unhandled user-defined warning condition + +# -- Check that handlers are choosen properly in case of deep stack and +# -- nested SQL-blocks. + +CREATE PROCEDURE p10() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H2' AS HandlerId; +BEGIN +BEGIN +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H1:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H1:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H2:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H2:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H3:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H3:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H4:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H4:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H5:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H5:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H6:1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'Wrong:H6:2' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +BEGIN +SELECT 'H2' AS HandlerId; +SIGNAL SQLSTATE '01000'; # Should be handled by H1. +END; +SELECT 'S6' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S5' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S4' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S3' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S2' AS SignalId; +SIGNAL SQLSTATE 'HY000'; +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. +END; +END; +END; +END| + +CALL p10()| +SignalId +S1 +SignalId +S2 +SignalId +S3 +SignalId +S4 +SignalId +S5 +SignalId +S6 +HandlerId +H2 +HandlerId +H1 + +# -- Test stored procedure from Peter's mail. + +CREATE PROCEDURE p11() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H1' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H2' AS HandlerId; +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01000', 1249 +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION +SELECT 'H3' AS HandlerId; +DECLARE CONTINUE HANDLER FOR SQLWARNING +SELECT 'H4' AS HandlerId; +BEGIN +SELECT 'H5' AS HandlerId; +SELECT 'S3' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # H3 +SELECT 'S4' AS SignalId; +SIGNAL SQLSTATE '22003'; # H3 +SELECT 'S5' AS SignalId; +SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H4 +END; +END; +SELECT 'S6' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # H1 +SELECT 'S7' AS SignalId; +SIGNAL SQLSTATE '22003'; # H1 +SELECT 'S8' AS SignalId; +SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H5 +END; +SELECT 'S1' AS SignalId; +SIGNAL SQLSTATE 'HY000'; # H1 +SELECT 'S2' AS SignalId; +SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H2 +END| + +CALL p11()| +SignalId +S6 +HandlerId +H1 +SignalId +S7 +HandlerId +H1 +SignalId +S8 +HandlerId +H5 +SignalId +S3 +HandlerId +H3 +SignalId +S4 +HandlerId +H3 +SignalId +S5 +HandlerId +H4 +SignalId +S1 +HandlerId +H1 +SignalId +S2 +HandlerId +H2 + +# -- Check that runtime stack-trace can be deeper than parsing-time one. + +CREATE PROCEDURE p12() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN +DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN +SELECT 'H1:5' AS HandlerId; +SIGNAL SQLSTATE '01002'; +END; +SELECT 'H1:4' AS HandlerId; +SIGNAL SQLSTATE '01001'; +END; +SELECT 'H1:3' AS HandlerId; +SIGNAL SQLSTATE '01001'; +END; +SELECT 'H1:2' AS HandlerId; +SIGNAL SQLSTATE '01001'; +END; +SELECT 'H1:1' AS HandlerId; +SIGNAL SQLSTATE '01001'; +END; +######################################################### +DECLARE CONTINUE HANDLER FOR SQLSTATE '01002' + SELECT 'OK' AS Msg; +######################################################### +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +SELECT 'H2:5' AS HandlerId; +SIGNAL SQLSTATE '01001'; +END; +SELECT 'H2:4' AS HandlerId; +SIGNAL SQLSTATE '01000'; +END; +SELECT 'H2:3' AS HandlerId; +SIGNAL SQLSTATE '01000'; +END; +SELECT 'H2:2' AS HandlerId; +SIGNAL SQLSTATE '01000'; +END; +SELECT 'H2:1' AS HandlerId; +SIGNAL SQLSTATE '01000'; +END; +####################################################### +SELECT 'Throw 01000' AS Msg; +SIGNAL SQLSTATE '01000'; +END; +END| + +CALL p12()| +Msg +Throw 01000 +HandlerId +H2:1 +HandlerId +H2:2 +HandlerId +H2:3 +HandlerId +H2:4 +HandlerId +H2:5 +HandlerId +H1:1 +HandlerId +H1:2 +HandlerId +H1:3 +HandlerId +H1:4 +HandlerId +H1:5 +Warnings: +Warning 1642 Unhandled user-defined warning condition + +# -- Check that handler-call-frames are removed properly for EXIT +# -- handlers. + +CREATE PROCEDURE p13() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING +BEGIN +DECLARE EXIT HANDLER FOR SQLWARNING +BEGIN +SELECT 'EXIT handler 3' AS Msg; +END; +SELECT 'CONTINUE handler 2: 1' AS Msg; +SIGNAL SQLSTATE '01000'; +SELECT 'CONTINUE handler 2: 2' AS Msg; +END; +SELECT 'CONTINUE handler 1: 1' AS Msg; +SIGNAL SQLSTATE '01000'; +SELECT 'CONTINUE handler 1: 2' AS Msg; +END; +SELECT 'Throw 01000' AS Msg; +SIGNAL SQLSTATE '01000'; +END| + +CALL p13()| +Msg +Throw 01000 +Msg +CONTINUE handler 1: 1 +Msg +CONTINUE handler 2: 1 +Msg +EXIT handler 3 +Msg +CONTINUE handler 1: 2 + +# That's it. Cleanup. + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; +DROP PROCEDURE p7; +DROP PROCEDURE p8; +DROP PROCEDURE p9; +DROP PROCEDURE p10; +DROP PROCEDURE p11; +DROP PROCEDURE p12; +DROP PROCEDURE p13; + +# Bug#12731619: NESTED SP HANDLERS CAN TRIGGER ASSERTION + +DROP FUNCTION IF EXISTS f1; +DROP TABLE IF EXISTS t1; +CREATE TABLE t1(msg VARCHAR(255)); +CREATE FUNCTION f1() RETURNS INT +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION # handler 1 +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION # handler 2 +BEGIN +INSERT INTO t1 VALUE('WRONG: Inside H2'); +RETURN 2; +END; +INSERT INTO t1 VALUE('CORRECT: Inside H1'); +RETURN 1; +END; +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING # handler 3 +BEGIN +INSERT INTO t1 VALUE('WRONG: Inside H3'); +RETURN 3; +END; +INSERT INTO t1 VALUE('CORRECT: Calling f1()'); +RETURN f1(); # -- exception here +END; +INSERT INTO t1 VALUE('WRONG: Returning 10'); +RETURN 10; +END| + +SELECT f1(); +f1() +1 + +SELECT * FROM t1; +msg +CORRECT: Calling f1() +CORRECT: Inside H1 + +DROP FUNCTION f1; +DROP TABLE t1; + +# Check that handled SQL-conditions are properly cleared from DA. + +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP PROCEDURE IF EXISTS p5; +CREATE TABLE t1(a CHAR, b CHAR, c CHAR); +CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT); + +# Check that SQL-conditions for which SQL-handler has been invoked, +# are cleared from the Diagnostics Area. Note, there might be several +# SQL-conditions, but SQL-handler must be invoked only once. + +CREATE PROCEDURE p1() +BEGIN +DECLARE EXIT HANDLER FOR SQLWARNING +SELECT 'Warning caught' AS msg; +# The INSERT below raises 3 SQL-conditions (warnings). The EXIT HANDLER +# above must be invoked once (for one condition), but all three conditions +# must be cleared from the Diagnostics Area. +INSERT INTO t1 VALUES('qqqq', 'ww', 'eee'); +# The following INSERT will not be executed, because of the EXIT HANDLER. +INSERT INTO t1 VALUES('zzz', 'xx', 'yyyy'); +END| + +CALL p1()| +msg +Warning caught + +SELECT * FROM t1| +a b c +q w e + +# Check that SQL-conditions for which SQL-handler has *not* been +# invoked, are *still* cleared from the Diagnostics Area. + +CREATE PROCEDURE p2() +BEGIN +DECLARE CONTINUE HANDLER FOR 1292 +SELECT 'Warning 1292 caught' AS msg; +# The following INSERT raises 6 SQL-warnings with code 1292, +# and 3 SQL-warnings with code 1264. The CONTINUE HANDLER above must be +# invoked once, and all nine SQL-warnings must be cleared from +# the Diagnostics Area. +INSERT INTO t2 +SELECT +CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +CALL p2()| +msg +Warning 1292 caught + +# Check that if there are two equally ranked SQL-handlers to handle +# SQL-conditions from SQL-statement, only one of them will be invoked. + +CREATE PROCEDURE p3() +BEGIN +DECLARE CONTINUE HANDLER FOR 1292 +SELECT 'Warning 1292 caught' AS msg; +DECLARE CONTINUE HANDLER FOR 1264 +SELECT 'Warning 1264 caught' AS msg; +# The following INSERT raises 6 SQL-warnings with code 1292, +# and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above +# must be called, and only once. The SQL Standard does not define, which one +# should be invoked. +INSERT INTO t2 +SELECT +CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +CALL p3()| +msg +Warning 1264 caught + +# The same as p3, but 1264 comes first. + +CREATE PROCEDURE p4() +BEGIN +DECLARE CONTINUE HANDLER FOR 1292 +SELECT 'Warning 1292 caught' AS msg; +DECLARE CONTINUE HANDLER FOR 1264 +SELECT 'Warning 1264 caught' AS msg; +# The following INSERT raises 4 SQL-warnings with code 1292, +# and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above +# must be called, and only once. The SQL Standard does not define, which one +# should be invoked. +INSERT INTO t2 +SELECT +CAST(999999 AS SIGNED INTEGER), +CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +CALL p4()| +msg +Warning 1264 caught + +# Check that if a SQL-handler raised its own SQL-conditions, there are +# preserved after handler exit. + +CREATE PROCEDURE p5() +BEGIN +DECLARE EXIT HANDLER FOR 1292 +BEGIN +SELECT 'Handler for 1292 (1)' AS Msg; +SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1234; +SHOW WARNINGS; +SELECT 'Handler for 1292 (2)' AS Msg; +END; +INSERT INTO t2 +SELECT +CAST(999999 AS SIGNED INTEGER), +CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +CALL p5()| +Msg +Handler for 1292 (1) +Level Code Message +Warning 1234 Unhandled user-defined warning condition +Msg +Handler for 1292 (2) +Warnings: +Warning 1234 Unhandled user-defined warning condition + +# Check that SQL-conditions are available inside the handler, but +# cleared after the handler exits. + +CREATE PROCEDURE p6() +BEGIN +DECLARE CONTINUE HANDLER FOR 1292 +BEGIN +SHOW WARNINGS; +SELECT 'Handler for 1292' Msg; +END; +INSERT INTO t2 +SELECT +CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), +CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +CALL p6()| +Level Code Message +Warning 1292 Truncated incorrect INTEGER value: '1 ' +Warning 1292 Truncated incorrect INTEGER value: '1999999 ' +Warning 1264 Out of range value for column 'a' at row 1 +Warning 1292 Truncated incorrect INTEGER value: '2 ' +Warning 1292 Truncated incorrect INTEGER value: '2999999 ' +Warning 1264 Out of range value for column 'b' at row 1 +Warning 1292 Truncated incorrect INTEGER value: '3 ' +Warning 1292 Truncated incorrect INTEGER value: '3999999 ' +Warning 1264 Out of range value for column 'c' at row 1 +Msg +Handler for 1292 + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; +DROP TABLE t1; +DROP TABLE t2; + +# Bug#13059316: ASSERTION FAILURE IN SP_RCONTEXT.CC +# Check DECLARE statements that raise conditions before handlers +# are declared. + +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +CREATE PROCEDURE p1() +BEGIN +DECLARE var1 INTEGER DEFAULT 'string'; +DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H1'; +END| + +CALL p1()| +Warnings: +Warning 1366 Incorrect integer value: 'string' for column 'var1' at row 1 + +CREATE PROCEDURE p2() +BEGIN +DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H2'; +CALL p1(); +END| + +CALL p2()| +H2 +H2 + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +# +# Bug#13113222 RQG_SIGNAL_RESIGNAL FAILED WITH ASSERTION. +# +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +CREATE PROCEDURE p1() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'triggered p1'; +# This will trigger an error. +SIGNAL SQLSTATE 'HY000'; +END| +CREATE PROCEDURE p2() +BEGIN +DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'triggered p2'; +# This will trigger a warning. +SIGNAL SQLSTATE '01000'; +END| +SET @old_max_error_count= @@session.max_error_count; +SET SESSION max_error_count= 0; +CALL p1(); +triggered p1 +triggered p1 +CALL p2(); +SET SESSION max_error_count= @old_max_error_count; +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +# Bug#12652873: 61392: Continue handler for NOT FOUND being triggered +# from internal stored function. + +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP TABLE IF EXISTS t1; + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1, 2); + +# f1() raises NOT_FOUND condition. +# Raising NOT_FOUND can not be simulated by SIGNAL, +# because SIGNAL would raise SQL-error in that case. + +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN +DECLARE v VARCHAR(5) DEFAULT -1; +SELECT b FROM t1 WHERE a = 2 INTO v; +RETURN v; +END| + +# Here we check that the NOT_FOUND condition raised in f1() +# is not visible in the outer function (f2), i.e. the continue +# handler in f2() will not be called. + +CREATE FUNCTION f2() RETURNS INTEGER +BEGIN +DECLARE v INTEGER; +DECLARE CONTINUE HANDLER FOR NOT FOUND +SET @msg = 'Handler activated.'; +SELECT f1() INTO v; +RETURN v; +END| +SET @msg = ''; + +SELECT f2(); +f2() +-1 + +SELECT @msg; +@msg + + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1; diff --git a/mysql-test/t/signal.test b/mysql-test/t/signal.test index 13a0db2029b..31bc7bc9633 100644 --- a/mysql-test/t/signal.test +++ b/mysql-test/t/signal.test @@ -1551,15 +1551,24 @@ drop procedure test_signal $$ --echo # Test where SIGNAL can be used --echo # +--echo +--echo # RETURN statement clears Diagnostics Area, thus +--echo # the warnings raised in a stored function are not +--echo # visible outsidef the stored function. So, we're using +--echo # @@warning_count variable to check that SIGNAL succeeded. +--echo + create function test_signal_func() returns integer begin + DECLARE v INT; DECLARE warn CONDITION FOR SQLSTATE "01XXX"; SIGNAL warn SET MESSAGE_TEXT = "This function SIGNAL a warning", MYSQL_ERRNO = 1012; - return 5; + SELECT @@warning_count INTO v; + return v; end $$ select test_signal_func() $$ diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index 063b30c01cb..711e639191e 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -2881,3 +2881,973 @@ SHOW WARNINGS; DROP TABLE t1; DROP TABLE t2; DROP PROCEDURE p1; + +--echo +--echo ################################################################### +--echo # Tests for the following bugs: +--echo # - Bug#11763171: 55852 - Possibly inappropriate handler activation. +--echo # - Bug#11749343: 38806 - Wrong scope for SQL HANDLERS in SP. +--echo ################################################################### +--echo + +# +# Structure of SQL-block: +# BEGIN +# <Handler declaration block> +# <Statement block> +# END +# +# Scope of Handler-decl-block is Statement-block. +# I.e. SQL-conditions thrown in the Handler-decl-block can not be handled by +# the same block, only by outer SQL-blocks. +# +# This rule is recursive, i.e. if a Handler-decl-block has nested SQL-blocks, +# the SQL-conditions from those nested blocks can not be handled by the this +# Handler-decl-block, only by outer SQL-blocks. +# + +delimiter |; + +--echo +--echo # -- Check that SQL-conditions thrown by Statement-blocks are +--echo # -- handled by Handler-decl blocks properly. +--echo + +CREATE PROCEDURE p1() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H2' AS HandlerId; + + SIGNAL SQLSTATE '01000'; # Should be handled by H2. +END| + +--echo +CALL p1()| + +--echo +--echo # -- Check that SQL-conditions thrown by Statement-blocks are +--echo # -- handled by Handler-decl blocks properly in case of nested +--echo # -- SQL-blocks. +--echo + +CREATE PROCEDURE p2() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H2' AS HandlerId; + + BEGIN + + SELECT 'B1' AS BlockId; + BEGIN + + SELECT 'B2' AS BlockId; + BEGIN + SELECT 'B3' AS BlockId; + SIGNAL SQLSTATE '01000'; # Should be handled by H2. + END; + + END; + + END; + +END| + +--echo +CALL p2()| + +--echo +--echo # -- Check SQL-handler resolution rules. +--echo + +CREATE PROCEDURE p3() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H3' AS HandlerId; + + SIGNAL SQLSTATE '01000'; # Should be handled by H3. +END| + +--echo +CALL p3()| +--echo + +CREATE PROCEDURE p4() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H3' AS HandlerId; + + SIGNAL SQLSTATE '01000'; # Should be handled by H2. +END| + +--echo +CALL p4()| +--echo + +CREATE PROCEDURE p5() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H2' AS HandlerId; + + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H3' AS HandlerId; + + SIGNAL SQLSTATE '01000'; # Should be handled by H3. + END; +END| + +--echo +CALL p5()| + +--echo +--echo # -- Check that handlers don't handle its own exceptions. +--echo + +CREATE PROCEDURE p6() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + SELECT 'H1' AS HandlerId; + SIGNAL SQLSTATE 'HY000'; # Should *not* be handled by H1. + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # Should be handled by H1. +END| + +--echo +--error ER_SIGNAL_EXCEPTION +CALL p6()| + +--echo +--echo # -- Check that handlers don't handle its own warnings. +--echo + +CREATE PROCEDURE p7() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + SELECT 'H1' AS HandlerId; + SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE '01000'; # Should be handled by H1. +END| + +--echo +CALL p7()| + +--echo +--echo # -- Check that conditions for handlers are not handled by the handlers +--echo # -- from the same block. +--echo + +CREATE PROCEDURE p8() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + SELECT 'H2' AS HandlerId; + SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. +END| + +--echo +CALL p8()| + +--echo +--echo # -- Check that conditions for handlers are not handled by the handlers +--echo # -- from the same block even if they are thrown deep down the stack. +--echo + +CREATE PROCEDURE p9() +BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H1:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H1:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H2:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H2:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H3:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H3:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H4:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H4:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H5:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H5:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H6:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H6:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + SELECT 'H2' AS HandlerId; + SIGNAL SQLSTATE '01000'; # Should *not* be handled by H1. + END; + + SELECT 'S6' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + END; + + SELECT 'S5' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S4' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S3' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S2' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. + +END| + +--echo +CALL p9()| + +--echo +--echo # -- Check that handlers are choosen properly in case of deep stack and +--echo # -- nested SQL-blocks. +--echo + +CREATE PROCEDURE p10() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H2' AS HandlerId; + + BEGIN + BEGIN + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H1:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H1:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H2:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H2:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H3:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H3:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H4:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H4:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H5:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H5:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000' + SELECT 'Wrong:H6:1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'Wrong:H6:2' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + BEGIN + SELECT 'H2' AS HandlerId; + SIGNAL SQLSTATE '01000'; # Should be handled by H1. + END; + + SELECT 'S6' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + END; + + SELECT 'S5' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S4' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S3' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S2' AS SignalId; + SIGNAL SQLSTATE 'HY000'; + + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # Should be handled by H2. + + END; + END; + END; +END| + +--echo +CALL p10()| + +--echo +--echo # -- Test stored procedure from Peter's mail. +--echo + +CREATE PROCEDURE p11() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H1' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H2' AS HandlerId; + + BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01000', 1249 + BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION + SELECT 'H3' AS HandlerId; + + DECLARE CONTINUE HANDLER FOR SQLWARNING + SELECT 'H4' AS HandlerId; + + BEGIN + SELECT 'H5' AS HandlerId; + + SELECT 'S3' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # H3 + + SELECT 'S4' AS SignalId; + SIGNAL SQLSTATE '22003'; # H3 + + SELECT 'S5' AS SignalId; + SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H4 + END; + END; + + SELECT 'S6' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # H1 + + SELECT 'S7' AS SignalId; + SIGNAL SQLSTATE '22003'; # H1 + + SELECT 'S8' AS SignalId; + SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H5 + END; + + SELECT 'S1' AS SignalId; + SIGNAL SQLSTATE 'HY000'; # H1 + + SELECT 'S2' AS SignalId; + SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1249; # H2 +END| + +--echo +CALL p11()| + +--echo +--echo # -- Check that runtime stack-trace can be deeper than parsing-time one. +--echo + +CREATE PROCEDURE p12() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN + DECLARE CONTINUE HANDLER FOR SQLSTATE '01001' + BEGIN + SELECT 'H1:5' AS HandlerId; + SIGNAL SQLSTATE '01002'; + END; + SELECT 'H1:4' AS HandlerId; + SIGNAL SQLSTATE '01001'; + END; + SELECT 'H1:3' AS HandlerId; + SIGNAL SQLSTATE '01001'; + END; + SELECT 'H1:2' AS HandlerId; + SIGNAL SQLSTATE '01001'; + END; + SELECT 'H1:1' AS HandlerId; + SIGNAL SQLSTATE '01001'; + END; + + ######################################################### + + DECLARE CONTINUE HANDLER FOR SQLSTATE '01002' + SELECT 'OK' AS Msg; + + ######################################################### + + BEGIN + + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + SELECT 'H2:5' AS HandlerId; + SIGNAL SQLSTATE '01001'; + END; + SELECT 'H2:4' AS HandlerId; + SIGNAL SQLSTATE '01000'; + END; + SELECT 'H2:3' AS HandlerId; + SIGNAL SQLSTATE '01000'; + END; + SELECT 'H2:2' AS HandlerId; + SIGNAL SQLSTATE '01000'; + END; + SELECT 'H2:1' AS HandlerId; + SIGNAL SQLSTATE '01000'; + END; + + ####################################################### + + SELECT 'Throw 01000' AS Msg; + SIGNAL SQLSTATE '01000'; + END; + +END| + +--echo +CALL p12()| + +--echo +--echo # -- Check that handler-call-frames are removed properly for EXIT +--echo # -- handlers. +--echo + +CREATE PROCEDURE p13() +BEGIN + + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING + BEGIN + DECLARE EXIT HANDLER FOR SQLWARNING + BEGIN + SELECT 'EXIT handler 3' AS Msg; + END; + + SELECT 'CONTINUE handler 2: 1' AS Msg; + SIGNAL SQLSTATE '01000'; + SELECT 'CONTINUE handler 2: 2' AS Msg; + END; + + SELECT 'CONTINUE handler 1: 1' AS Msg; + SIGNAL SQLSTATE '01000'; + SELECT 'CONTINUE handler 1: 2' AS Msg; + END; + + SELECT 'Throw 01000' AS Msg; + SIGNAL SQLSTATE '01000'; +END| + +--echo +CALL p13()| + +delimiter ;| + +--echo +--echo # That's it. Cleanup. +--echo + +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; +DROP PROCEDURE p7; +DROP PROCEDURE p8; +DROP PROCEDURE p9; +DROP PROCEDURE p10; +DROP PROCEDURE p11; +DROP PROCEDURE p12; +DROP PROCEDURE p13; + +--echo +--echo # Bug#12731619: NESTED SP HANDLERS CAN TRIGGER ASSERTION +--echo + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP TABLE IF EXISTS t1; +--enable_warnings + +CREATE TABLE t1(msg VARCHAR(255)); + +delimiter |; +CREATE FUNCTION f1() RETURNS INT +BEGIN + + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION # handler 1 + BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION # handler 2 + BEGIN + INSERT INTO t1 VALUE('WRONG: Inside H2'); + RETURN 2; + END; + + INSERT INTO t1 VALUE('CORRECT: Inside H1'); + RETURN 1; + END; + + BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING # handler 3 + BEGIN + INSERT INTO t1 VALUE('WRONG: Inside H3'); + RETURN 3; + END; + + INSERT INTO t1 VALUE('CORRECT: Calling f1()'); + RETURN f1(); # -- exception here + END; + + INSERT INTO t1 VALUE('WRONG: Returning 10'); + RETURN 10; + +END| + +delimiter ;| + +--echo +SELECT f1(); +--echo +SELECT * FROM t1; +--echo + +DROP FUNCTION f1; +DROP TABLE t1; + + +--echo +--echo # Check that handled SQL-conditions are properly cleared from DA. +--echo + +--disable_warnings +DROP TABLE IF EXISTS t1; +DROP TABLE IF EXISTS t2; +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +DROP PROCEDURE IF EXISTS p3; +DROP PROCEDURE IF EXISTS p4; +DROP PROCEDURE IF EXISTS p5; +--enable_warnings + +CREATE TABLE t1(a CHAR, b CHAR, c CHAR); +CREATE TABLE t2(a SMALLINT, b SMALLINT, c SMALLINT); + +delimiter |; + +--echo +--echo # Check that SQL-conditions for which SQL-handler has been invoked, +--echo # are cleared from the Diagnostics Area. Note, there might be several +--echo # SQL-conditions, but SQL-handler must be invoked only once. +--echo + +CREATE PROCEDURE p1() +BEGIN + DECLARE EXIT HANDLER FOR SQLWARNING + SELECT 'Warning caught' AS msg; + + # The INSERT below raises 3 SQL-conditions (warnings). The EXIT HANDLER + # above must be invoked once (for one condition), but all three conditions + # must be cleared from the Diagnostics Area. + + INSERT INTO t1 VALUES('qqqq', 'ww', 'eee'); + + # The following INSERT will not be executed, because of the EXIT HANDLER. + + INSERT INTO t1 VALUES('zzz', 'xx', 'yyyy'); +END| + +--echo +CALL p1()| +--echo +SELECT * FROM t1| + +--echo +--echo # Check that SQL-conditions for which SQL-handler has *not* been +--echo # invoked, are *still* cleared from the Diagnostics Area. +--echo + +CREATE PROCEDURE p2() +BEGIN + DECLARE CONTINUE HANDLER FOR 1292 + SELECT 'Warning 1292 caught' AS msg; + + # The following INSERT raises 6 SQL-warnings with code 1292, + # and 3 SQL-warnings with code 1264. The CONTINUE HANDLER above must be + # invoked once, and all nine SQL-warnings must be cleared from + # the Diagnostics Area. + + INSERT INTO t2 + SELECT + CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +--echo +CALL p2()| + +--echo +--echo # Check that if there are two equally ranked SQL-handlers to handle +--echo # SQL-conditions from SQL-statement, only one of them will be invoked. +--echo + +CREATE PROCEDURE p3() +BEGIN + DECLARE CONTINUE HANDLER FOR 1292 + SELECT 'Warning 1292 caught' AS msg; + + DECLARE CONTINUE HANDLER FOR 1264 + SELECT 'Warning 1264 caught' AS msg; + + # The following INSERT raises 6 SQL-warnings with code 1292, + # and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above + # must be called, and only once. The SQL Standard does not define, which one + # should be invoked. + + INSERT INTO t2 + SELECT + CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +--echo +CALL p3()| + +--echo +--echo # The same as p3, but 1264 comes first. +--echo + +CREATE PROCEDURE p4() +BEGIN + DECLARE CONTINUE HANDLER FOR 1292 + SELECT 'Warning 1292 caught' AS msg; + + DECLARE CONTINUE HANDLER FOR 1264 + SELECT 'Warning 1264 caught' AS msg; + + # The following INSERT raises 4 SQL-warnings with code 1292, + # and 3 SQL-warnings with code 1264. Only one of the CONTINUE HANDLERs above + # must be called, and only once. The SQL Standard does not define, which one + # should be invoked. + + INSERT INTO t2 + SELECT + CAST(999999 AS SIGNED INTEGER), + CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +--echo +CALL p4()| + +--echo +--echo # Check that if a SQL-handler raised its own SQL-conditions, there are +--echo # preserved after handler exit. +--echo + +CREATE PROCEDURE p5() +BEGIN + DECLARE EXIT HANDLER FOR 1292 + BEGIN + SELECT 'Handler for 1292 (1)' AS Msg; + SIGNAL SQLSTATE '01000' SET MYSQL_ERRNO = 1234; + SHOW WARNINGS; + SELECT 'Handler for 1292 (2)' AS Msg; + END; + + INSERT INTO t2 + SELECT + CAST(999999 AS SIGNED INTEGER), + CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +--echo +CALL p5()| + +--echo +--echo # Check that SQL-conditions are available inside the handler, but +--echo # cleared after the handler exits. +--echo + +CREATE PROCEDURE p6() +BEGIN + DECLARE CONTINUE HANDLER FOR 1292 + BEGIN + SHOW WARNINGS; + SELECT 'Handler for 1292' Msg; + END; + + INSERT INTO t2 + SELECT + CAST(CONCAT(CAST('1 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('2 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER), + CAST(CONCAT(CAST('3 ' AS UNSIGNED INTEGER), '999999 ') AS SIGNED INTEGER); +END| + +--echo +CALL p6()| + +delimiter ;| + +--echo +DROP PROCEDURE p1; +DROP PROCEDURE p2; +DROP PROCEDURE p3; +DROP PROCEDURE p4; +DROP PROCEDURE p5; +DROP PROCEDURE p6; +DROP TABLE t1; +DROP TABLE t2; + +--echo +--echo # Bug#13059316: ASSERTION FAILURE IN SP_RCONTEXT.CC +--echo # Check DECLARE statements that raise conditions before handlers +--echo # are declared. +--echo + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +--enable_warnings + +delimiter |; + +CREATE PROCEDURE p1() +BEGIN + DECLARE var1 INTEGER DEFAULT 'string'; + DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H1'; +END| + +--echo +CALL p1()| +--echo + +CREATE PROCEDURE p2() +BEGIN + DECLARE EXIT HANDLER FOR SQLWARNING SELECT 'H2'; + CALL p1(); +END| + +--echo +CALL p2()| + +delimiter ;| + +--echo +DROP PROCEDURE p1; +DROP PROCEDURE p2; + + +--echo # +--echo # Bug#13113222 RQG_SIGNAL_RESIGNAL FAILED WITH ASSERTION. +--echo # + +--disable_warnings +DROP PROCEDURE IF EXISTS p1; +DROP PROCEDURE IF EXISTS p2; +--enable_warnings + +delimiter |; +CREATE PROCEDURE p1() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'triggered p1'; + # This will trigger an error. + SIGNAL SQLSTATE 'HY000'; +END| + +CREATE PROCEDURE p2() +BEGIN + DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'triggered p2'; + # This will trigger a warning. + SIGNAL SQLSTATE '01000'; +END| +delimiter ;| + +SET @old_max_error_count= @@session.max_error_count; +SET SESSION max_error_count= 0; +CALL p1(); +CALL p2(); +SET SESSION max_error_count= @old_max_error_count; + +DROP PROCEDURE p1; +DROP PROCEDURE p2; + +--echo +--echo # Bug#12652873: 61392: Continue handler for NOT FOUND being triggered +--echo # from internal stored function. +--echo + +--disable_warnings +DROP FUNCTION IF EXISTS f1; +DROP FUNCTION IF EXISTS f2; +DROP TABLE IF EXISTS t1; +--enable_warnings + +--echo + +CREATE TABLE t1 (a INT, b INT); +INSERT INTO t1 VALUES (1, 2); + +delimiter |; + +--echo +--echo # f1() raises NOT_FOUND condition. +--echo # Raising NOT_FOUND can not be simulated by SIGNAL, +--echo # because SIGNAL would raise SQL-error in that case. +--echo + +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN + DECLARE v VARCHAR(5) DEFAULT -1; + SELECT b FROM t1 WHERE a = 2 INTO v; + RETURN v; +END| + +--echo +--echo # Here we check that the NOT_FOUND condition raised in f1() +--echo # is not visible in the outer function (f2), i.e. the continue +--echo # handler in f2() will not be called. +--echo + +CREATE FUNCTION f2() RETURNS INTEGER +BEGIN + DECLARE v INTEGER; + + DECLARE CONTINUE HANDLER FOR NOT FOUND + SET @msg = 'Handler activated.'; + + SELECT f1() INTO v; + + RETURN v; +END| + +delimiter ;| + +SET @msg = ''; + +--echo +SELECT f2(); +--echo +SELECT @msg; +--echo + +DROP FUNCTION f1; +DROP FUNCTION f2; +DROP TABLE t1; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 48088cefc1c..045051c0b14 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -3391,6 +3391,14 @@ int sp_instr_freturn::exec_core(THD *thd, uint *nextp) { /* + RETURN is a "procedure statement" (in terms of the SQL standard). + That means, Diagnostics Area should be clean before its execution. + */ + + Diagnostics_area *da= thd->get_stmt_da(); + da->clear_warning_info(da->warning_info_id()); + + /* Change <next instruction pointer>, so that this will be the last instruction in the stored function. */ diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index afec3921a9b..6b1b0730548 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -233,6 +233,23 @@ bool sp_rcontext::handle_sql_condition(THD *thd, if (found_handler) found_condition= da->get_error_condition(); + + /* + Found condition can be NULL if the diagnostics area was full + when the error was raised. It can also be NULL if + Diagnostics_area::set_error_status(uint sql_error) was used. + In these cases, make a temporary Sql_condition here so the + error can be handled. + */ + if (!found_condition) + { + Sql_condition *condition= + new (callers_arena->mem_root) Sql_condition(callers_arena->mem_root); + condition->set(da->sql_errno(), da->get_sqlstate(), + Sql_condition::WARN_LEVEL_ERROR, + da->message()); + found_condition= condition; + } } else if (da->current_statement_warn_count()) { |