#At file:///home/alik/MySQL/bzr/00/bug55847/mysql-trunk-bugfixing-bug55847.2/ based on revid:alexander.nozdrin@stripped
3426 Alexander Nozdrin 2010-12-15
A patch for Bug#55843 (Handled condition appears as not handled).
Patch for Bug 23032 changed the behavior so that handled condition
(sql warning or exception) left in Warning_info. The problem was
that handled conditions were treated as unhandled ones, so they
were shown as "active statement" warnings.
This patch consists of two parts:
1. Refactoring SQL handlers: it changes the way how SQL handlers
are found and activated
2. Fix the problem.
1. We used to search handlers recursively (from the current scope up
to the top one). That was needed because a search for handlers was
done right when an SQL condition occurs. After patch for Bug 23032
the search for SQL handlers happens after SQL statement completes.
That means, there is no need to do a recursive search now:
- if there are warnings, they are handled by SQL handlers within
the current scope only;
- if there is an error, it is propagated to the outer scope.
2. The bug fix is to remove conditions, which have SQL handlers
from Warning Info.
modified:
mysql-test/r/signal.result
mysql-test/r/signal_demo3.result
mysql-test/r/sp-big.result
mysql-test/r/sp-bugs.result
mysql-test/r/sp-code.result
mysql-test/r/sp-error.result
mysql-test/r/sp.result
mysql-test/r/sp_trans.result
mysql-test/r/strict.result
mysql-test/r/view.result
mysql-test/suite/rpl/r/rpl_row_sp005.result
mysql-test/suite/rpl/r/rpl_row_sp006_InnoDB.result
mysql-test/t/sp-error.test
sql/sp_head.cc
sql/sp_head.h
sql/sp_rcontext.cc
sql/sp_rcontext.h
sql/sql_error.cc
sql/sql_error.h
sql/sql_signal.cc
=== modified file 'mysql-test/r/signal.result'
--- a/mysql-test/r/signal.result 2010-10-27 10:28:09 +0000
+++ b/mysql-test/r/signal.result 2010-12-15 18:21:04 +0000
@@ -1189,8 +1189,6 @@ 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
@@ -1206,8 +1204,6 @@ 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
@@ -1223,8 +1219,6 @@ 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
@@ -1240,8 +1234,6 @@ 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
@@ -1257,8 +1249,6 @@ 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
@@ -1274,8 +1264,6 @@ 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
@@ -1291,8 +1279,6 @@ 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
@@ -1308,8 +1294,6 @@ 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
@@ -1325,8 +1309,6 @@ 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
@@ -1466,7 +1448,6 @@ after RESIGNAL
after RESIGNAL
Warnings:
Warning 1012 Raising a warning
-Warning 1012 Raising a warning
drop procedure test_resignal $$
create procedure test_resignal()
begin
@@ -1521,7 +1502,6 @@ 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
@@ -1578,7 +1558,6 @@ 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()
@@ -1639,7 +1618,6 @@ 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()
@@ -2141,9 +2119,6 @@ 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 $$
@@ -2188,18 +2163,15 @@ 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
=== modified file 'mysql-test/r/signal_demo3.result'
--- a/mysql-test/r/signal_demo3.result 2010-08-30 06:38:09 +0000
+++ b/mysql-test/r/signal_demo3.result 2010-12-15 18:21:04 +0000
@@ -95,11 +95,11 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
-Error 1051 Unknown table 'demo.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 = 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 'demo.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,7 +123,6 @@ call proc_1();
ERROR 45000: Oops in proc_1
show warnings;
Level Code Message
-Error 1051 Unknown table 'demo.oops_it_is_not_here'
Error 1644 Oops in proc_9
Error 1644 Oops in proc_8
Error 1644 Oops in proc_7
@@ -132,6 +131,7 @@ 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;
=== modified file 'mysql-test/r/sp-big.result'
--- a/mysql-test/r/sp-big.result 2010-07-30 15:28:36 +0000
+++ b/mysql-test/r/sp-big.result 2010-12-15 18:21:04 +0000
@@ -46,8 +46,6 @@ end while;
close cur1;
end|
call p1();
-Warnings:
-Error 1329 No data - zero rows fetched, selected, or processed
select count(*) from t1;
count(*)
256
=== modified file 'mysql-test/r/sp-bugs.result'
--- a/mysql-test/r/sp-bugs.result 2010-11-11 05:06:16 +0000
+++ b/mysql-test/r/sp-bugs.result 2010-12-15 18:21:04 +0000
@@ -43,8 +43,6 @@ END|
SELECT f2 ();
f2 ()
NULL
-Warnings:
-Error 1305 FUNCTION testdb.f_not_exists does not exist
DROP SCHEMA testdb;
USE test;
#
=== modified file 'mysql-test/r/sp-code.result'
--- a/mysql-test/r/sp-code.result 2010-07-30 15:28:36 +0000
+++ b/mysql-test/r/sp-code.result 2010-12-15 18:21:04 +0000
@@ -711,8 +711,6 @@ 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
@@ -732,8 +730,6 @@ 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;
@@ -928,20 +924,16 @@ 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;
=== modified file 'mysql-test/r/sp-error.result'
--- a/mysql-test/r/sp-error.result 2010-10-27 10:28:09 +0000
+++ b/mysql-test/r/sp-error.result 2010-12-15 18:21:04 +0000
@@ -1344,8 +1344,6 @@ 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
@@ -1353,8 +1351,6 @@ 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
@@ -1754,77 +1750,103 @@ DROP PROCEDURE p2;
# - Case 2
+DROP TABLE IF EXISTS t1;
+CREATE TABLE t1(a INT);
CREATE PROCEDURE p1()
BEGIN
DECLARE c INT DEFAULT 0;
-DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
-CALL p2();
-CALL p3();
-CALL p4();
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+SET c = c + 1;
+SELECT 'Warning caught!' AS Msg;
+END;
+CALL p2(); # 1 warning
+CALL p3(); # 1 warning
+CALL p4(); # No warnings
+CALL p5(); # 1 warning
SELECT c;
SELECT @@warning_count;
SHOW WARNINGS;
END|
CREATE PROCEDURE p2()
BEGIN
-SELECT CAST('10 ' as unsigned integer);
+SELECT CAST('2 ' as unsigned integer);
END|
CREATE PROCEDURE p3()
BEGIN
-SELECT CAST('10 ' as unsigned integer);
-SELECT 1;
+SELECT CAST('3 ' as unsigned integer);
+SELECT 1; # does not clear the warning
END|
CREATE PROCEDURE p4()
BEGIN
-SELECT CAST('10 ' as unsigned integer);
-CALL p2();
+SELECT CAST('4 ' as unsigned integer);
+INSERT INTO t1 VALUES(1); # Clears the warning
END|
CREATE PROCEDURE p5()
BEGIN
-SELECT CAST('10 ' as unsigned integer);
+SELECT CAST('5 ' as unsigned integer);
+CALL p2();
+END|
+CREATE PROCEDURE p6()
+BEGIN
+SELECT CAST('6 ' as unsigned integer);
SHOW WARNINGS;
END|
-CREATE PROCEDURE P6()
+CREATE PROCEDURE p7()
BEGIN
DECLARE c INT DEFAULT 0;
-DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
-CALL p5();
+DECLARE CONTINUE HANDLER FOR SQLWARNING
+BEGIN
+SET c = c + 1;
+SELECT 'Warning caught!' AS Msg;
+END;
+CALL p6();
SELECT c;
END|
+
CALL p1();
-CAST('10 ' as unsigned integer)
-10
-CAST('10 ' as unsigned integer)
-10
+CAST('2 ' as unsigned integer)
+2
+Msg
+Warning caught!
+CAST('3 ' as unsigned integer)
+3
1
1
-CAST('10 ' as unsigned integer)
-10
-CAST('10 ' as unsigned integer)
-10
+Msg
+Warning caught!
+CAST('4 ' as unsigned integer)
+4
+CAST('5 ' as unsigned integer)
+5
+CAST('2 ' as unsigned integer)
+2
+Msg
+Warning caught!
c
3
@@warning_count
-1
+0
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
+
+CALL p7();
+CAST('6 ' as unsigned integer)
+6
Level Code Message
-Warning 1292 Truncated incorrect INTEGER value: '10 '
+Warning 1292 Truncated incorrect INTEGER value: '6 '
+Msg
+Warning caught!
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;
+DROP PROCEDURE p7;
+DROP TABLE t1;
# - Case 3: check that "Exception trumps No Data".
@@ -1871,7 +1893,6 @@ exception
exception
Warnings:
Warning 1292 Truncated incorrect INTEGER value: '10 '
-Error 1048 Column 'b' cannot be null
DROP TABLE t1;
DROP PROCEDURE p1;
#
@@ -1915,11 +1936,8 @@ CALL p1();
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
=== modified file 'mysql-test/r/sp.result'
--- a/mysql-test/r/sp.result 2010-11-10 11:26:45 +0000
+++ b/mysql-test/r/sp.result 2010-12-15 18:21:04 +0000
@@ -737,8 +737,6 @@ 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
@@ -774,8 +772,6 @@ 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
@@ -865,8 +861,6 @@ 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
@@ -1688,64 +1682,42 @@ 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)
@@ -1758,18 +1730,12 @@ 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|
@@ -1918,8 +1884,6 @@ set @x2 = 2;
close c1;
end|
call bug2260()|
-Warnings:
-Error 1329 No data - zero rows fetched, selected, or processed
select @x2|
@x2
2
@@ -2063,8 +2027,6 @@ 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
@@ -2487,8 +2449,6 @@ declare continue handler for sqlstate 'H
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|
@@ -2628,17 +2588,13 @@ select row_count()|
row_count()
1
call bug4905()|
-Warnings:
-Error 1062 Duplicate entry '1' for key 'PRIMARY'
select row_count()|
row_count()
--1
+0
call bug4905()|
-Warnings:
-Error 1062 Duplicate entry '1' for key 'PRIMARY'
select row_count()|
row_count()
--1
+0
select * from t3|
s1
1
@@ -2659,14 +2615,10 @@ 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|
@@ -2958,23 +2910,15 @@ 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|
@@ -3017,13 +2961,9 @@ 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|
@@ -3254,8 +3194,6 @@ x
2
x
3
-Warnings:
-Error 1326 Cursor is not open
call bug10961()|
x
1
@@ -3263,8 +3201,6 @@ x
2
x
3
-Warnings:
-Error 1326 Cursor is not open
drop procedure bug10961|
DROP PROCEDURE IF EXISTS bug6866|
DROP VIEW IF EXISTS tv|
@@ -3380,11 +3316,7 @@ 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|
@@ -3558,32 +3490,24 @@ 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
@@ -3883,8 +3807,6 @@ end|
call bug7049_2()|
Result
Caught it
-Warnings:
-Error 1062 Duplicate entry '42' for key 'x'
select * from t3|
x
42
@@ -3892,16 +3814,12 @@ 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|
@@ -4029,8 +3947,6 @@ 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|
@@ -4234,8 +4150,6 @@ end|
call bug13729()|
55
55
-Warnings:
-Error 1062 Duplicate entry '1' for key 'PRIMARY'
select * from t3|
s1
1
@@ -4272,15 +4186,11 @@ 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|
@@ -4604,15 +4514,11 @@ 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
@@ -4620,22 +4526,16 @@ 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|
@@ -4700,8 +4600,6 @@ Before NOT FOUND condition is triggered
After NOT FOUND condtition is triggered
xid xdone
1 1
-Warnings:
-Warning 1329 No data - zero rows fetched, selected, or processed
call bug15231_3()|
Result
Missed it (correct)
@@ -4709,8 +4607,6 @@ 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
call bug15231_5()|
Result
Missed it (correct)
@@ -4739,8 +4635,6 @@ 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|
@@ -4816,8 +4710,6 @@ 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|
@@ -4890,8 +4782,6 @@ declare continue handler for sqlexceptio
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|
@@ -5265,8 +5155,6 @@ statement failed
statement failed
statement after update
statement after update
-Warnings:
-Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
@@ -5278,8 +5166,6 @@ statement failed
statement failed
statement after update
statement after update
-Warnings:
-Error 1242 Subquery returns more than 1 row
select * from t3|
a
1
@@ -5312,8 +5198,6 @@ 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
@@ -5329,8 +5213,6 @@ 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
@@ -5364,8 +5246,6 @@ 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|
@@ -5934,13 +5814,9 @@ 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|
@@ -6062,8 +5938,6 @@ 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
@@ -6075,8 +5949,6 @@ 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
@@ -6096,8 +5968,6 @@ 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
@@ -6109,8 +5979,6 @@ 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|
@@ -6824,8 +6692,6 @@ DECLARE CONTINUE HANDLER FOR SQLEXCEPTIO
SELECT x FROM t1;
END|
CALL bug29770();
-Warnings:
-Error 1054 Unknown column 'x' in 'field list'
SELECT @state, @exception;
@state @exception
run NULL
@@ -6864,8 +6730,6 @@ 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;
#
=== modified file 'mysql-test/r/sp_trans.result'
--- a/mysql-test/r/sp_trans.result 2010-10-07 12:47:15 +0000
+++ b/mysql-test/r/sp_trans.result 2010-12-15 18:21:04 +0000
@@ -99,8 +99,6 @@ 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
@@ -526,8 +524,6 @@ 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
=== modified file 'mysql-test/r/strict.result'
--- a/mysql-test/r/strict.result 2010-09-07 06:45:00 +0000
+++ b/mysql-test/r/strict.result 2010-12-15 18:21:04 +0000
@@ -1193,8 +1193,6 @@ select'a'; insert into t1 values (200);
call t1();
a
a
-Warnings:
-Error 1264 Out of range value for column 'col1' at row 1
select * from t1;
col1
drop procedure t1;
=== modified file 'mysql-test/r/view.result'
--- a/mysql-test/r/view.result 2010-12-03 09:18:23 +0000
+++ b/mysql-test/r/view.result 2010-12-15 18:21:04 +0000
@@ -3948,8 +3948,6 @@ create view a as select 1;
end|
call p();
call p();
-Warnings:
-Error 1050 Table 'a' already exists
drop view a;
drop procedure p;
#
=== modified file 'mysql-test/suite/rpl/r/rpl_row_sp005.result'
--- a/mysql-test/suite/rpl/r/rpl_row_sp005.result 2010-07-30 15:28:36 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_sp005.result 2010-12-15 18:21:04 +0000
@@ -77,8 +77,6 @@ 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
=== modified file 'mysql-test/suite/rpl/r/rpl_row_sp006_InnoDB.result'
--- a/mysql-test/suite/rpl/r/rpl_row_sp006_InnoDB.result 2010-07-30 15:28:36 +0000
+++ b/mysql-test/suite/rpl/r/rpl_row_sp006_InnoDB.result 2010-12-15 18:21:04 +0000
@@ -38,8 +38,6 @@ INSERT INTO t1 VALUES ('MySQL','1993-02-
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;
=== modified file 'mysql-test/t/sp-error.test'
--- a/mysql-test/t/sp-error.test 2010-10-26 11:48:08 +0000
+++ b/mysql-test/t/sp-error.test 2010-12-15 18:21:04 +0000
@@ -2585,15 +2585,26 @@ DROP PROCEDURE p2;
--echo # - Case 2
--echo
+--disable_warnings
+DROP TABLE IF EXISTS t1;
+--enable_warnings
+
+CREATE TABLE t1(a INT);
+
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();
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ BEGIN
+ SET c = c + 1;
+ SELECT 'Warning caught!' AS Msg;
+ END;
+ CALL p2(); # 1 warning
+ CALL p3(); # 1 warning
+ CALL p4(); # No warnings
+ CALL p5(); # 1 warning
SELECT c;
SELECT @@warning_count;
SHOW WARNINGS;
@@ -2601,39 +2612,54 @@ CREATE PROCEDURE p1()
CREATE PROCEDURE p2()
BEGIN
- SELECT CAST('10 ' as unsigned integer);
- END|
+ SELECT CAST('2 ' as unsigned integer);
+ END| # 1 warning is passed to the caller
CREATE PROCEDURE p3()
BEGIN
- SELECT CAST('10 ' as unsigned integer);
- SELECT 1;
- END|
+ SELECT CAST('3 ' as unsigned integer);
+ SELECT 1; # does not clear the warning
+ END| # 1 warning is passed to the caller
CREATE PROCEDURE p4()
BEGIN
- SELECT CAST('10 ' as unsigned integer);
+ SELECT CAST('4 ' as unsigned integer);
+ INSERT INTO t1 VALUES(1); # Clears the warning
+ END| # No warnings to pass
+
+CREATE PROCEDURE p5()
+ BEGIN
+ SELECT CAST('5 ' as unsigned integer);
CALL p2();
END|
-CREATE PROCEDURE p5()
+CREATE PROCEDURE p6()
BEGIN
- SELECT CAST('10 ' as unsigned integer);
+ SELECT CAST('6 ' as unsigned integer);
SHOW WARNINGS;
END|
-CREATE PROCEDURE P6()
+CREATE PROCEDURE p7()
BEGIN
DECLARE c INT DEFAULT 0;
- DECLARE CONTINUE HANDLER FOR SQLWARNING SET c = c + 1;
- CALL p5();
+ DECLARE CONTINUE HANDLER FOR SQLWARNING
+ BEGIN
+ SET c = c + 1;
+ SELECT 'Warning caught!' AS Msg;
+ END;
+ CALL p6();
SELECT c;
END|
delimiter ;|
+--echo
CALL p1();
-CALL p6();
+
+--echo
+CALL p7();
+
+--echo
DROP PROCEDURE p1;
DROP PROCEDURE p2;
@@ -2641,6 +2667,9 @@ DROP PROCEDURE p3;
DROP PROCEDURE p4;
DROP PROCEDURE p5;
DROP PROCEDURE p6;
+DROP PROCEDURE p7;
+
+DROP TABLE t1;
--echo
--echo # - Case 3: check that "Exception trumps No Data".
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2010-12-14 15:02:19 +0000
+++ b/sql/sp_head.cc 2010-12-15 18:21:04 +0000
@@ -1076,104 +1076,6 @@ void sp_head::recursion_level_error(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->get_stmt_da()->sql_errno(),
- thd->get_stmt_da()->get_sqlstate(),
- MYSQL_ERROR::WARN_LEVEL_ERROR,
- thd->get_stmt_da()->message());
- }
- else if (thd->get_warning_info()->statement_warn_count())
- {
- List_iterator<MYSQL_ERROR> it(thd->get_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.
@@ -1438,19 +1340,10 @@ sp_head::execute(THD *thd, bool merge_da
errors are not catchable by SQL handlers) or the connection has been
killed during execution.
*/
- if (!thd->is_fatal_error && !thd->killed_errno())
+ if (!thd->is_fatal_error && !thd->killed_errno() &&
+ ctx->handle_sql_condition(thd, &ip, i, &execute_arena, &backup_arena))
{
- /*
- 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);
-
- /* If found, activate handler for the current scope. */
- if (ctx->activate_handler(thd, &ip, i, &execute_arena, &backup_arena))
- err_status= FALSE;
+ err_status= FALSE;
}
/* Reset sp_rcontext::end_partial_result_set flag. */
@@ -1705,7 +1598,7 @@ sp_head::execute_trigger(THD *thd,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, 0, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, NULL)) ||
nctx->init(thd))
{
err_status= TRUE;
@@ -1822,7 +1715,7 @@ sp_head::execute_function(THD *thd, Item
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, return_value_fld)) ||
nctx->init(thd))
{
thd->restore_active_arena(&call_arena, &backup_arena);
@@ -2040,7 +1933,7 @@ sp_head::execute_procedure(THD *thd, Lis
if (! octx)
{
/* Create a temporary old context. */
- if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) || octx->init(thd))
+ if (!(octx= new sp_rcontext(m_pcont, NULL)) || octx->init(thd))
{
delete octx; /* Delete octx if it was init() that failed. */
DBUG_RETURN(TRUE);
@@ -2055,7 +1948,7 @@ sp_head::execute_procedure(THD *thd, Lis
thd->spcont->callers_arena= thd;
}
- if (!(nctx= new sp_rcontext(m_pcont, NULL, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, NULL)) ||
nctx->init(thd))
{
delete nctx; /* Delete nctx if it was init() that failed. */
@@ -3050,7 +2943,7 @@ int sp_instr::exec_open_and_lock_tables(
return result;
}
-uint sp_instr::get_cont_dest()
+uint sp_instr::get_cont_dest() const
{
return (m_ip+1);
}
@@ -3261,7 +3154,7 @@ sp_instr_set_trigger_field::print(String
sp_instr_opt_meta
*/
-uint sp_instr_opt_meta::get_cont_dest()
+uint sp_instr_opt_meta::get_cont_dest() const
{
return m_cont_dest;
}
=== modified file 'sql/sp_head.h'
--- a/sql/sp_head.h 2010-11-29 16:27:58 +0000
+++ b/sql/sp_head.h 2010-12-15 18:21:04 +0000
@@ -599,7 +599,7 @@ public:
Get the continuation destination of this instruction.
@return the continuation destination
*/
- virtual uint get_cont_dest();
+ virtual uint get_cont_dest() const;
/*
Execute core function of instruction after all preparations (e.g.
@@ -871,7 +871,7 @@ public:
virtual void set_destination(uint old_dest, uint new_dest)
= 0;
- virtual uint get_cont_dest();
+ virtual uint get_cont_dest() const;
protected:
=== modified file 'sql/sp_rcontext.cc'
--- a/sql/sp_rcontext.cc 2010-07-30 15:30:30 +0000
+++ b/sql/sp_rcontext.cc 2010-12-15 18:21:04 +0000
@@ -27,8 +27,7 @@
#include "sql_select.h" // create_virtual_tmp_table
sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx,
- Field *return_value_fld,
- sp_rcontext *prev_runtime_ctx)
+ Field *return_value_fld)
:end_partial_result_set(FALSE),
m_root_parsing_ctx(root_parsing_ctx),
m_var_table(0),
@@ -39,10 +38,8 @@ sp_rcontext::sp_rcontext(sp_pcontext *ro
m_hcount(0),
m_hsp(0),
m_ihsp(0),
- m_hfound(-1),
m_ccount(0),
- m_case_expr_holders(0),
- m_prev_runtime_ctx(prev_runtime_ctx)
+ m_case_expr_holders(0)
{
}
@@ -172,7 +169,7 @@ sp_rcontext::set_return_value(THD *thd,
#define IS_EXCEPTION_CONDITION(S) ((S)[0] != '0' || (S)[1] > '2')
/**
- Find an SQL handler for the given error.
+ Find an SQL handler for the given SQL condition.
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
@@ -183,39 +180,25 @@ sp_rcontext::set_return_value(THD *thd,
Note that mysql error code handlers is a MySQL extension, not part of
the standard.
- SQL handlers for warnings are searched in the current scope only.
-
- 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
+ @return SQL handler index, or -1 if there is no handler.
*/
-bool
+int
sp_rcontext::find_handler(THD *thd,
uint sql_errno,
const char *sqlstate,
MYSQL_ERROR::enum_warning_level level,
const char *msg)
{
+ int hfound= -1;
int i= m_hcount;
- /* Reset previously found handler. */
- m_hfound= -1;
-
/*
If this is a fatal sub-statement error, and this runtime
context corresponds to a sub-statement, no CONTINUE/EXIT
@@ -242,56 +225,42 @@ sp_rcontext::find_handler(THD *thd,
{
case sp_cond_type_t::number:
if (sql_errno == cond->mysqlerr &&
- (m_hfound < 0 || m_handler[m_hfound].cond->type > sp_cond_type_t::number))
- m_hfound= i; // Always the most specific
+ (hfound < 0 || m_handler[hfound].cond->type > sp_cond_type_t::number))
+ hfound= i; // Always the most specific
break;
case sp_cond_type_t::state:
if (strcmp(sqlstate, cond->sqlstate) == 0 &&
- (m_hfound < 0 || m_handler[m_hfound].cond->type > sp_cond_type_t::state))
- m_hfound= i;
+ (hfound < 0 || m_handler[hfound].cond->type > sp_cond_type_t::state))
+ hfound= i;
break;
case sp_cond_type_t::warning:
if ((IS_WARNING_CONDITION(sqlstate) ||
level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
- m_hfound < 0)
- m_hfound= i;
+ hfound < 0)
+ hfound= i;
break;
case sp_cond_type_t::notfound:
- if (IS_NOT_FOUND_CONDITION(sqlstate) && m_hfound < 0)
- m_hfound= i;
+ if (IS_NOT_FOUND_CONDITION(sqlstate) && hfound < 0)
+ hfound= i;
break;
case sp_cond_type_t::exception:
if (IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
- m_hfound < 0)
- m_hfound= i;
+ hfound < 0)
+ hfound= i;
break;
}
}
- if (m_hfound >= 0)
+ if (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;
- }
+ DBUG_ASSERT((uint) hfound < m_root_parsing_ctx->max_handler_index());
- /*
- Only "exception conditions" are propagated to handlers in calling
- contexts. If no handler is found locally for a "completion condition"
- (warning or "not found") we will simply resume execution.
- */
- 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);
+ m_raised_conditions[hfound].clear();
+ m_raised_conditions[hfound].set(sql_errno, sqlstate, level, msg);
}
- return FALSE;
+ return hfound;
}
void
@@ -370,31 +339,187 @@ sp_rcontext::pop_hstack()
}
/**
- Prepare found handler to be executed.
+ Handle current SQL condition (if any).
- @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
+ This is the public-interface function to handle SQL conditions in stored
+ routines.
+
+ @param thd Thread handle.
+ @param ip[out] Instruction pointer to the first handler instruction.
+ @param cur_spi Current SP instruction.
+ @param execute_arena Current execution arena for SP.
+ @param backup_arena Backup arena for SP.
*/
bool
+sp_rcontext::handle_sql_condition(THD *thd,
+ uint *ip,
+ const sp_instr *cur_spi,
+ Query_arena *execute_arena,
+ Query_arena *backup_arena)
+{
+ int handler_idx= find_handler(thd);
+
+ if (handler_idx < 0)
+ return FALSE;
+
+ activate_handler(thd, handler_idx, ip, cur_spi, execute_arena, backup_arena);
+
+ return TRUE;
+}
+
+
+/**
+ Find an SQL handler for any condition (warning or error) after execution
+ of a stored routine instruction. Basically, this function does two:
+ - looks for an appropriate SQL handler in the current RT-context;
+ - removes handled SQL condition from Warning Info.
+
+ If there is no pending condition, the function just returns.
+
+ 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 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 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
+
+ @return SQL handler index, or -1 if there is no handler or no pending SQL
+ condition.
+*/
+
+int
+sp_rcontext::find_handler(THD *thd)
+{
+ Diagnostics_area *da= thd->get_stmt_da();
+ Warning_info *wi= thd->get_warning_info();
+
+ if (thd->is_error())
+ {
+
+ int handler_idx= find_handler(thd, da->sql_errno(), da->get_sqlstate(),
+ MYSQL_ERROR::WARN_LEVEL_ERROR, da->message());
+ if (handler_idx < 0)
+ return -1;
+
+ MYSQL_ERROR *err_condition= wi->get_error_condition();
+
+ if (!err_condition)
+ return -1;
+
+ List_iterator<MYSQL_ERROR> it(wi->warn_list());
+ MYSQL_ERROR *err;
+
+ while ((err= it++))
+ {
+ if (err != err_condition)
+ continue;
+
+ da->remove_warning(err);
+ it.remove();
+
+ break;
+ }
+
+ return handler_idx;
+ }
+ else if (wi->statement_warn_count())
+ {
+ List_iterator<MYSQL_ERROR> it(wi->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;
+
+ int handler_idx= find_handler(thd,
+ err->get_sql_errno(),
+ err->get_sqlstate(),
+ err->get_level(),
+ err->get_message_text());
+ if (handler_idx < 0)
+ continue;
+
+ da->remove_warning(err);
+ it.remove();
+
+ return handler_idx;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ Prepare an SQL handler to be executed.
+
+ @param thd Thread handle.
+ @param handler_idx Handler index (must be >= 0).
+ @param ip[out] Instruction pointer to the first handler instruction.
+ @param cur_spi Current SP instruction.
+ @param execute_arena Current execution arena for SP.
+ @param backup_arena Backup arena for SP.
+*/
+
+void
sp_rcontext::activate_handler(THD *thd,
+ int handler_idx,
uint *ip,
- sp_instr *instr,
+ const sp_instr *cur_spi,
Query_arena *execute_arena,
Query_arena *backup_arena)
{
- if (m_hfound < 0)
- return FALSE;
+ DBUG_ASSERT(handler_idx >= 0);
- switch (m_handler[m_hfound].type) {
+ switch (m_handler[handler_idx].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());
+ push_hstack(cur_spi->get_cont_dest());
/* Fall through */
@@ -407,10 +532,9 @@ sp_rcontext::activate_handler(THD *thd,
/* Enter handler. */
DBUG_ASSERT(m_ihsp < m_root_parsing_ctx->max_handler_index());
- 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_in_handler[m_ihsp].ip= m_handler[handler_idx].handler;
+ m_in_handler[m_ihsp].index= handler_idx;
m_ihsp++;
DBUG_PRINT("info", ("Entering handler..."));
@@ -423,13 +547,8 @@ sp_rcontext::activate_handler(THD *thd,
// (e.g. "bad data").
/* Return IP of the activated SQL handler. */
- *ip= m_handler[m_hfound].handler;
-
- /* Reset found handler. */
- m_hfound= -1;
+ *ip= m_handler[handler_idx].handler;
}
-
- return TRUE;
}
void
@@ -456,9 +575,6 @@ sp_rcontext::raised_condition() const
return raised;
}
- if (m_prev_runtime_ctx)
- return m_prev_runtime_ctx->raised_condition();
-
return NULL;
}
=== modified file 'sql/sp_rcontext.h'
--- a/sql/sp_rcontext.h 2010-11-13 15:11:39 +0000
+++ b/sql/sp_rcontext.h 2010-12-15 18:21:04 +0000
@@ -107,8 +107,7 @@ class sp_rcontext : public Sql_alloc
sp_head *sp;
#endif
- sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld,
- sp_rcontext *prev_runtime_ctx);
+ sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld);
bool init(THD *thd);
~sp_rcontext();
@@ -139,13 +138,6 @@ class sp_rcontext : public Sql_alloc
void pop_handlers(uint count);
- bool
- find_handler(THD *thd,
- uint sql_errno,
- const char *sqlstate,
- MYSQL_ERROR::enum_warning_level level,
- const char *msg);
-
MYSQL_ERROR *
raised_condition() const;
@@ -156,12 +148,11 @@ class sp_rcontext : public Sql_alloc
pop_hstack();
bool
- activate_handler(THD *thd,
- uint *ip,
- sp_instr *instr,
- Query_arena *execute_arena,
- Query_arena *backup_arena);
-
+ handle_sql_condition(THD *thd,
+ uint *ip,
+ const sp_instr *cur_spi,
+ Query_arena *execute_arena,
+ Query_arena *backup_arena);
void
exit_handler();
@@ -198,6 +189,25 @@ class sp_rcontext : public Sql_alloc
get_case_expr_addr(int case_expr_id);
private:
+ int
+ find_handler(THD *thd);
+
+ int
+ find_handler(THD *thd,
+ uint sql_errno,
+ const char *sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char *msg);
+
+ void
+ activate_handler(THD *thd,
+ int handler_idx,
+ uint *ip,
+ const sp_instr *cur_spi,
+ Query_arena *execute_arena,
+ Query_arena *backup_arena);
+
+private:
sp_pcontext *m_root_parsing_ctx;
/* Virtual table for storing variables. */
@@ -240,16 +250,12 @@ private:
/** Active handler stack. */
sp_active_handler_t *m_in_handler;
uint m_ihsp; // Stack pointer for m_in_handler
- int m_hfound; // Set by find_handler; -1 if not found
sp_cursor **m_cstack;
uint m_ccount;
Item_cache **m_case_expr_holders;
- /* Previous runtime context (NULL if none) */
- sp_rcontext *m_prev_runtime_ctx;
-
private:
bool init_var_table(THD *thd);
bool init_var_items();
=== modified file 'sql/sql_error.cc'
--- a/sql/sql_error.cc 2010-12-15 12:00:26 +0000
+++ b/sql/sql_error.cc 2010-12-15 18:21:04 +0000
@@ -505,6 +505,13 @@ void Warning_info::append_warning_info(T
}
}
+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
@@ -574,6 +581,12 @@ MYSQL_ERROR *Warning_info::push_warning(
return cond;
}
+void Warning_info::remove_warning(const MYSQL_ERROR *sql_condition)
+{
+ m_warn_count[sql_condition->get_level()]--;
+ m_statement_warn_count--;
+}
+
MYSQL_ERROR *Warning_info::push_warning(THD *thd, const MYSQL_ERROR *sql_condition)
{
MYSQL_ERROR *new_condition= push_warning(thd,
=== modified file 'sql/sql_error.h'
--- a/sql/sql_error.h 2010-12-15 12:00:26 +0000
+++ b/sql/sql_error.h 2010-12-15 18:21:04 +0000
@@ -327,6 +327,8 @@ public:
ulong statement_warn_count() const { return m_statement_warn_count; }
+ 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,
@@ -367,10 +369,14 @@ public:
{ m_error_condition= NULL; }
private:
+ void remove_warning(const MYSQL_ERROR *sql_condition);
+
+private:
/** Read only status. */
bool m_read_only;
friend class Sql_cmd_resignal;
+ friend class Diagnostics_area;
};
/**
@@ -440,6 +446,12 @@ public:
return m_statement_warn_count;
}
+ void remove_warning(const MYSQL_ERROR *sql_condition)
+ {
+ --m_statement_warn_count;
+ m_warning_info->remove_warning(sql_condition);
+ }
+
Diagnostics_area(Warning_info *warning_info) :
m_warning_info(warning_info)
{ reset_diagnostics_area(); }
=== modified file 'sql/sql_signal.cc'
--- a/sql/sql_signal.cc 2010-12-14 15:02:19 +0000
+++ b/sql/sql_signal.cc 2010-12-15 18:21:04 +0000
@@ -492,14 +492,24 @@ bool Sql_cmd_resignal::execute(THD *thd)
DBUG_RETURN(result);
}
- if (m_cond == NULL)
+ if (m_cond)
{
- /* RESIGNAL without signal_value */
- result= raise_condition(thd, signaled);
- DBUG_RETURN(result);
+ MYSQL_ERROR *cond;
+
+ query_cache_abort(&thd->query_cache_tls);
+
+ /* Make room for 2 conditions. */
+ thd->get_warning_info()->reserve_space(thd, 2);
+
+ cond= thd->get_warning_info()->push_warning(thd,
+ signaled->get_sql_errno(),
+ signaled->get_sqlstate(),
+ signaled->get_level(),
+ signaled->get_message_text());
+ if (cond)
+ cond->copy_opt_attributes(signaled);
}
- /* RESIGNAL with signal_value */
result= raise_condition(thd, signaled);
DBUG_RETURN(result);
Attachment: [text/bzr-bundle] bzr/alexander.nozdrin@oracle.com-20101215182104-0sfn1kkjx3cnas0g.bundle
| Thread |
|---|
| • bzr commit into mysql-trunk-bugfixing branch (alexander.nozdrin:3426)Bug#55843 | Alexander Nozdrin | 15 Dec |