List:Commits« Previous MessageNext Message »
From:Alexander Nozdrin Date:December 15 2010 6:21pm
Subject:bzr commit into mysql-trunk-bugfixing branch (alexander.nozdrin:3426)
Bug#55843
View as plain text  
#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#55843Alexander Nozdrin15 Dec