From 5e84bbcb8f6b174906fca986c3404df4d2e9128c Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Dec 2005 13:12:42 +0100 Subject: [PATCH 1/3] Fixed BUG#15231: Stored procedure bug with not found condition handler Make the distinction between "exception conditions" and "completion conditions" (warning and "no data") as defined by the standard. The latter should not terminate a routine if no handler is found in the lexical scope. mysql-test/r/sp.result: New test case for BUG#15231. Moved part of the test for BUG#7049 to the new testcase (since it was actually an example of 15231). mysql-test/t/sp.test: New test case for BUG#15231. Moved part of the test for BUG#7049 to the new testcase (since it was actually an example of 15231). sql/sp_rcontext.cc: Only search for matching condition handlers in caller's contexts if it's an exception conditition. --- mysql-test/r/sp.result | 74 +++++++++++++++++++++++++++---------- mysql-test/t/sp.test | 83 +++++++++++++++++++++++++++++++----------- sql/sp_rcontext.cc | 23 ++++++++---- 3 files changed, 133 insertions(+), 47 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ded9754f172..288d25262e8 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3557,8 +3557,6 @@ drop procedure if exists bug7049_1| drop procedure if exists bug7049_2| drop procedure if exists bug7049_3| drop procedure if exists bug7049_4| -drop procedure if exists bug7049_5| -drop procedure if exists bug7049_6| drop function if exists bug7049_1| drop function if exists bug7049_2| create table t3 ( x int unique )| @@ -3583,18 +3581,6 @@ select 'Caught it' as 'Result'; call bug7049_3(); select 'Missed it' as 'Result'; end| -create procedure bug7049_5() -begin -declare x decimal(2,1); -set x = 'zap'; -end| -create procedure bug7049_6() -begin -declare exit handler for sqlwarning -select 'Caught it' as 'Result'; -call bug7049_5(); -select 'Missed it' as 'Result'; -end| create function bug7049_1() returns int begin @@ -3624,9 +3610,6 @@ Caught it select * from t3| x 42 -call bug7049_6()| -Result -Caught it select bug7049_2()| bug7049_2() 1 @@ -3635,8 +3618,6 @@ drop procedure bug7049_1| drop procedure bug7049_2| drop procedure bug7049_3| drop procedure bug7049_4| -drop procedure bug7049_5| -drop procedure bug7049_6| drop function bug7049_1| drop function bug7049_2| drop function if exists bug13941| @@ -4320,4 +4301,59 @@ id county 2 NULL drop table t3| drop procedure bug15441| +drop table if exists t3| +drop procedure if exists bug15231_1| +drop procedure if exists bug15231_2| +drop procedure if exists bug15231_3| +drop procedure if exists bug15231_4| +create table t3 (id int not null)| +create procedure bug15231_1() +begin +declare xid integer; +declare xdone integer default 0; +declare continue handler for not found set xdone = 1; +set xid=null; +call bug15231_2(xid); +select xid, xdone; +end| +create procedure bug15231_2(inout ioid integer) +begin +select "Before NOT FOUND condition is triggered" as '1'; +select id into ioid from t3 where id=ioid; +select "After NOT FOUND condtition is triggered" as '2'; +if ioid is null then +set ioid=1; +end if; +end| +create procedure bug15231_3() +begin +declare exit handler for sqlwarning +select 'Caught it (wrong)' as 'Result'; +call bug15231_4(); +end| +create procedure bug15231_4() +begin +declare x decimal(2,1); +set x = 'zap'; +select 'Missed it (correct)' as 'Result'; +end| +call bug15231_1()| +1 +Before NOT FOUND condition is triggered +2 +After NOT FOUND condtition is triggered +xid xdone +1 0 +Warnings: +Warning 1329 No data to FETCH +call bug15231_3()| +Result +Missed it (correct) +Warnings: +Warning 1366 Incorrect decimal value: 'zap' for column 'x' at row 1 +drop table if exists t3| +drop procedure if exists bug15231_1| +drop procedure if exists bug15231_2| +drop procedure if exists bug15231_3| +drop procedure if exists bug15231_4| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index f73288f04ba..8af5b4719a1 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4288,8 +4288,6 @@ drop procedure if exists bug7049_1| drop procedure if exists bug7049_2| drop procedure if exists bug7049_3| drop procedure if exists bug7049_4| -drop procedure if exists bug7049_5| -drop procedure if exists bug7049_6| drop function if exists bug7049_1| drop function if exists bug7049_2| --enable_warnings @@ -4323,22 +4321,6 @@ begin select 'Missed it' as 'Result'; end| -create procedure bug7049_5() -begin - declare x decimal(2,1); - - set x = 'zap'; -end| - -create procedure bug7049_6() -begin - declare exit handler for sqlwarning - select 'Caught it' as 'Result'; - - call bug7049_5(); - select 'Missed it' as 'Result'; -end| - create function bug7049_1() returns int begin @@ -4363,7 +4345,6 @@ select * from t3| delete from t3| call bug7049_4()| select * from t3| -call bug7049_6()| select bug7049_2()| drop table t3| @@ -4371,8 +4352,6 @@ drop procedure bug7049_1| drop procedure bug7049_2| drop procedure bug7049_3| drop procedure bug7049_4| -drop procedure bug7049_5| -drop procedure bug7049_6| drop function bug7049_1| drop function bug7049_2| @@ -5078,6 +5057,68 @@ call bug15441('Yale')| drop table t3| drop procedure bug15441| + +# +# BUG#15231: +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug15231_1| +drop procedure if exists bug15231_2| +drop procedure if exists bug15231_3| +drop procedure if exists bug15231_4| +--enable_warnings + +create table t3 (id int not null)| + +create procedure bug15231_1() +begin + declare xid integer; + declare xdone integer default 0; + declare continue handler for not found set xdone = 1; + + set xid=null; + call bug15231_2(xid); + select xid, xdone; +end| + +create procedure bug15231_2(inout ioid integer) +begin + select "Before NOT FOUND condition is triggered" as '1'; + select id into ioid from t3 where id=ioid; + select "After NOT FOUND condtition is triggered" as '2'; + + if ioid is null then + set ioid=1; + end if; +end| + +create procedure bug15231_3() +begin + declare exit handler for sqlwarning + select 'Caught it (wrong)' as 'Result'; + + call bug15231_4(); +end| + +create procedure bug15231_4() +begin + declare x decimal(2,1); + + set x = 'zap'; + select 'Missed it (correct)' as 'Result'; +end| + +call bug15231_1()| +call bug15231_3()| + +drop table if exists t3| +drop procedure if exists bug15231_1| +drop procedure if exists bug15231_2| +drop procedure if exists bug15231_3| +drop procedure if exists bug15231_4| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index eca87e69f8e..c36c904f45d 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -160,6 +160,10 @@ sp_rcontext::set_return_value(THD *thd, Item *return_value_item) } +#define IS_WARNING_CONDITION(S) ((S)[0] == '0' && (S)[1] == '1') +#define IS_NOT_FOUND_CONDITION(S) ((S)[0] == '0' && (S)[1] == '2') +#define IS_EXCEPTION_CONDITION(S) ((S)[0] != '0' || (S)[1] > '2') + bool sp_rcontext::find_handler(uint sql_errno, MYSQL_ERROR::enum_warning_level level) @@ -193,18 +197,17 @@ sp_rcontext::find_handler(uint sql_errno, found= i; break; case sp_cond_type_t::warning: - if ((sqlstate[0] == '0' && sqlstate[1] == '1' || - level == MYSQL_ERROR::WARN_LEVEL_WARN) && - found < 0) + if ((IS_WARNING_CONDITION(sqlstate) || + level == MYSQL_ERROR::WARN_LEVEL_WARN) && + found < 0) found= i; break; case sp_cond_type_t::notfound: - if (sqlstate[0] == '0' && sqlstate[1] == '2' && - found < 0) + if (IS_NOT_FOUND_CONDITION(sqlstate) && found < 0) found= i; break; case sp_cond_type_t::exception: - if ((sqlstate[0] != '0' || sqlstate[1] > '2') && + if (IS_EXCEPTION_CONDITION(sqlstate) && level == MYSQL_ERROR::WARN_LEVEL_ERROR && found < 0) found= i; @@ -213,7 +216,13 @@ sp_rcontext::find_handler(uint sql_errno, } if (found < 0) { - if (m_prev_runtime_ctx) + /* + 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(sql_errno, level); return FALSE; } From 2111e2035be48f1a6b40f995d1eef304a1a01ff8 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 13 Dec 2005 13:22:15 +0100 Subject: [PATCH 2/3] Added bug synopsis in comment for sp.test case BUG#15231. mysql-test/t/sp.test: Added bug synopsis in comment for test case BUG#15231. --- mysql-test/t/sp.test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 8af5b4719a1..2c323a6d2c6 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5059,7 +5059,7 @@ drop procedure bug15441| # -# BUG#15231: +# BUG#15231: Stored procedure bug with not found condition handler # --disable_warnings drop table if exists t3| From fbe2ba9fa85eae468c452c834705bdb69a31b079 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 17 Jan 2006 12:48:48 +0100 Subject: [PATCH 3/3] Post-review fix. (BUG#15231) sql/sp_rcontext.cc: Post-review fix. --- sql/sp_rcontext.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc index c36c904f45d..215de01e657 100644 --- a/sql/sp_rcontext.cc +++ b/sql/sp_rcontext.cc @@ -220,7 +220,7 @@ sp_rcontext::find_handler(uint sql_errno, 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(sql_errno, level);