Commit f203f617 authored by Alexander Nozdrin's avatar Alexander Nozdrin

Auto-merge from mysql-trunk-bugfixing.

******
This patch fixes the following bugs:
  - Bug#5889: Exit handler for a warning doesn't hide the warning in
    trigger
  - Bug#9857: Stored procedures: handler for sqlwarning ignored
  - Bug#23032: Handlers declared in a SP do not handle warnings generated
    in sub-SP
  - Bug#36185: Incorrect precedence for warning and exception handlers

The problem was in the way warnings/errors during stored routine execution
were handled. Prior to this patch the logic was as follows:

  - when a warning/an error happens: if we're executing a stored routine,
    and there is a handler for that warning/error, remember the handler,
    ignore the warning/error and continue execution.

  - after a stored routine instruction is executed: check for a remembered
    handler and activate one (if any).

This logic caused several problems:

  - if one instruction generates several warnings (errors) it's impossible
    to choose the right handler -- a handler for the first generated
    condition was chosen and remembered for activation.

  - mess with handling conditions in scopes different from the current one.

  - not putting generated warnings/errors into Warning Info (Diagnostic
    Area) is against The Standard.

The patch changes the logic as follows:

  - Diagnostic Area is cleared on the beginning of each statement that
    either is able to generate warnings, or is able to work with tables.

  - at the end of a stored routine instruction, Diagnostic Area is left
    intact.

  - Diagnostic Area is checked after each stored routine instruction. If
    an instruction generates several condition, it's now possible to take a
    look at all of them and determine an appropriate handler.

mysql-test/r/signal.result:
  Update result file:
    1. handled conditions are not cleared any more;
    2. reflect changes in signal.test
mysql-test/r/signal_demo3.result:
  Update result file: handled conditions are not cleared any more.
  Due to playing with max_error_count, resulting warning lists
  have changed.
mysql-test/r/sp-big.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/r/sp-bugs.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/r/sp-code.result:
  Update result file:
    1. handled conditions are not cleared any more.
    2. add result for a new test case in sp-code.test.
mysql-test/r/sp-error.result:
  Update result file:
    1. handled conditions are not cleared any more.
    2. add result for a new test case in sp-error.test.
mysql-test/r/sp.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/r/sp_trans.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/r/strict.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/r/view.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/funcs_1/r/innodb_storedproc_02.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/funcs_1/r/memory_storedproc_02.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/funcs_1/r/myisam_storedproc_02.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/funcs_1/r/storedproc.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/rpl/r/rpl_row_sp005.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/rpl/r/rpl_row_sp006_InnoDB.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/suite/rpl/r/rpl_row_trig003.result:
  Update result file: handled conditions are not cleared any more.
mysql-test/t/signal.test:
  Make a test case more readable in the result file.
mysql-test/t/sp-code.test:
  Add a test case for Bug#23032 checking that
  No Data takes precedence on Warning.
mysql-test/t/sp-error.test:
  Adding test cases for:
    - Bug#23032
    - Bug#36185
    - Bug#5889
    - Bug#9857
mysql-test/t/sp.test:
  Fixing test case to reflect behavioral changes made by the patch.
sql/sp_head.cc:
  Reset the per-statement warning count before executing
  a stored procedure instruction.
  
  Move to a separate function code which checks the
  completion status of the executed statement and searches
  for a handler.
  
  Remove redundant code now that search for a handler is
  done after execution, errors are always pushed.
sql/sp_pcontext.h:
  Remove unused code.
sql/sp_rcontext.cc:
  - Polish sp_rcontext::find_handler(): use sp_rcontext::m_hfound instead
    of an extra local variable;
  
  - Remove sp_rcontext::handle_condition();
  
  - Introduce sp_rcontext::activate_handler(), which prepares
    previously found handler for execution.
  
  - Move sp_rcontext::enter_handler() code into activate_handler(),
    because enter_handler() is used only from there;
  
  - Cleanups;
  
  - Introduce DBUG_EXECUTE_IF() for a test case in sp-code.test
sql/sp_rcontext.h:
  - Remove unused code
  - Cleanups
sql/sql_class.cc:
  Merge THD::raise_condition_no_handler() into THD::raise_condition().
  After the patch raise_condition_no_handler() was called
  in raise_condition() only.
sql/sql_class.h:
  Remove raise_condition_no_handler().
sql/sql_error.cc:
  Remove Warning_info::reserve_space() -- handled conditions are not
  cleared any more, so there is no need for RESIGNAL to re-push them.
sql/sql_error.h:
  Remove Warning_info::reserve_space().
sql/sql_signal.cc:
  Handled conditions are not cleared any more,
  so there is no need for RESIGNAL to re-push them.
parent 3ad5e9bd
......@@ -1189,6 +1189,8 @@ end $$
call test_signal() $$
Caught by SQLSTATE
Caught by SQLSTATE
Warnings:
Warning 1012 Raising a warning
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1204,6 +1206,8 @@ end $$
call test_signal() $$
Caught by number
Caught by number
Warnings:
Warning 1012 Raising a warning
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1219,6 +1223,8 @@ end $$
call test_signal() $$
Caught by SQLWARNING
Caught by SQLWARNING
Warnings:
Warning 1012 Raising a warning
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1234,6 +1240,8 @@ end $$
call test_signal() $$
Caught by SQLSTATE
Caught by SQLSTATE
Warnings:
Error 1012 Raising a not found
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1249,6 +1257,8 @@ end $$
call test_signal() $$
Caught by number
Caught by number
Warnings:
Error 1012 Raising a not found
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1264,6 +1274,8 @@ end $$
call test_signal() $$
Caught by NOT FOUND
Caught by NOT FOUND
Warnings:
Error 1012 Raising a not found
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1279,6 +1291,8 @@ end $$
call test_signal() $$
Caught by SQLSTATE
Caught by SQLSTATE
Warnings:
Error 1012 Raising an error
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1294,6 +1308,8 @@ end $$
call test_signal() $$
Caught by number
Caught by number
Warnings:
Error 1012 Raising an error
drop procedure test_signal $$
create procedure test_signal()
begin
......@@ -1309,6 +1325,8 @@ end $$
call test_signal() $$
Caught by SQLEXCEPTION
Caught by SQLEXCEPTION
Warnings:
Error 1012 Raising an error
drop procedure test_signal $$
#
# Test where SIGNAL can be used
......@@ -1455,6 +1473,7 @@ after RESIGNAL
after RESIGNAL
Warnings:
Warning 1012 Raising a warning
Warning 1012 Raising a warning
drop procedure test_resignal $$
create procedure test_resignal()
begin
......@@ -1509,6 +1528,7 @@ after RESIGNAL
after RESIGNAL
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
Warning 1264 Out of range value for column 'a' at row 1
drop procedure test_resignal $$
create procedure test_resignal()
begin
......@@ -1565,6 +1585,7 @@ before RESIGNAL
after RESIGNAL
after RESIGNAL
Warnings:
Warning 1012 Raising a warning
Warning 5555 RESIGNAL of a warning
drop procedure test_resignal $$
create procedure test_resignal()
......@@ -1625,6 +1646,7 @@ before RESIGNAL
after RESIGNAL
after RESIGNAL
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
Warning 5555 RESIGNAL of a warning
drop procedure test_resignal $$
create procedure test_resignal()
......@@ -2126,6 +2148,9 @@ CALL peter_p2() $$
ERROR 42000: Hi, I am a useless error message
show warnings $$
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Hi, I am a useless error message
drop procedure peter_p1 $$
drop procedure peter_p2 $$
......@@ -2135,15 +2160,17 @@ DECLARE x CONDITION FOR SQLSTATE '42000';
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '2';
SHOW WARNINGS;
RESIGNAL x SET MYSQL_ERRNO = 9999;
END;
BEGIN
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '1';
SHOW WARNINGS;
RESIGNAL x SET
SCHEMA_NAME = 'test',
MYSQL_ERRNO= 1231;
MYSQL_ERRNO= 1232;
END;
/* Raises ER_WRONG_VALUE_FOR_VAR : 1231, SQLSTATE 42000 */
SET @@sql_mode=NULL;
......@@ -2156,6 +2183,7 @@ DECLARE x CONDITION for SQLSTATE '42000';
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '3';
SHOW WARNINGS;
RESIGNAL x SET
MESSAGE_TEXT = 'Hi, I am a useless error message',
MYSQL_ERRNO = 9999;
......@@ -2166,15 +2194,24 @@ $$
CALL peter_p2() $$
1
1
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
2
2
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1232 Variable 'sql_mode' can't be set to the value of 'NULL'
3
3
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1232 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
ERROR 42000: Hi, I am a useless error message
show warnings $$
Level Code Message
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1231 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 1232 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Variable 'sql_mode' can't be set to the value of 'NULL'
Error 9999 Hi, I am a useless error message
drop procedure peter_p1 $$
......
......@@ -95,11 +95,11 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
Error 1644 Oops in proc_5
Error 1644 Oops in proc_4
Error 1644 Oops in proc_3
Error 1644 Oops in proc_2
Error 1644 Oops in proc_1
Error 1051 Unknown table 'oops_it_is_not_here'
Error 1644 Oops in proc_9
Error 1644 Oops in proc_8
Error 1644 Oops in proc_7
Error 1644 Oops in proc_6
SET @@session.max_error_count = 7;
SELECT @@session.max_error_count;
@@session.max_error_count
......@@ -108,13 +108,13 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
Error 1051 Unknown table 'oops_it_is_not_here'
Error 1644 Oops in proc_9
Error 1644 Oops in proc_8
Error 1644 Oops in proc_7
Error 1644 Oops in proc_6
Error 1644 Oops in proc_5
Error 1644 Oops in proc_4
Error 1644 Oops in proc_3
Error 1644 Oops in proc_2
Error 1644 Oops in proc_1
SET @@session.max_error_count = 9;
SELECT @@session.max_error_count;
@@session.max_error_count
......@@ -123,6 +123,7 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
Error 1051 Unknown table 'oops_it_is_not_here'
Error 1644 Oops in proc_9
Error 1644 Oops in proc_8
Error 1644 Oops in proc_7
......@@ -131,7 +132,6 @@ Error 1644 Oops in proc_5
Error 1644 Oops in proc_4
Error 1644 Oops in proc_3
Error 1644 Oops in proc_2
Error 1644 Oops in proc_1
drop database demo;
SET @@global.max_error_count = @start_global_value;
SELECT @@global.max_error_count;
......
......@@ -46,6 +46,8 @@ end while;
close cur1;
end|
call p1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select count(*) from t1;
count(*)
256
......
......@@ -43,6 +43,8 @@ END|
SELECT f2 ();
f2 ()
NULL
Warnings:
Error 1305 FUNCTION testdb.f_not_exists does not exist
DROP SCHEMA testdb;
USE test;
#
......
......@@ -711,6 +711,8 @@ looping i
looping 1
looping i
looping 0
Warnings:
Error 1062 Duplicate entry '1' for key 'a'
call proc_26977_works(2);
do something
do something
......@@ -730,6 +732,8 @@ looping i
looping 0
optimizer: keep hreturn
optimizer: keep hreturn
Warnings:
Error 1062 Duplicate entry '2' for key 'a'
drop table t1;
drop procedure proc_26977_broken;
drop procedure proc_26977_works;
......@@ -888,3 +892,56 @@ Pos Instruction
4 jump 6
5 error 1339
DROP PROCEDURE p1;
#
# Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
#
# - Case 4: check that "No Data trumps Warning".
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2), (3);
CREATE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT a FROM t1;
OPEN c;
BEGIN
DECLARE v INT;
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
SELECT "Warning found!";
SHOW WARNINGS;
END;
DECLARE EXIT HANDLER FOR NOT FOUND
BEGIN
SELECT "End of Result Set found!";
SHOW WARNINGS;
END;
WHILE TRUE DO
FETCH c INTO v;
END WHILE;
END;
CLOSE c;
SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
END|
SET SESSION debug="+d,bug23032_emit_warning";
CALL p1();
Warning found!
Warning found!
Level Code Message
Warning 1105 Unknown error
Warning found!
Warning found!
Level Code Message
Warning 1105 Unknown error
Warning found!
Warning found!
Level Code Message
Warning 1105 Unknown error
End of Result Set found!
End of Result Set found!
Level Code Message
Warning 1105 Unknown error
Error 1329 No data - zero rows fetched, selected, or processed
SET SESSION debug="-d,bug23032_emit_warning";
DROP PROCEDURE p1;
DROP TABLE t1;
......@@ -1344,6 +1344,8 @@ set @in_func := 0;
select func_20713_a();
func_20713_a()
NULL
Warnings:
Error 1146 Table 'test.bogus_table_20713' doesn't exist
select @in_func;
@in_func
2
......@@ -1351,6 +1353,8 @@ set @in_func := 0;
select func_20713_b();
func_20713_b()
NULL
Warnings:
Error 1146 Table 'test.bogus_table_20713' doesn't exist
select @in_func;
@in_func
2
......@@ -1714,3 +1718,246 @@ DROP PROCEDURE p1;
DROP VIEW v1;
DROP TABLE t1;
End of 5.1 tests
#
# Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
#
# - Case 1
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;
DROP PROCEDURE IF EXISTS p6;
CREATE PROCEDURE p1()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SELECT 1;
CALL p2();
END|
CREATE PROCEDURE p2()
BEGIN
SELECT CAST('10 ' as unsigned integer);
END|
CALL p1();
CAST('10 ' as unsigned integer)
10
1
1
CAST('10 ' as unsigned integer)
10
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '10 '
DROP PROCEDURE p1;
DROP PROCEDURE p2;
# - Case 2
CREATE PROCEDURE p1()
BEGIN
DECLARE c INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
CALL p2();
CALL p3();
CALL p4();
SELECT c;
SELECT @@warning_count;
SHOW WARNINGS;
END|
CREATE PROCEDURE p2()
BEGIN
SELECT CAST('10 ' as unsigned integer);
END|
CREATE PROCEDURE p3()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SELECT 1;
END|
CREATE PROCEDURE p4()
BEGIN
SELECT CAST('10 ' as unsigned integer);
CALL p2();
END|
CREATE PROCEDURE p5()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SHOW WARNINGS;
END|
CREATE PROCEDURE P6()
BEGIN
DECLARE c INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
CALL p5();
SELECT c;
END|
CALL p1();
CAST('10 ' as unsigned integer)
10
CAST('10 ' as unsigned integer)
10
1
1
CAST('10 ' as unsigned integer)
10
CAST('10 ' as unsigned integer)
10
c
3
@@warning_count
1
Level Code Message
Warning 1292 Truncated incorrect INTEGER value: '10 '
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '10 '
CALL p6();
CAST('10 ' as unsigned integer)
10
Level Code Message
Warning 1292 Truncated incorrect INTEGER value: '10 '
c
1
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '10 '
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP PROCEDURE p4;
DROP PROCEDURE p5;
DROP PROCEDURE p6;
# - Case 3: check that "Exception trumps No Data".
DROP TABLE IF EXISTS t1;
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2), (3);
CREATE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT a FROM t1;
OPEN c;
BEGIN
DECLARE v1 INT;
DECLARE v2 INT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SELECT "Error caught (expected)";
DECLARE EXIT HANDLER FOR NOT FOUND
SELECT "End of Result Set found!";
WHILE TRUE DO
FETCH c INTO v1, v2;
END WHILE;
END;
CLOSE c;
SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
END|
CALL p1();
Error caught (expected)
Error caught (expected)
DROP PROCEDURE p1;
DROP TABLE t1;
#
# Bug#36185: Incorrect precedence for warning and exception handlers
#
DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
CREATE TABLE t1 (a INT, b INT NOT NULL);
CREATE PROCEDURE p1()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'warning';
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'exception';
INSERT INTO t1 VALUES (CAST('10 ' AS SIGNED), NULL);
END|
CALL p1();
exception
exception
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '10 '
Error 1048 Column 'b' cannot be null
DROP TABLE t1;
DROP PROCEDURE p1;
#
# Bug#5889: Exit handler for a warning doesn't hide the warning in trigger
#
# - Case 1
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1, 2);
CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING
SET NEW.a = 10;
SET NEW.a = 99999999999;
END|
UPDATE t1 SET b = 20;
Warnings:
Warning 1264 Out of range value for column 'a' at row 1
SHOW WARNINGS;
Level Code Message
Warning 1264 Out of range value for column 'a' at row 1
SELECT * FROM t1;
a b
10 20
DROP TRIGGER t1_bu;
DROP TABLE t1;
# - Case 2
CREATE TABLE t1(a INT);
CREATE TABLE t2(b CHAR(1));
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
INSERT INTO t2 VALUES('ab'); # Produces a warning.
INSERT INTO t2 VALUES('b'); # Does not produce a warning,
# previous warning should be cleared.
END|
INSERT INTO t1 VALUES(0);
SHOW WARNINGS;
Level Code Message
SELECT * FROM t1;
a
0
SELECT * FROM t2;
b
a
b
DROP TRIGGER t1_bi;
DROP TABLE t1;
DROP TABLE t2;
#
# Bug#9857: Stored procedures: handler for sqlwarning ignored
#
SET @sql_mode_saved = @@sql_mode;
SET sql_mode = traditional;
CREATE PROCEDURE p1()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING
SELECT 'warning caught (expected)';
SELECT 5 / 0;
END|
CREATE PROCEDURE p2()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
SELECT 'error caught (unexpected)';
SELECT 5 / 0;
END|
CALL p1();
5 / 0
NULL
warning caught (expected)
warning caught (expected)
Warnings:
Warning 1365 Division by 0
SHOW WARNINGS;
Level Code Message
Warning 1365 Division by 0
CALL p2();
5 / 0
NULL
Warnings:
Warning 1365 Division by 0
SHOW WARNINGS;
Level Code Message
Warning 1365 Division by 0
DROP PROCEDURE p1;
DROP PROCEDURE p2;
SET sql_mode = @sql_mode_saved;
......@@ -737,6 +737,8 @@ close c;
end|
insert into t2 values ("foo", 42, -1.9), ("bar", 3, 12.1), ("zap", 666, -3.14)|
call cur1()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t1|
id data
foo 40
......@@ -772,6 +774,8 @@ close c1;
close c2;
end|
call cur2()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t3 order by i,s|
s i
bar 3
......@@ -861,6 +865,8 @@ end$
set @@sql_mode = ''|
set sql_select_limit = 1|
call modes(@c1, @c2)|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
set sql_select_limit = default|
select @c1, @c2|
@c1 @c2
......@@ -1682,42 +1688,64 @@ end|
call h_ee()|
h_ee
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_es()|
h_es
Outer (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_en()|
h_en
Outer (good)
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call h_ew()|
h_ew
Outer (good)
call h_ex()|
h_ex
Outer (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_se()|
h_se
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_ss()|
h_ss
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_sn()|
h_sn
Outer (good)
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call h_sw()|
h_sw
Outer (good)
call h_sx()|
h_sx
Outer (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_ne()|
h_ne
Inner (good)
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call h_ns()|
h_ns
Inner (good)
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call h_nn()|
h_nn
Inner (good)
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call h_we()|
h_we
Inner (good)
......@@ -1730,12 +1758,18 @@ Inner (good)
call h_xe()|
h_xe
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_xs()|
h_xs
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
call h_xx()|
h_xx
Inner (good)
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
drop table t3|
drop procedure h_ee|
drop procedure h_es|
......@@ -1884,6 +1918,8 @@ set @x2 = 2;
close c1;
end|
call bug2260()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select @x2|
@x2
2
......@@ -2027,6 +2063,8 @@ insert into t3 values (123456789012);
insert into t3 values (0);
end|
call bug2780()|
Warnings:
Warning 1264 Out of range value for column 's1' at row 1
select @x|
@x
1
......@@ -2449,6 +2487,8 @@ declare continue handler for sqlstate 'HY000' begin end;
select s1 from t3 union select s2 from t3;
end|
call bug4904()|
Warnings:
Error 1267 Illegal mix of collations (latin1_swedish_ci,IMPLICIT) and (latin2_general_ci,IMPLICIT) for operation 'UNION'
drop procedure bug4904|
drop table t3|
drop procedure if exists bug336|
......@@ -2588,13 +2628,17 @@ select row_count()|
row_count()
1
call bug4905()|
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
select row_count()|
row_count()
0
-1
call bug4905()|
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
select row_count()|
row_count()
0
-1
select * from t3|
s1
1
......@@ -2615,10 +2659,14 @@ insert into t3 values (1)|
call bug6029()|
sqlstate 23000
sqlstate 23000
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
delete from t3|
call bug6029()|
1136
1136
Warnings:
Error 1136 Column count doesn't match value count at row 1
drop procedure bug6029|
drop table t3|
drop procedure if exists bug8540|
......@@ -2910,15 +2958,23 @@ end|
call bug6900()|
2
2
Warnings:
Error 1136 Column count doesn't match value count at row 1
call bug9074()|
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
call bug6900_9074(0)|
sqlexception
sqlexception
Warnings:
Error 1136 Column count doesn't match value count at row 1
call bug6900_9074(1)|
23000
23000
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
drop procedure bug6900|
drop procedure bug9074|
drop procedure bug6900_9074|
......@@ -2961,9 +3017,13 @@ delete from t1|
call bug9856()|
16
16
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
call bug9856()|
16
16
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
drop procedure bug9856|
drop procedure if exists bug9674_1|
drop procedure if exists bug9674_2|
......@@ -3194,6 +3254,8 @@ x
2
x
3
Warnings:
Error 1326 Cursor is not open
call bug10961()|
x
1
......@@ -3201,6 +3263,8 @@ x
2
x
3
Warnings:
Error 1326 Cursor is not open
drop procedure bug10961|
DROP PROCEDURE IF EXISTS bug6866|
DROP VIEW IF EXISTS tv|
......@@ -3316,7 +3380,11 @@ insert into t1 values
('Name4', 13),
('Name5', 14)|
call bug11529()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
call bug11529()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
delete from t1|
drop procedure bug11529|
set character set utf8|
......@@ -3490,24 +3558,32 @@ end;
end if;
end|
call bug12168('a')|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t4|
a
1
3
truncate t4|
call bug12168('b')|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t4|
a
2
4
truncate t4|
call bug12168('a')|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t4|
a
1
3
truncate t4|
call bug12168('b')|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select * from t4|
a
2
......@@ -3807,6 +3883,8 @@ end|
call bug7049_2()|
Result
Caught it
Warnings:
Error 1062 Duplicate entry '42' for key 'x'
select * from t3|
x
42
......@@ -3814,12 +3892,16 @@ delete from t3|
call bug7049_4()|
Result
Caught it
Warnings:
Error 1062 Duplicate entry '42' for key 'x'
select * from t3|
x
42
select bug7049_2()|
bug7049_2()
1
Warnings:
Error 1062 Duplicate entry '42' for key 'x'
drop table t3|
drop procedure bug7049_1|
drop procedure bug7049_2|
......@@ -3947,6 +4029,8 @@ end|
call bug14845()|
a
0
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
drop procedure bug14845|
drop procedure if exists bug13549_1|
drop procedure if exists bug13549_2|
......@@ -4150,6 +4234,8 @@ end|
call bug13729()|
55
55
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
select * from t3|
s1
1
......@@ -4186,11 +4272,15 @@ Handler
boo
v isnull(v)
NULL 1
Warnings:
Error 1054 Unknown column 'undefined_var' in 'field list'
call bug14643_2()|
Handler
boo
Handler
boo
Warnings:
Error 1054 Unknown column 'undefined_var' in 'field list'
drop procedure bug14643_1|
drop procedure bug14643_2|
drop procedure if exists bug14304|
......@@ -4514,11 +4604,15 @@ Handler
error
End
done
Warnings:
Error 1054 Unknown column 'v' in 'field list'
call bug14498_2()|
Handler
error
End
done
Warnings:
Error 1054 Unknown column 'v' in 'field list'
call bug14498_3()|
v
maybe
......@@ -4526,16 +4620,22 @@ Handler
error
End
done
Warnings:
Error 1054 Unknown column 'v' in 'field list'
call bug14498_4()|
Handler
error
End
done
Warnings:
Error 1054 Unknown column 'v' in 'field list'
call bug14498_5()|
Handler
error
End
done
Warnings:
Error 1054 Unknown column 'v' in 'field list'
drop procedure bug14498_1|
drop procedure bug14498_2|
drop procedure bug14498_3|
......@@ -4546,6 +4646,8 @@ drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2|
drop procedure if exists bug15231_3|
drop procedure if exists bug15231_4|
drop procedure if exists bug15231_5|
drop procedure if exists bug15231_6|
create table t3 (id int not null)|
create procedure bug15231_1()
begin
......@@ -4568,7 +4670,7 @@ end|
create procedure bug15231_3()
begin
declare exit handler for sqlwarning
select 'Caught it (wrong)' as 'Result';
select 'Caught it (correct)' as 'Result';
call bug15231_4();
end|
create procedure bug15231_4()
......@@ -4576,6 +4678,20 @@ begin
declare x decimal(2,1);
set x = 'zap';
select 'Missed it (correct)' as 'Result';
show warnings;
end|
create procedure bug15231_5()
begin
declare exit handler for sqlwarning
select 'Caught it (wrong)' as 'Result';
call bug15231_6();
end|
create procedure bug15231_6()
begin
declare x decimal(2,1);
set x = 'zap';
select 'Missed it (correct)' as 'Result';
select id from t3;
end|
call bug15231_1()|
1
......@@ -4583,19 +4699,29 @@ Before NOT FOUND condition is triggered
2
After NOT FOUND condtition is triggered
xid xdone
1 0
1 1
Warnings:
Warning 1329 No data - zero rows fetched, selected, or processed
call bug15231_3()|
Result
Missed it (correct)
Level Code Message
Warning 1366 Incorrect decimal value: 'zap' for column 'x' at row 1
Result
Caught it (correct)
Warnings:
Warning 1366 Incorrect decimal value: 'zap' for column 'x' at row 1
drop table if exists t3|
drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2|
drop procedure if exists bug15231_3|
drop procedure if exists bug15231_4|
call bug15231_5()|
Result
Missed it (correct)
id
drop table t3|
drop procedure bug15231_1|
drop procedure bug15231_2|
drop procedure bug15231_3|
drop procedure bug15231_4|
drop procedure bug15231_5|
drop procedure bug15231_6|
drop procedure if exists bug15011|
create table t3 (c1 int primary key)|
insert into t3 values (1)|
......@@ -4613,6 +4739,8 @@ end|
call bug15011()|
Handler
Inner
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
drop procedure bug15011|
drop table t3|
drop procedure if exists bug17476|
......@@ -4688,6 +4816,8 @@ i
1
i
0
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
drop table t3|
drop procedure bug16887|
drop procedure if exists bug16474_1|
......@@ -4760,6 +4890,8 @@ declare continue handler for sqlexception begin end;
select no_such_function();
end|
call bug18787()|
Warnings:
Error 1305 FUNCTION test.no_such_function does not exist
drop procedure bug18787|
create database bug18344_012345678901|
use bug18344_012345678901|
......@@ -5133,6 +5265,8 @@ statement failed
statement failed
statement after update
statement after update
Warnings:
Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
......@@ -5144,6 +5278,8 @@ statement failed
statement failed
statement after update
statement after update
Warnings:
Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
......@@ -5176,6 +5312,8 @@ in continue handler
in continue handler
reachable code a2
reachable code a2
Warnings:
Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
......@@ -5191,6 +5329,8 @@ in continue handler
in continue handler
reachable code a2
reachable code a2
Warnings:
Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
......@@ -5224,6 +5364,8 @@ in continue handler
in continue handler
reachable code a2
reachable code a2
Warnings:
Error 1305 FUNCTION test.no_such_function does not exist
drop procedure bug8153_proc_a|
drop procedure bug8153_proc_b|
drop table t3|
......@@ -5792,9 +5934,13 @@ end|
select func_8407_a()|
func_8407_a()
NULL
Warnings:
Error 1146 Table 'test.no_such_view' doesn't exist
select func_8407_b()|
func_8407_b()
1500
Warnings:
Error 1146 Table 'test.no_such_view' doesn't exist
drop function func_8407_a|
drop function func_8407_b|
drop table if exists table_26503|
......@@ -5916,6 +6062,8 @@ looping i
looping 0
leaving handler
leaving handler
Warnings:
Error 1062 Duplicate entry '1' for key 'a'
call proc_26503_ok_2(2)|
do something
do something
......@@ -5927,6 +6075,8 @@ looping i
looping 4
leaving handler
leaving handler
Warnings:
Error 1062 Duplicate entry '2' for key 'a'
call proc_26503_ok_3(3)|
do something
do something
......@@ -5946,6 +6096,8 @@ looping i
looping 0
leaving handler
leaving handler
Warnings:
Error 1062 Duplicate entry '3' for key 'a'
call proc_26503_ok_4(4)|
do something
do something
......@@ -5957,6 +6109,8 @@ looping i
looping 4
leaving handler
leaving handler
Warnings:
Error 1062 Duplicate entry '4' for key 'a'
drop table table_26503|
drop procedure proc_26503_ok_1|
drop procedure proc_26503_ok_2|
......@@ -6670,6 +6824,8 @@ DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SET @exception:= 'run';
SELECT x FROM t1;
END|
CALL bug29770();
Warnings:
Error 1054 Unknown column 'x' in 'field list'
SELECT @state, @exception;
@state @exception
run NULL
......@@ -6708,6 +6864,8 @@ end;
end while;
end//
call proc_33618(20);
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
drop table t_33618;
drop procedure proc_33618;
#
......
......@@ -99,6 +99,8 @@ return i;
end|
set @error_in_func:= 0|
insert into t1 values (bug10015_6(5)), (bug10015_6(6))|
Warnings:
Error 1062 Duplicate entry '1' for key 'PRIMARY'
select @error_in_func|
@error_in_func
1
......@@ -524,6 +526,8 @@ until done end repeat;
close c;
end|
call bug14210()|
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
select count(*) from t4|
count(*)
256
......
......@@ -1190,6 +1190,8 @@ select'a'; insert into t1 values (200); end;|
call t1();
a
a
Warnings:
Error 1264 Out of range value for column 'col1' at row 1
select * from t1;
col1
drop procedure t1;
......
......@@ -3946,6 +3946,8 @@ create view a as select 1;
end|
call p();
call p();
Warnings:
Error 1050 Table 'a' already exists
drop view a;
drop procedure p;
#
......
......@@ -347,6 +347,8 @@ CALL h1();
-7- 1 1 1 1 1 1
END x1 x2 x3 x4 x5 x6
END 1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
DROP TABLE IF EXISTS tnull;
DROP PROCEDURE IF EXISTS sp1;
CREATE TABLE tnull(f1 int);
......@@ -445,6 +447,8 @@ END//
CALL h2();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
SELECT * FROM res_t1;
w x
a b
......@@ -550,6 +554,8 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
Warnings:
Error 1146 Table 'db_storedproc.tqq' doesn't exist
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
......@@ -580,6 +586,8 @@ END//
CALL h1();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
This will fail, SQLSTATE 00000 is not allowed
CREATE PROCEDURE sp1()
begin1_label:BEGIN
......@@ -623,6 +631,8 @@ CALL sp2();
NULL
@x2 @x
1 2
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -654,6 +664,8 @@ ERROR 42000: Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expe
CALL sp2();
-1- @x2 @x
-1- 0 1
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
SELECT '-3-', @x2, @x;
-3- @x2 @x
-3- 1 1
......@@ -696,6 +708,8 @@ CALL sp2();
-2- 1 20
-4- @x2 @x
-4- 11 22
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -762,21 +776,33 @@ SELECT @done, @x;
0 1
INSERT INTO temp VALUES('1', NULL);
CALL sp1();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('2', NULL);
CALL sp2();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('3', NULL);
CALL sp3();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
INSERT INTO temp VALUES('4', NULL);
CALL sp4();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
......@@ -885,18 +911,26 @@ SELECT @done, @x;
@done @x
0 1
CALL sp1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp2();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp3();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
CALL sp4();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
......@@ -1031,6 +1065,8 @@ SQLSTATE
21000
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-1-', @x;
-1- @x
-1- 6
......@@ -1041,18 +1077,24 @@ SQLSTATE
SQLEXCEPTION
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-2-', @x;
-2- @x
-2- 6
CALL sp3();
SQLSTATE
20000
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-3-', @x;
-3- @x
-3- 1
CALL sp4();
SQLSTATE
SQLEXCEPTION
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-4-', @x;
-4- @x
-4- 1
......@@ -1335,6 +1377,8 @@ CLOSE cur1;
CLOSE cur2;
END//
CALL sp_outer();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT * FROM temp1;
f0 cnt f1 f2 f3 f4
_sp_out_ 1 a` a` 1000-01-01 -5000
......
......@@ -348,6 +348,8 @@ CALL h1();
-7- 1 1 1 1 1 1
END x1 x2 x3 x4 x5 x6
END 1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
DROP TABLE IF EXISTS tnull;
DROP PROCEDURE IF EXISTS sp1;
CREATE TABLE tnull(f1 int);
......@@ -446,6 +448,8 @@ END//
CALL h2();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
SELECT * FROM res_t1;
w x
a b
......@@ -551,6 +555,8 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
Warnings:
Error 1146 Table 'db_storedproc.tqq' doesn't exist
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
......@@ -581,6 +587,8 @@ END//
CALL h1();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
This will fail, SQLSTATE 00000 is not allowed
CREATE PROCEDURE sp1()
begin1_label:BEGIN
......@@ -624,6 +632,8 @@ CALL sp2();
NULL
@x2 @x
1 2
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -655,6 +665,8 @@ ERROR 42000: Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expe
CALL sp2();
-1- @x2 @x
-1- 0 1
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
SELECT '-3-', @x2, @x;
-3- @x2 @x
-3- 1 1
......@@ -697,6 +709,8 @@ CALL sp2();
-2- 1 20
-4- @x2 @x
-4- 11 22
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -763,21 +777,33 @@ SELECT @done, @x;
0 1
INSERT INTO temp VALUES('1', NULL);
CALL sp1();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('2', NULL);
CALL sp2();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('3', NULL);
CALL sp3();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
INSERT INTO temp VALUES('4', NULL);
CALL sp4();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
......@@ -886,18 +912,26 @@ SELECT @done, @x;
@done @x
0 1
CALL sp1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp2();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp3();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
CALL sp4();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
......@@ -1032,6 +1066,8 @@ SQLSTATE
21000
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-1-', @x;
-1- @x
-1- 6
......@@ -1042,18 +1078,24 @@ SQLSTATE
SQLEXCEPTION
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-2-', @x;
-2- @x
-2- 6
CALL sp3();
SQLSTATE
20000
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-3-', @x;
-3- @x
-3- 1
CALL sp4();
SQLSTATE
SQLEXCEPTION
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-4-', @x;
-4- @x
-4- 1
......@@ -1336,6 +1378,8 @@ CLOSE cur1;
CLOSE cur2;
END//
CALL sp_outer();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT * FROM temp1;
f0 cnt f1 f2 f3 f4
_sp_out_ 1 a` a` 1000-01-01 -5000
......
......@@ -348,6 +348,8 @@ CALL h1();
-7- 1 1 1 1 1 1
END x1 x2 x3 x4 x5 x6
END 1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
DROP TABLE IF EXISTS tnull;
DROP PROCEDURE IF EXISTS sp1;
CREATE TABLE tnull(f1 int);
......@@ -446,6 +448,8 @@ END//
CALL h2();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
SELECT * FROM res_t1;
w x
a b
......@@ -551,6 +555,8 @@ exit handler 2
exit handler 2
exit handler 1
exit handler 1
Warnings:
Error 1146 Table 'db_storedproc.tqq' doesn't exist
create table res_t1(w char unique, x char);
insert into res_t1 values ('a', 'b');
CREATE PROCEDURE h1 ()
......@@ -581,6 +587,8 @@ END//
CALL h1();
x1 x2 x3 x4 x5 x6
1 1 1 1 1 1
Warnings:
Error 1062 Duplicate entry 'a' for key 'w'
This will fail, SQLSTATE 00000 is not allowed
CREATE PROCEDURE sp1()
begin1_label:BEGIN
......@@ -624,6 +632,8 @@ CALL sp2();
NULL
@x2 @x
1 2
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -655,6 +665,8 @@ ERROR 42000: Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expe
CALL sp2();
-1- @x2 @x
-1- 0 1
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
SELECT '-3-', @x2, @x;
-3- @x2 @x
-3- 1 1
......@@ -697,6 +709,8 @@ CALL sp2();
-2- 1 20
-4- @x2 @x
-4- 11 22
Warnings:
Error 1318 Incorrect number of arguments for PROCEDURE db_storedproc.sp1; expected 2, got 1
DROP PROCEDURE sp1;
DROP PROCEDURE sp2;
......@@ -763,21 +777,33 @@ SELECT @done, @x;
0 1
INSERT INTO temp VALUES('1', NULL);
CALL sp1();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('2', NULL);
CALL sp2();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 1
INSERT INTO temp VALUES('3', NULL);
CALL sp3();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
INSERT INTO temp VALUES('4', NULL);
CALL sp4();
Warnings:
Warning 1265 Data truncated for column 'f1' at row 1
Warning 1265 Data truncated for column 'f2' at row 1
SELECT @done, @x;
@done @x
1 0
......@@ -886,18 +912,26 @@ SELECT @done, @x;
@done @x
0 1
CALL sp1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp2();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 2
CALL sp3();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
CALL sp4();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT @done, @x;
@done @x
1 1
......@@ -1032,6 +1066,8 @@ SQLSTATE
21000
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-1-', @x;
-1- @x
-1- 6
......@@ -1042,18 +1078,24 @@ SQLSTATE
SQLEXCEPTION
SQLSTATE
24000
Warnings:
Error 1326 Cursor is not open
SELECT '-2-', @x;
-2- @x
-2- 6
CALL sp3();
SQLSTATE
20000
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-3-', @x;
-3- @x
-3- 1
CALL sp4();
SQLSTATE
SQLEXCEPTION
Warnings:
Error 1339 Case not found for CASE statement
SELECT '-4-', @x;
-4- @x
-4- 1
......@@ -1336,6 +1378,8 @@ CLOSE cur1;
CLOSE cur2;
END//
CALL sp_outer();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT * FROM temp1;
f0 cnt f1 f2 f3 f4
_sp_out_ 1 a` a` 1000-01-01 -5000
......
......@@ -77,6 +77,8 @@ id2
< ---- Master selects-- >
-------------------------
CALL test.p1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
SELECT * FROM test.t3 ORDER BY id3;
id3 c
1 MySQL
......
......@@ -38,6 +38,8 @@ INSERT INTO t1 VALUES ('MySQL','1993-02-04'),('ROCKS', '1990-08-27'),('Texas', '
END|
CALL p2();
CALL p1();
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
DROP TABLE t1;
DROP TABLE t2;
DROP PROCEDURE p1;
......
......@@ -69,9 +69,15 @@ INSERT INTO test.t2 VALUES(NULL,0,'Testing MySQL databases is a cool ', 'MySQL C
UPDATE test.t1 SET b1 = 0 WHERE b1 = 1;
INSERT INTO test.t2 VALUES(NULL,1,'This is an after update test.', 'If this works, total will not be zero on the master or slave',1.4321,5.221,0,YEAR(NOW()),NOW());
UPDATE test.t2 SET b1 = 0 WHERE b1 = 1;
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
INSERT INTO test.t1 VALUES(NULL,1,'add some more test data test.', 'and hope for the best', 3.321,5.221,0,YEAR(NOW()),NOW());
DELETE FROM test.t1 WHERE id = 1;
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
DELETE FROM test.t2 WHERE id = 1;
Warnings:
Error 1329 No data - zero rows fetched, selected, or processed
DROP TRIGGER test.t1_bi;
DROP TRIGGER test.t2_ai;
DROP TRIGGER test.t1_bu;
......
......@@ -2408,6 +2408,7 @@ BEGIN
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '2';
SHOW WARNINGS;
RESIGNAL x SET MYSQL_ERRNO = 9999;
END;
......@@ -2415,9 +2416,10 @@ BEGIN
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '1';
SHOW WARNINGS;
RESIGNAL x SET
SCHEMA_NAME = 'test',
MYSQL_ERRNO= 1231;
MYSQL_ERRNO= 1232;
END;
/* Raises ER_WRONG_VALUE_FOR_VAR : 1231, SQLSTATE 42000 */
SET @@sql_mode=NULL;
......@@ -2431,6 +2433,7 @@ BEGIN
DECLARE EXIT HANDLER FOR x
BEGIN
SELECT '3';
SHOW WARNINGS;
RESIGNAL x SET
MESSAGE_TEXT = 'Hi, I am a useless error message',
MYSQL_ERRNO = 9999;
......
......@@ -649,3 +649,56 @@ END//
DELIMITER ;//
SHOW PROCEDURE CODE p1;
DROP PROCEDURE p1;
--echo #
--echo # Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
--echo #
--echo
--echo # - Case 4: check that "No Data trumps Warning".
--echo
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2), (3);
delimiter |;
CREATE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT a FROM t1;
OPEN c;
BEGIN
DECLARE v INT;
DECLARE CONTINUE HANDLER FOR SQLWARNING
BEGIN
SELECT "Warning found!";
SHOW WARNINGS;
END;
DECLARE EXIT HANDLER FOR NOT FOUND
BEGIN
SELECT "End of Result Set found!";
SHOW WARNINGS;
END;
WHILE TRUE DO
FETCH c INTO v;
END WHILE;
END;
CLOSE c;
SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
END|
delimiter ;|
SET SESSION debug="+d,bug23032_emit_warning";
CALL p1();
SET SESSION debug="-d,bug23032_emit_warning";
DROP PROCEDURE p1;
DROP TABLE t1;
......@@ -2543,3 +2543,273 @@ DROP TABLE t1;
--echo End of 5.1 tests
--echo #
--echo # Bug#23032: Handlers declared in a SP do not handle warnings generated in sub-SP
--echo #
--echo
--echo # - Case 1
--echo
--disable_warnings
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;
DROP PROCEDURE IF EXISTS p6;
--enable_warnings
delimiter |;
CREATE PROCEDURE p1()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SELECT 1;
CALL p2();
END|
CREATE PROCEDURE p2()
BEGIN
SELECT CAST('10 ' as unsigned integer);
END|
delimiter ;|
CALL p1();
DROP PROCEDURE p1;
DROP PROCEDURE p2;
--echo
--echo # - Case 2
--echo
delimiter |;
CREATE PROCEDURE p1()
BEGIN
DECLARE c INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
CALL p2();
CALL p3();
CALL p4();
SELECT c;
SELECT @@warning_count;
SHOW WARNINGS;
END|
CREATE PROCEDURE p2()
BEGIN
SELECT CAST('10 ' as unsigned integer);
END|
CREATE PROCEDURE p3()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SELECT 1;
END|
CREATE PROCEDURE p4()
BEGIN
SELECT CAST('10 ' as unsigned integer);
CALL p2();
END|
CREATE PROCEDURE p5()
BEGIN
SELECT CAST('10 ' as unsigned integer);
SHOW WARNINGS;
END|
CREATE PROCEDURE P6()
BEGIN
DECLARE c INT DEFAULT 0;
DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
CALL p5();
SELECT c;
END|
delimiter ;|
CALL p1();
CALL p6();
DROP PROCEDURE p1;
DROP PROCEDURE p2;
DROP PROCEDURE p3;
DROP PROCEDURE p4;
DROP PROCEDURE p5;
DROP PROCEDURE p6;
--echo
--echo # - Case 3: check that "Exception trumps No Data".
--echo
--disable_warnings
DROP TABLE IF EXISTS t1;
--enable_warnings
CREATE TABLE t1(a INT);
INSERT INTO t1 VALUES (1), (2), (3);
delimiter |;
CREATE PROCEDURE p1()
BEGIN
DECLARE c CURSOR FOR SELECT a FROM t1;
OPEN c;
BEGIN
DECLARE v1 INT;
DECLARE v2 INT;
DECLARE EXIT HANDLER FOR SQLEXCEPTION
SELECT "Error caught (expected)";
DECLARE EXIT HANDLER FOR NOT FOUND
SELECT "End of Result Set found!";
WHILE TRUE DO
FETCH c INTO v1, v2;
END WHILE;
END;
CLOSE c;
SELECT a INTO @foo FROM t1 LIMIT 1; # Clear warning stack
END|
delimiter ;|
CALL p1();
DROP PROCEDURE p1;
DROP TABLE t1;
--echo #
--echo # Bug#36185: Incorrect precedence for warning and exception handlers
--echo #
--disable_warnings
DROP TABLE IF EXISTS t1;
DROP PROCEDURE IF EXISTS p1;
--enable_warnings
CREATE TABLE t1 (a INT, b INT NOT NULL);
delimiter |;
CREATE PROCEDURE p1()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING SELECT 'warning';
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION SELECT 'exception';
INSERT INTO t1 VALUES (CAST('10 ' AS SIGNED), NULL);
END|
delimiter ;|
CALL p1();
DROP TABLE t1;
DROP PROCEDURE p1;
--echo #
--echo # Bug#5889: Exit handler for a warning doesn't hide the warning in trigger
--echo #
--echo
--echo # - Case 1
--echo
CREATE TABLE t1(a INT, b INT);
INSERT INTO t1 VALUES (1, 2);
delimiter |;
CREATE TRIGGER t1_bu BEFORE UPDATE ON t1 FOR EACH ROW
BEGIN
DECLARE EXIT HANDLER FOR SQLWARNING
SET NEW.a = 10;
SET NEW.a = 99999999999;
END|
delimiter ;|
UPDATE t1 SET b = 20;
SHOW WARNINGS;
SELECT * FROM t1;
DROP TRIGGER t1_bu;
DROP TABLE t1;
--echo
--echo # - Case 2
--echo
CREATE TABLE t1(a INT);
CREATE TABLE t2(b CHAR(1));
delimiter |;
CREATE TRIGGER t1_bi BEFORE INSERT ON t1 FOR EACH ROW
BEGIN
INSERT INTO t2 VALUES('ab'); # Produces a warning.
INSERT INTO t2 VALUES('b'); # Does not produce a warning,
# previous warning should be cleared.
END|
delimiter ;|
INSERT INTO t1 VALUES(0);
SHOW WARNINGS;
SELECT * FROM t1;
SELECT * FROM t2;
DROP TRIGGER t1_bi;
DROP TABLE t1;
DROP TABLE t2;
--echo #
--echo # Bug#9857: Stored procedures: handler for sqlwarning ignored
--echo #
SET @sql_mode_saved = @@sql_mode;
SET sql_mode = traditional;
delimiter |;
CREATE PROCEDURE p1()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLWARNING
SELECT 'warning caught (expected)';
SELECT 5 / 0;
END|
CREATE PROCEDURE p2()
BEGIN
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
SELECT 'error caught (unexpected)';
SELECT 5 / 0;
END|
delimiter ;|
CALL p1();
SHOW WARNINGS;
CALL p2();
SHOW WARNINGS;
DROP PROCEDURE p1;
DROP PROCEDURE p2;
SET sql_mode = @sql_mode_saved;
......@@ -5432,6 +5432,8 @@ drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2|
drop procedure if exists bug15231_3|
drop procedure if exists bug15231_4|
drop procedure if exists bug15231_5|
drop procedure if exists bug15231_6|
--enable_warnings
create table t3 (id int not null)|
......@@ -5461,7 +5463,7 @@ end|
create procedure bug15231_3()
begin
declare exit handler for sqlwarning
select 'Caught it (wrong)' as 'Result';
select 'Caught it (correct)' as 'Result';
call bug15231_4();
end|
......@@ -5472,16 +5474,37 @@ begin
set x = 'zap';
select 'Missed it (correct)' as 'Result';
show warnings;
end|
create procedure bug15231_5()
begin
declare exit handler for sqlwarning
select 'Caught it (wrong)' as 'Result';
call bug15231_6();
end|
create procedure bug15231_6()
begin
declare x decimal(2,1);
set x = 'zap';
select 'Missed it (correct)' as 'Result';
select id from t3;
end|
call bug15231_1()|
call bug15231_3()|
call bug15231_5()|
drop table if exists t3|
drop procedure if exists bug15231_1|
drop procedure if exists bug15231_2|
drop procedure if exists bug15231_3|
drop procedure if exists bug15231_4|
drop table t3|
drop procedure bug15231_1|
drop procedure bug15231_2|
drop procedure bug15231_3|
drop procedure bug15231_4|
drop procedure bug15231_5|
drop procedure bug15231_6|
#
......
......@@ -1075,6 +1075,104 @@ void sp_head::recursion_level_error(THD *thd)
}
/**
Find an SQL handler for any condition (warning or error) after execution
of a stored routine instruction. Basically, this function looks for an
appropriate SQL handler in RT-contexts. If an SQL handler is found, it is
remembered in the RT-context for future activation (the context can be
inactive at the moment).
If there is no pending condition, the function just returns.
If there was an error during the execution, an SQL handler for it will be
searched within the current and outer scopes.
There might be several errors in the Warning Info (that's possible by using
SIGNAL/RESIGNAL in nested scopes) -- the function is looking for an SQL
handler for the latest (current) error only.
If there was a warning during the execution, an SQL handler for it will be
searched within the current scope only.
If several warnings were thrown during the execution and there are different
SQL handlers for them, it is not determined which SQL handler will be chosen.
Only one SQL handler will be executed.
If warnings and errors were thrown during the execution, the error takes
precedence. I.e. error handler will be executed. If there is no handler
for that error, condition will remain unhandled.
Once a warning or an error has been handled it is not removed from
Warning Info.
According to The Standard (quoting PeterG):
An SQL procedure statement works like this ...
SQL/Foundation 13.5 <SQL procedure statement>
(General Rules) (greatly summarized) says:
(1) Empty diagnostics area, thus clearing the condition.
(2) Execute statement.
During execution, if Exception Condition occurs,
set Condition Area = Exception Condition and stop
statement.
During execution, if No Data occurs,
set Condition Area = No Data Condition and continue
statement.
During execution, if Warning occurs,
and Condition Area is not already full due to
an earlier No Data condition, set Condition Area
= Warning and continue statement.
(3) Finish statement.
At end of execution, if Condition Area is not
already full due to an earlier No Data or Warning,
set Condition Area = Successful Completion.
In effect, this system means there is a precedence:
Exception trumps No Data, No Data trumps Warning,
Warning trumps Successful Completion.
NB: "Procedure statements" include any DDL or DML or
control statements. So CREATE and DELETE and WHILE
and CALL and RETURN are procedure statements. But
DECLARE and END are not procedure statements.
@param thd thread handle
@param ctx runtime context of the stored routine
*/
static void
find_handler_after_execution(THD *thd, sp_rcontext *ctx)
{
if (thd->is_error())
{
ctx->find_handler(thd,
thd->stmt_da->sql_errno(),
thd->stmt_da->get_sqlstate(),
MYSQL_ERROR::WARN_LEVEL_ERROR,
thd->stmt_da->message());
}
else if (thd->warning_info->statement_warn_count())
{
List_iterator<MYSQL_ERROR> it(thd->warning_info->warn_list());
MYSQL_ERROR *err;
while ((err= it++))
{
if (err->get_level() != MYSQL_ERROR::WARN_LEVEL_WARN &&
err->get_level() != MYSQL_ERROR::WARN_LEVEL_NOTE)
continue;
if (ctx->find_handler(thd,
err->get_sql_errno(),
err->get_sqlstate(),
err->get_level(),
err->get_message_text()))
{
break;
}
}
}
}
/**
Execute the routine. The main instruction jump loop is there.
Assume the parameters already set.
......@@ -1096,7 +1194,7 @@ sp_head::execute(THD *thd)
LEX_STRING saved_cur_db_name=
{ saved_cur_db_name_buf, sizeof(saved_cur_db_name_buf) };
bool cur_db_changed= FALSE;
sp_rcontext *ctx;
sp_rcontext *ctx= thd->spcont;
bool err_status= FALSE;
uint ip= 0;
ulong save_sql_mode;
......@@ -1157,8 +1255,6 @@ sp_head::execute(THD *thd)
goto done;
}
if ((ctx= thd->spcont))
ctx->clear_handler();
thd->is_slave_error= 0;
old_arena= thd->stmt_arena;
......@@ -1243,7 +1339,6 @@ sp_head::execute(THD *thd)
do
{
sp_instr *i;
uint hip;
#if defined(ENABLED_PROFILING)
/*
......@@ -1265,6 +1360,9 @@ sp_head::execute(THD *thd)
break;
}
/* Reset number of warnings for this query. */
thd->warning_info->reset_for_next_command();
DBUG_PRINT("execute", ("Instruction %u", ip));
/*
......@@ -1309,40 +1407,28 @@ sp_head::execute(THD *thd)
free_root(&execute_mem_root, MYF(0));
/*
Check if an exception has occurred and a handler has been found
Note: We have to check even if err_status == FALSE, since warnings (and
some errors) don't return a non-zero value. We also have to check even
if thd->killed != 0, since some errors return with this even when a
handler has been found (e.g. "bad data").
Find and process SQL handlers unless it is a fatal error (fatal
errors are not catchable by SQL handlers) or the connection has been
killed during execution.
*/
if (ctx)
if (!thd->is_fatal_error && !thd->killed_errno())
{
uint handler_index;
/*
Find SQL handler in the appropriate RT-contexts:
- warnings can be handled by SQL handlers within
the current scope only;
- errors can be handled by any SQL handler from outer scope.
*/
find_handler_after_execution(thd, ctx);
switch (ctx->found_handler(& hip, & handler_index)) {
case SP_HANDLER_NONE:
break;
case SP_HANDLER_CONTINUE:
thd->restore_active_arena(&execute_arena, &backup_arena);
thd->set_n_backup_active_arena(&execute_arena, &backup_arena);
ctx->push_hstack(i->get_cont_dest());
/* Fall through */
default:
if (ctx->end_partial_result_set)
thd->protocol->end_partial_result_set(thd);
ip= hip;
/* If found, activate handler for the current scope. */
if (ctx->activate_handler(thd, &ip, i, &execute_arena, &backup_arena))
err_status= FALSE;
ctx->clear_handler();
ctx->enter_handler(hip, handler_index);
thd->clear_error();
thd->is_fatal_error= 0;
thd->killed= THD::NOT_KILLED;
thd->mysys_var->abort= 0;
continue;
}
/* Reset sp_rcontext::end_partial_result_set flag. */
ctx->end_partial_result_set= FALSE;
}
} while (!err_status && !thd->killed && !thd->is_fatal_error);
#if defined(ENABLED_PROFILING)
......@@ -3037,23 +3123,14 @@ sp_instr_set::exec_core(THD *thd, uint *nextp)
{
int res= thd->spcont->set_variable(thd, m_offset, &m_value);
if (res && thd->spcont->found_handler_here())
if (res)
{
/*
Failed to evaluate the value, and a handler has been found. Reset the
variable to NULL.
*/
/* Failed to evaluate the value. Reset the variable to NULL. */
if (thd->spcont->set_variable(thd, m_offset, 0))
{
/* If this also failed, let's abort. */
sp_rcontext *spcont= thd->spcont;
thd->spcont= NULL; /* Avoid handlers */
my_error(ER_OUT_OF_RESOURCES, MYF(0));
spcont->clear_handler();
thd->spcont= spcont;
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
}
}
......@@ -3586,18 +3663,6 @@ sp_instr_copen::execute(THD *thd, uint *nextp)
if (thd->stmt_arena->free_list)
cleanup_items(thd->stmt_arena->free_list);
thd->stmt_arena= old_arena;
/*
Work around the fact that errors in selects are not returned properly
(but instead converted into a warning), so if a condition handler
caught, we have lost the result code.
*/
if (!res)
{
uint dummy1, dummy2;
if (thd->spcont->found_handler(&dummy1, &dummy2))
res= -1;
}
/* TODO: Assert here that we either have an error or a cursor */
}
DBUG_RETURN(res);
......@@ -3773,13 +3838,11 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
{
int res= thd->spcont->set_case_expr(thd, m_case_expr_id, &m_case_expr);
if (res &&
!thd->spcont->get_case_expr(m_case_expr_id) &&
thd->spcont->found_handler_here())
if (res && !thd->spcont->get_case_expr(m_case_expr_id))
{
/*
Failed to evaluate the value, the case expression is still not
initialized, and a handler has been found. Set to NULL so we can continue.
initialized. Set to NULL so we can continue.
*/
Item *null_item= new Item_null();
......@@ -3788,13 +3851,7 @@ sp_instr_set_case_expr::exec_core(THD *thd, uint *nextp)
thd->spcont->set_case_expr(thd, m_case_expr_id, &null_item))
{
/* If this also failed, we have to abort. */
sp_rcontext *spcont= thd->spcont;
thd->spcont= NULL; /* Avoid handlers */
my_error(ER_OUT_OF_RESOURCES, MYF(0));
spcont->clear_handler();
thd->spcont= spcont;
my_error(ER_OUT_OF_RESOURCES, MYF(ME_FATALERROR));
}
}
else
......
......@@ -332,13 +332,6 @@ class sp_pcontext : public Sql_alloc
int
push_cond(LEX_STRING *name, sp_cond_type_t *val);
inline void
pop_cond(uint num)
{
while (num--)
pop_dynamic(&m_conds);
}
sp_cond_type_t *
find_cond(LEX_STRING *name, my_bool scoped=0);
......
......@@ -171,48 +171,50 @@ sp_rcontext::set_return_value(THD *thd, Item **return_value_item)
#define IS_NOT_FOUND_CONDITION(S) ((S)[0] == '0' && (S)[1] == '2')
#define IS_EXCEPTION_CONDITION(S) ((S)[0] != '0' || (S)[1] > '2')
/*
Find a handler for the given errno.
This is called from all error message functions (e.g. push_warning,
net_send_error, et al) when a sp_rcontext is in effect. If a handler
is found, no error is sent, and the the SP execution loop will instead
invoke the found handler.
This might be called several times before we get back to the execution
loop, so m_hfound can be >= 0 if a handler has already been found.
(In which case we don't search again - the first found handler will
be used.)
Handlers are pushed on the stack m_handler, with the latest/innermost
/**
Find an SQL handler for the given error.
SQL handlers are pushed on the stack m_handler, with the latest/innermost
one on the top; we then search for matching handlers from the top and
down.
We search through all the handlers, looking for the most specific one
(sql_errno more specific than sqlstate more specific than the rest).
Note that mysql error code handlers is a MySQL extension, not part of
the standard.
SYNOPSIS
sql_errno The error code
level Warning level
SQL handlers for warnings are searched in the current scope only.
RETURN
1 if a handler was found, m_hfound is set to its index (>= 0)
0 if not found, m_hfound is -1
SQL handlers for errors are searched in the current and in outer scopes.
That's why finding and activation of handler must be separated: an errror
handler might be located in the outer scope, which is not active at the
moment. Before such handler can be activated, execution flow should
unwind to that scope.
Found SQL handler is remembered in m_hfound for future activation.
If no handler is found, m_hfound is -1.
@param thd Thread handle
@param sql_errno The error code
@param sqlstate The error SQL state
@param level The error level
@param msg The error message
@retval TRUE if an SQL handler was found
@retval FALSE otherwise
*/
bool
sp_rcontext::find_handler(THD *thd,
uint sql_errno,
const char* sqlstate,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
const char *msg)
{
if (m_hfound >= 0)
{
*cond_hdl= NULL;
return TRUE; // Already got one
}
int i= m_hcount;
int i= m_hcount, found= -1;
/* Reset previously found handler. */
m_hfound= -1;
/*
If this is a fatal sub-statement error, and this runtime
......@@ -240,34 +242,43 @@ sp_rcontext::find_handler(THD *thd,
{
case sp_cond_type_t::number:
if (sql_errno == cond->mysqlerr &&
(found < 0 || m_handler[found].cond->type > sp_cond_type_t::number))
found= i; // Always the most specific
(m_hfound < 0 || m_handler[m_hfound].cond->type > sp_cond_type_t::number))
m_hfound= i; // Always the most specific
break;
case sp_cond_type_t::state:
if (strcmp(sqlstate, cond->sqlstate) == 0 &&
(found < 0 || m_handler[found].cond->type > sp_cond_type_t::state))
found= i;
(m_hfound < 0 || m_handler[m_hfound].cond->type > sp_cond_type_t::state))
m_hfound= i;
break;
case sp_cond_type_t::warning:
if ((IS_WARNING_CONDITION(sqlstate) ||
level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
found < 0)
found= i;
m_hfound < 0)
m_hfound= i;
break;
case sp_cond_type_t::notfound:
if (IS_NOT_FOUND_CONDITION(sqlstate) && found < 0)
found= i;
if (IS_NOT_FOUND_CONDITION(sqlstate) && m_hfound < 0)
m_hfound= i;
break;
case sp_cond_type_t::exception:
if (IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
found < 0)
found= i;
m_hfound < 0)
m_hfound= i;
break;
}
}
if (found < 0)
if (m_hfound >= 0)
{
DBUG_ASSERT((uint) m_hfound < m_root_parsing_ctx->max_handler_index());
m_raised_conditions[m_hfound].clear();
m_raised_conditions[m_hfound].set(sql_errno, sqlstate, level, msg);
return TRUE;
}
/*
Only "exception conditions" are propagated to handlers in calling
contexts. If no handler is found locally for a "completion condition"
......@@ -275,70 +286,12 @@ sp_rcontext::find_handler(THD *thd,
*/
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
return m_prev_runtime_ctx->find_handler(thd,
sql_errno,
sqlstate,
level,
msg,
cond_hdl);
*cond_hdl= NULL;
return FALSE;
}
m_hfound= found;
MYSQL_ERROR *raised= NULL;
DBUG_ASSERT(m_hfound >= 0);
DBUG_ASSERT((uint) m_hfound < m_root_parsing_ctx->max_handler_index());
raised= & m_raised_conditions[m_hfound];
raised->clear();
raised->set(sql_errno, sqlstate, level, msg);
*cond_hdl= raised;
return TRUE;
}
/*
Handle the error for a given errno.
The severity of the error is adjusted depending of the current sql_mode.
If an handler is present for the error (see find_handler()),
this function will return true.
If a handler is found and if the severity of the error indicate
that the current instruction executed should abort,
the flag thd->net.report_error is also set.
This will cause the execution of the current instruction in a
sp_instr* to fail, and give control to the handler code itself
in the sp_head::execute() loop.
SYNOPSIS
sql_errno The error code
level Warning level
thd The current thread
RETURN
TRUE if a handler was found.
FALSE if no handler was found.
*/
bool
sp_rcontext::handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl)
{
MYSQL_ERROR::enum_warning_level elevated_level= level;
/* Depending on the sql_mode of execution,
warnings may be considered errors */
if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
thd->really_abort_on_warning())
{
elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
return m_prev_runtime_ctx->find_handler(thd, sql_errno, sqlstate,
level, msg);
}
return find_handler(thd, sql_errno, sqlstate, elevated_level, msg, cond_hdl);
return FALSE;
}
void
......@@ -384,7 +337,9 @@ sp_rcontext::pop_handlers(uint count)
{
DBUG_ENTER("sp_rcontext::pop_handlers");
DBUG_ASSERT(m_hcount >= count);
m_hcount-= count;
DBUG_PRINT("info", ("m_hcount: %d", m_hcount));
DBUG_VOID_RETURN;
}
......@@ -394,7 +349,9 @@ sp_rcontext::push_hstack(uint h)
{
DBUG_ENTER("sp_rcontext::push_hstack");
DBUG_ASSERT(m_hsp < m_root_parsing_ctx->max_handler_index());
m_hstack[m_hsp++]= h;
DBUG_PRINT("info", ("m_hsp: %d", m_hsp));
DBUG_VOID_RETURN;
}
......@@ -405,21 +362,74 @@ sp_rcontext::pop_hstack()
uint handler;
DBUG_ENTER("sp_rcontext::pop_hstack");
DBUG_ASSERT(m_hsp);
handler= m_hstack[--m_hsp];
DBUG_PRINT("info", ("m_hsp: %d", m_hsp));
DBUG_RETURN(handler);
}
void
sp_rcontext::enter_handler(uint hip, uint hindex)
/**
Prepare found handler to be executed.
@retval TRUE if an SQL handler is activated (was found) and IP of the
first handler instruction.
@retval FALSE if there is no active handler
*/
bool
sp_rcontext::activate_handler(THD *thd,
uint *ip,
sp_instr *instr,
Query_arena *execute_arena,
Query_arena *backup_arena)
{
DBUG_ENTER("sp_rcontext::enter_handler");
if (m_hfound < 0)
return FALSE;
switch (m_handler[m_hfound].type) {
case SP_HANDLER_NONE:
break;
case SP_HANDLER_CONTINUE:
thd->restore_active_arena(execute_arena, backup_arena);
thd->set_n_backup_active_arena(execute_arena, backup_arena);
push_hstack(instr->get_cont_dest());
/* Fall through */
default:
/* End aborted result set. */
if (end_partial_result_set)
thd->protocol->end_partial_result_set(thd);
/* Enter handler. */
DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index());
m_in_handler[m_ihsp].ip= hip;
m_in_handler[m_ihsp].index= hindex;
DBUG_ASSERT(m_hfound >= 0);
m_in_handler[m_ihsp].ip= m_handler[m_hfound].handler;
m_in_handler[m_ihsp].index= m_hfound;
m_ihsp++;
DBUG_PRINT("info", ("Entering handler..."));
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
/* Reset error state. */
thd->clear_error();
thd->killed= THD::NOT_KILLED; // Some errors set thd->killed
// (e.g. "bad data").
/* Return IP of the activated SQL handler. */
*ip= m_handler[m_hfound].handler;
/* Reset found handler. */
m_hfound= -1;
}
return TRUE;
}
void
......@@ -427,9 +437,11 @@ sp_rcontext::exit_handler()
{
DBUG_ENTER("sp_rcontext::exit_handler");
DBUG_ASSERT(m_ihsp);
uint hindex= m_in_handler[m_ihsp-1].index;
m_raised_conditions[hindex].clear();
m_ihsp-= 1;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
}
......@@ -567,6 +579,11 @@ sp_cursor::fetch(THD *thd, List<struct sp_variable> *vars)
return -1;
}
DBUG_EXECUTE_IF("bug23032_emit_warning",
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_UNKNOWN_ERROR,
ER(ER_UNKNOWN_ERROR)););
result.set_spvar_list(vars);
/* Attempt to fetch one row */
......
......@@ -131,67 +131,40 @@ class sp_rcontext : public Sql_alloc
return m_return_value_set;
}
/*
SQL handlers support.
*/
void push_handler(struct sp_cond_type *cond, uint h, int type);
void pop_handlers(uint count);
// Returns 1 if a handler was found, 0 otherwise.
bool
find_handler(THD *thd,
uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
// If there is an error handler for this error, handle it and return TRUE.
bool
handle_condition(THD *thd,
uint sql_errno,
const char* sqlstate,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg,
MYSQL_ERROR ** cond_hdl);
// Returns handler type and sets *ip to location if one was found
inline int
found_handler(uint *ip, uint *index)
{
if (m_hfound < 0)
return SP_HANDLER_NONE;
*ip= m_handler[m_hfound].handler;
*index= m_hfound;
return m_handler[m_hfound].type;
}
MYSQL_ERROR* raised_condition() const;
const char *msg);
// Returns true if we found a handler in this context
inline bool
found_handler_here()
{
return (m_hfound >= 0);
}
MYSQL_ERROR *
raised_condition() const;
// Clears the handler find state
inline void
clear_handler()
{
m_hfound= -1;
}
void
push_hstack(uint h);
void push_hstack(uint h);
uint
pop_hstack();
uint pop_hstack();
bool
activate_handler(THD *thd,
uint *ip,
sp_instr *instr,
Query_arena *execute_arena,
Query_arena *backup_arena);
/**
Enter a SQL exception handler.
@param hip the handler instruction pointer
@param index the handler index
*/
void enter_handler(uint hip, uint index);
void exit_handler();
void
exit_handler();
void
push_cursor(sp_lex_keeper *lex_keeper, sp_instr_cpush *i);
......@@ -199,7 +172,7 @@ class sp_rcontext : public Sql_alloc
void
pop_cursors(uint count);
void
inline void
pop_all_cursors()
{
pop_cursors(m_ccount);
......
......@@ -845,35 +845,6 @@ MYSQL_ERROR* THD::raise_condition(uint sql_errno,
}
}
/*
If a continue handler is found, the error message will be cleared
by the stored procedures code.
*/
if (!is_fatal_error && spcont &&
spcont->handle_condition(this, sql_errno, sqlstate, level, msg, &cond))
{
/*
Do not push any warnings, a handled error must be completely
silenced.
*/
DBUG_RETURN(cond);
}
/* Un-handled conditions */
cond= raise_condition_no_handler(sql_errno, sqlstate, level, msg);
DBUG_RETURN(cond);
}
MYSQL_ERROR*
THD::raise_condition_no_handler(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg)
{
MYSQL_ERROR *cond= NULL;
DBUG_ENTER("THD::raise_condition_no_handler");
query_cache_abort(&query_cache_tls);
/* FIXME: broken special case */
......@@ -886,6 +857,7 @@ THD::raise_condition_no_handler(uint sql_errno,
cond= warning_info->push_warning(this, sql_errno, sqlstate, level, msg);
DBUG_RETURN(cond);
}
extern "C"
void *thd_alloc(MYSQL_THD thd, unsigned int size)
{
......
......@@ -2800,23 +2800,6 @@ class THD :public Statement,
MYSQL_ERROR::enum_warning_level level,
const char* msg);
/**
Raise a generic SQL condition, without activation any SQL condition
handlers.
This method is necessary to support the RESIGNAL statement,
which is allowed to bypass SQL exception handlers.
@param sql_errno the condition error number
@param sqlstate the condition SQLSTATE
@param level the condition level
@param msg the condition message text
@return The condition raised, or NULL
*/
MYSQL_ERROR*
raise_condition_no_handler(uint sql_errno,
const char* sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char* msg);
public:
/** Overloaded to guard query/query_length fields */
virtual void set_statement(Statement *stmt);
......
......@@ -494,14 +494,6 @@ void Warning_info::clear_warning_info(ulonglong warn_id_arg)
m_current_row_for_warning= 1; /* Start counting from the first row */
}
void Warning_info::reserve_space(THD *thd, uint count)
{
/* Make room for count conditions */
while ((m_warn_list.elements > 0) &&
((m_warn_list.elements + count) > thd->variables.max_error_count))
m_warn_list.pop();
}
/**
Append warnings only if the original contents of the routine
warning info was replaced.
......
......@@ -153,8 +153,8 @@ class Diagnostics_area
Representation of a SQL condition.
A SQL condition can be a completion condition (note, warning),
or an exception condition (error, not found).
@note This class is named MYSQL_ERROR instead of SQL_condition for historical reasons,
to facilitate merging code with previous releases.
@note This class is named MYSQL_ERROR instead of SQL_condition for
historical reasons, to facilitate merging code with previous releases.
*/
class MYSQL_ERROR : public Sql_alloc
{
......@@ -471,18 +471,6 @@ class Warning_info
ulong statement_warn_count() const { return m_statement_warn_count; }
/**
Reserve some space in the condition area.
This is a privileged operation, reserved for the RESIGNAL implementation,
as only the RESIGNAL statement is allowed to remove conditions from
the condition area.
For other statements, new conditions are not added to the condition
area once the condition area is full.
@param thd The current thread
@param count The number of slots to reserve
*/
void reserve_space(THD *thd, uint count);
/** Add a new condition to the current list. */
MYSQL_ERROR *push_warning(THD *thd,
uint sql_errno, const char* sqlstate,
......
......@@ -499,18 +499,6 @@ bool Resignal_statement::execute(THD *thd)
}
/* RESIGNAL with signal_value */
/* Make room for 2 conditions */
thd->warning_info->reserve_space(thd, 2);
MYSQL_ERROR *raised= NULL;
raised= thd->raise_condition_no_handler(signaled->get_sql_errno(),
signaled->get_sqlstate(),
signaled->get_level(),
signaled->get_message_text());
if (raised)
raised->copy_opt_attributes(signaled);
result= raise_condition(thd, signaled);
DBUG_RETURN(result);
......
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