Commit 3cd1861a authored by Sergei Golubchik's avatar Sergei Golubchik

merge bugfuxes for sp-error.test

parent f0502cf8
...@@ -1315,19 +1315,25 @@ drop procedure test_signal $$ ...@@ -1315,19 +1315,25 @@ drop procedure test_signal $$
# #
# Test where SIGNAL can be used # 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 create function test_signal_func() returns integer
begin begin
DECLARE v INT;
DECLARE warn CONDITION FOR SQLSTATE "01XXX"; DECLARE warn CONDITION FOR SQLSTATE "01XXX";
SIGNAL warn SET SIGNAL warn SET
MESSAGE_TEXT = "This function SIGNAL a warning", MESSAGE_TEXT = "This function SIGNAL a warning",
MYSQL_ERRNO = 1012; MYSQL_ERRNO = 1012;
return 5; SELECT @@warning_count INTO v;
return v;
end $$ end $$
select test_signal_func() $$ select test_signal_func() $$
test_signal_func() test_signal_func()
5 1
Warnings:
Warning 1012 This function SIGNAL a warning
drop function test_signal_func $$ drop function test_signal_func $$
create function test_signal_func() returns integer create function test_signal_func() returns integer
begin begin
......
...@@ -1993,3 +1993,878 @@ Error 1048 Column 'c' cannot be null ...@@ -1993,3 +1993,878 @@ Error 1048 Column 'c' cannot be null
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP PROCEDURE p1; 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;
...@@ -1551,15 +1551,24 @@ drop procedure test_signal $$ ...@@ -1551,15 +1551,24 @@ drop procedure test_signal $$
--echo # Test where SIGNAL can be used --echo # Test where SIGNAL can be used
--echo # --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 create function test_signal_func() returns integer
begin begin
DECLARE v INT;
DECLARE warn CONDITION FOR SQLSTATE "01XXX"; DECLARE warn CONDITION FOR SQLSTATE "01XXX";
SIGNAL warn SET SIGNAL warn SET
MESSAGE_TEXT = "This function SIGNAL a warning", MESSAGE_TEXT = "This function SIGNAL a warning",
MYSQL_ERRNO = 1012; MYSQL_ERRNO = 1012;
return 5; SELECT @@warning_count INTO v;
return v;
end $$ end $$
select test_signal_func() $$ select test_signal_func() $$
......
...@@ -2881,3 +2881,973 @@ SHOW WARNINGS; ...@@ -2881,3 +2881,973 @@ SHOW WARNINGS;
DROP TABLE t1; DROP TABLE t1;
DROP TABLE t2; DROP TABLE t2;
DROP PROCEDURE p1; 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;
...@@ -3390,6 +3390,14 @@ sp_instr_freturn::execute(THD *thd, uint *nextp) ...@@ -3390,6 +3390,14 @@ sp_instr_freturn::execute(THD *thd, uint *nextp)
int int
sp_instr_freturn::exec_core(THD *thd, uint *nextp) 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 Change <next instruction pointer>, so that this will be the last
instruction in the stored function. instruction in the stored function.
......
...@@ -233,6 +233,23 @@ bool sp_rcontext::handle_sql_condition(THD *thd, ...@@ -233,6 +233,23 @@ bool sp_rcontext::handle_sql_condition(THD *thd,
if (found_handler) if (found_handler)
found_condition= da->get_error_condition(); 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()) else if (da->current_statement_warn_count())
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment