Commit 5e84bbcb authored by unknown's avatar unknown

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.
parent 95cabee1
...@@ -3557,8 +3557,6 @@ drop procedure if exists bug7049_1| ...@@ -3557,8 +3557,6 @@ drop procedure if exists bug7049_1|
drop procedure if exists bug7049_2| drop procedure if exists bug7049_2|
drop procedure if exists bug7049_3| drop procedure if exists bug7049_3|
drop procedure if exists bug7049_4| 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_1|
drop function if exists bug7049_2| drop function if exists bug7049_2|
create table t3 ( x int unique )| create table t3 ( x int unique )|
...@@ -3583,18 +3581,6 @@ select 'Caught it' as 'Result'; ...@@ -3583,18 +3581,6 @@ select 'Caught it' as 'Result';
call bug7049_3(); call bug7049_3();
select 'Missed it' as 'Result'; select 'Missed it' as 'Result';
end| 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() create function bug7049_1()
returns int returns int
begin begin
...@@ -3624,9 +3610,6 @@ Caught it ...@@ -3624,9 +3610,6 @@ Caught it
select * from t3| select * from t3|
x x
42 42
call bug7049_6()|
Result
Caught it
select bug7049_2()| select bug7049_2()|
bug7049_2() bug7049_2()
1 1
...@@ -3635,8 +3618,6 @@ drop procedure bug7049_1| ...@@ -3635,8 +3618,6 @@ drop procedure bug7049_1|
drop procedure bug7049_2| drop procedure bug7049_2|
drop procedure bug7049_3| drop procedure bug7049_3|
drop procedure bug7049_4| drop procedure bug7049_4|
drop procedure bug7049_5|
drop procedure bug7049_6|
drop function bug7049_1| drop function bug7049_1|
drop function bug7049_2| drop function bug7049_2|
drop function if exists bug13941| drop function if exists bug13941|
...@@ -4320,4 +4301,59 @@ id county ...@@ -4320,4 +4301,59 @@ id county
2 NULL 2 NULL
drop table t3| drop table t3|
drop procedure bug15441| 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; drop table t1,t2;
...@@ -4288,8 +4288,6 @@ drop procedure if exists bug7049_1| ...@@ -4288,8 +4288,6 @@ drop procedure if exists bug7049_1|
drop procedure if exists bug7049_2| drop procedure if exists bug7049_2|
drop procedure if exists bug7049_3| drop procedure if exists bug7049_3|
drop procedure if exists bug7049_4| 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_1|
drop function if exists bug7049_2| drop function if exists bug7049_2|
--enable_warnings --enable_warnings
...@@ -4323,22 +4321,6 @@ begin ...@@ -4323,22 +4321,6 @@ begin
select 'Missed it' as 'Result'; select 'Missed it' as 'Result';
end| 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() create function bug7049_1()
returns int returns int
begin begin
...@@ -4363,7 +4345,6 @@ select * from t3| ...@@ -4363,7 +4345,6 @@ select * from t3|
delete from t3| delete from t3|
call bug7049_4()| call bug7049_4()|
select * from t3| select * from t3|
call bug7049_6()|
select bug7049_2()| select bug7049_2()|
drop table t3| drop table t3|
...@@ -4371,8 +4352,6 @@ drop procedure bug7049_1| ...@@ -4371,8 +4352,6 @@ drop procedure bug7049_1|
drop procedure bug7049_2| drop procedure bug7049_2|
drop procedure bug7049_3| drop procedure bug7049_3|
drop procedure bug7049_4| drop procedure bug7049_4|
drop procedure bug7049_5|
drop procedure bug7049_6|
drop function bug7049_1| drop function bug7049_1|
drop function bug7049_2| drop function bug7049_2|
...@@ -5078,6 +5057,68 @@ call bug15441('Yale')| ...@@ -5078,6 +5057,68 @@ call bug15441('Yale')|
drop table t3| drop table t3|
drop procedure bug15441| 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 # BUG#NNNN: New bug synopsis
# #
......
...@@ -160,6 +160,10 @@ sp_rcontext::set_return_value(THD *thd, Item *return_value_item) ...@@ -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 bool
sp_rcontext::find_handler(uint sql_errno, sp_rcontext::find_handler(uint sql_errno,
MYSQL_ERROR::enum_warning_level level) MYSQL_ERROR::enum_warning_level level)
...@@ -193,18 +197,17 @@ sp_rcontext::find_handler(uint sql_errno, ...@@ -193,18 +197,17 @@ sp_rcontext::find_handler(uint sql_errno,
found= i; found= i;
break; break;
case sp_cond_type_t::warning: case sp_cond_type_t::warning:
if ((sqlstate[0] == '0' && sqlstate[1] == '1' || if ((IS_WARNING_CONDITION(sqlstate) ||
level == MYSQL_ERROR::WARN_LEVEL_WARN) && level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
found < 0) found < 0)
found= i; found= i;
break; break;
case sp_cond_type_t::notfound: case sp_cond_type_t::notfound:
if (sqlstate[0] == '0' && sqlstate[1] == '2' && if (IS_NOT_FOUND_CONDITION(sqlstate) && found < 0)
found < 0)
found= i; found= i;
break; break;
case sp_cond_type_t::exception: case sp_cond_type_t::exception:
if ((sqlstate[0] != '0' || sqlstate[1] > '2') && if (IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR && level == MYSQL_ERROR::WARN_LEVEL_ERROR &&
found < 0) found < 0)
found= i; found= i;
...@@ -213,7 +216,13 @@ sp_rcontext::find_handler(uint sql_errno, ...@@ -213,7 +216,13 @@ sp_rcontext::find_handler(uint sql_errno,
} }
if (found < 0) 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 m_prev_runtime_ctx->find_handler(sql_errno, level);
return FALSE; return FALSE;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment