Commit d9c12f82 authored by unknown's avatar unknown

Fixed BUG#6029: Stored procedure specific handlers should have priority.


mysql-test/r/sp.result:
  New test case for BUG#6022.
mysql-test/t/sp.test:
  New test case for BUG#6022.
sql/sp_rcontext.cc:
  Find the most specific condition handler, not just the first one.
  (And corrected the return type for find_handler)
sql/sp_rcontext.h:
  Corrected return type for find_handler.
parent 5174a837
...@@ -1947,6 +1947,26 @@ select bug6022(5)| ...@@ -1947,6 +1947,26 @@ select bug6022(5)|
bug6022(5) bug6022(5)
0 0
drop function bug6022| drop function bug6022|
drop procedure if exists bug6029|
create procedure bug6029()
begin
declare exit handler for 1136 select '1136';
declare exit handler for sqlstate '23000' select 'sqlstate 23000';
declare continue handler for sqlexception select 'sqlexception';
insert into t3 values (1);
insert into t3 values (1,2);
end|
create table t3 (s1 int, primary key (s1))|
insert into t3 values (1)|
call bug6029()|
sqlstate 23000
sqlstate 23000
delete from t3|
call bug6029()|
1136
1136
drop procedure bug6029|
drop table t3|
drop table if exists fac| drop table if exists fac|
create table fac (n int unsigned not null primary key, f bigint unsigned)| create table fac (n int unsigned not null primary key, f bigint unsigned)|
create procedure ifac(n int unsigned) create procedure ifac(n int unsigned)
......
...@@ -2109,6 +2109,32 @@ end| ...@@ -2109,6 +2109,32 @@ end|
select bug6022(5)| select bug6022(5)|
drop function bug6022| drop function bug6022|
#
# BUG#6029: Stored procedure specific handlers should have priority
#
--disable_warnings
drop procedure if exists bug6029|
--enable_warnings
create procedure bug6029()
begin
declare exit handler for 1136 select '1136';
declare exit handler for sqlstate '23000' select 'sqlstate 23000';
declare continue handler for sqlexception select 'sqlexception';
insert into t3 values (1);
insert into t3 values (1,2);
end|
create table t3 (s1 int, primary key (s1))|
insert into t3 values (1)|
call bug6029()|
delete from t3|
call bug6029()|
drop procedure bug6029|
drop table t3|
# #
# Some "real" examples # Some "real" examples
......
...@@ -56,7 +56,7 @@ sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type) ...@@ -56,7 +56,7 @@ sp_rcontext::set_item_eval(uint idx, Item *i, enum_field_types type)
} }
} }
int 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)
{ {
...@@ -66,9 +66,9 @@ sp_rcontext::find_handler(uint sql_errno, ...@@ -66,9 +66,9 @@ sp_rcontext::find_handler(uint sql_errno,
return 1; // Already got one return 1; // Already got one
const char *sqlstate= mysql_errno_to_sqlstate(sql_errno); const char *sqlstate= mysql_errno_to_sqlstate(sql_errno);
int i= m_hcount, found= 0; int i= m_hcount, found= -1;
while (!found && i--) while (i--)
{ {
sp_cond_type_t *cond= m_handler[i].cond; sp_cond_type_t *cond= m_handler[i].cond;
...@@ -76,31 +76,36 @@ sp_rcontext::find_handler(uint sql_errno, ...@@ -76,31 +76,36 @@ sp_rcontext::find_handler(uint sql_errno,
{ {
case sp_cond_type_t::number: case sp_cond_type_t::number:
if (sql_errno == cond->mysqlerr) if (sql_errno == cond->mysqlerr)
found= 1; found= i; // Always the most specific
break; break;
case sp_cond_type_t::state: case sp_cond_type_t::state:
if (strcmp(sqlstate, cond->sqlstate) == 0) if (strcmp(sqlstate, cond->sqlstate) == 0 &&
found= 1; (found < 0 || m_handler[found].cond->type > sp_cond_type_t::number))
found= i;
break; break;
case sp_cond_type_t::warning: case sp_cond_type_t::warning:
if (sqlstate[0] == '0' && sqlstate[1] == '1' || if ((sqlstate[0] == '0' && sqlstate[1] == '1' ||
level == MYSQL_ERROR::WARN_LEVEL_WARN) level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
found= 1; (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state))
found= i;
break; break;
case sp_cond_type_t::notfound: case sp_cond_type_t::notfound:
if (sqlstate[0] == '0' && sqlstate[1] == '2') if (sqlstate[0] == '0' && sqlstate[1] == '2' &&
found= 1; (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state))
found= i;
break; break;
case sp_cond_type_t::exception: case sp_cond_type_t::exception:
if (sqlstate[0] != '0' || sqlstate[1] > '2' || if ((sqlstate[0] != '0' || sqlstate[1] > '2' ||
level == MYSQL_ERROR::WARN_LEVEL_ERROR) level == MYSQL_ERROR::WARN_LEVEL_ERROR) &&
found= 1; (found < 0 || m_handler[found].cond->type > sp_cond_type_t::state))
found= i;
break; break;
} }
} }
if (found) if (found < 0)
m_hfound= i; return FALSE;
return found; m_hfound= found;
return TRUE;
} }
void void
......
...@@ -122,7 +122,7 @@ class sp_rcontext : public Sql_alloc ...@@ -122,7 +122,7 @@ class sp_rcontext : public Sql_alloc
} }
// Returns 1 if a handler was found, 0 otherwise. // Returns 1 if a handler was found, 0 otherwise.
int bool
find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level); find_handler(uint sql_errno,MYSQL_ERROR::enum_warning_level level);
// Returns handler type and sets *ip to location if one was found // Returns handler type and sets *ip to location if one was found
......
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