mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fixed BUG#6127: Stored procedure handlers within handlers don't work
Replaced the dumb in-handler/not-in-handler check with a proper recursion
check of handlers being executed.
(Re-commit in a different tree, to make push possible.)
mysql-test/r/sp.result:
New test case for BUG#6127.
mysql-test/t/sp.test:
New test case for BUG#6127.
sql/sp_head.cc:
Replaced the setting of ctx->in_handler with a enter/exit handler methods.
sql/sp_rcontext.cc:
Replaced the boolean in_handler flag with a stack of handlers being exectuted, for proper recursion check.
sql/sp_rcontext.h:
Replaced the boolean in_handler flag with a stack of handlers being exectuted, for proper recursion check.
(And added some comments in the sp_rcontext class.)
This commit is contained in:
@@ -3360,4 +3360,34 @@ call bug12979_2()|
|
||||
internal_var
|
||||
NULL
|
||||
drop procedure bug12979_2|
|
||||
drop table if exists t3|
|
||||
drop procedure if exists bug6127|
|
||||
create table t3 (s1 int unique)|
|
||||
set @sm=@@sql_mode|
|
||||
set sql_mode='traditional'|
|
||||
create procedure bug6127()
|
||||
begin
|
||||
declare continue handler for sqlstate '23000'
|
||||
begin
|
||||
declare continue handler for sqlstate '22003'
|
||||
insert into t3 values (0);
|
||||
insert into t3 values (1000000000000000);
|
||||
end;
|
||||
insert into t3 values (1);
|
||||
insert into t3 values (1);
|
||||
end|
|
||||
call bug6127()|
|
||||
select * from t3|
|
||||
s1
|
||||
0
|
||||
1
|
||||
call bug6127()|
|
||||
ERROR 23000: Duplicate entry '0' for key 1
|
||||
select * from t3|
|
||||
s1
|
||||
0
|
||||
1
|
||||
set sql_mode=@sm|
|
||||
drop table t3|
|
||||
drop procedure bug6127|
|
||||
drop table t1,t2;
|
||||
|
||||
@@ -4228,6 +4228,42 @@ call bug12979_2()|
|
||||
drop procedure bug12979_2|
|
||||
|
||||
|
||||
#
|
||||
# BUG#6127: Stored procedure handlers within handlers don't work
|
||||
#
|
||||
--disable_warnings
|
||||
drop table if exists t3|
|
||||
drop procedure if exists bug6127|
|
||||
--enable_warnings
|
||||
create table t3 (s1 int unique)|
|
||||
|
||||
set @sm=@@sql_mode|
|
||||
set sql_mode='traditional'|
|
||||
|
||||
create procedure bug6127()
|
||||
begin
|
||||
declare continue handler for sqlstate '23000'
|
||||
begin
|
||||
declare continue handler for sqlstate '22003'
|
||||
insert into t3 values (0);
|
||||
|
||||
insert into t3 values (1000000000000000);
|
||||
end;
|
||||
|
||||
insert into t3 values (1);
|
||||
insert into t3 values (1);
|
||||
end|
|
||||
|
||||
call bug6127()|
|
||||
select * from t3|
|
||||
--error ER_DUP_ENTRY
|
||||
call bug6127()|
|
||||
select * from t3|
|
||||
set sql_mode=@sm|
|
||||
drop table t3|
|
||||
drop procedure bug6127|
|
||||
|
||||
|
||||
#
|
||||
# BUG#NNNN: New bug synopsis
|
||||
#
|
||||
|
||||
@@ -1015,7 +1015,7 @@ int sp_head::execute(THD *thd)
|
||||
ip= hip;
|
||||
ret= 0;
|
||||
ctx->clear_handler();
|
||||
ctx->in_handler= TRUE;
|
||||
ctx->enter_handler(hip);
|
||||
thd->clear_error();
|
||||
thd->killed= THD::NOT_KILLED;
|
||||
continue;
|
||||
@@ -2378,7 +2378,7 @@ sp_instr_hreturn::execute(THD *thd, uint *nextp)
|
||||
thd->spcont->restore_variables(m_frame);
|
||||
*nextp= thd->spcont->pop_hstack();
|
||||
}
|
||||
thd->spcont->in_handler= FALSE;
|
||||
thd->spcont->exit_handler();
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
@@ -31,12 +31,12 @@
|
||||
|
||||
sp_rcontext::sp_rcontext(uint fsize, uint hmax, uint cmax)
|
||||
: m_count(0), m_fsize(fsize), m_result(NULL), m_hcount(0), m_hsp(0),
|
||||
m_hfound(-1), m_ccount(0)
|
||||
m_ihsp(0), m_hfound(-1), m_ccount(0)
|
||||
{
|
||||
in_handler= FALSE;
|
||||
m_frame= (Item **)sql_alloc(fsize * sizeof(Item*));
|
||||
m_handler= (sp_handler_t *)sql_alloc(hmax * sizeof(sp_handler_t));
|
||||
m_hstack= (uint *)sql_alloc(hmax * sizeof(uint));
|
||||
m_in_handler= (uint *)sql_alloc(hmax * sizeof(uint));
|
||||
m_cstack= (sp_cursor **)sql_alloc(cmax * sizeof(sp_cursor *));
|
||||
m_saved.empty();
|
||||
}
|
||||
@@ -68,8 +68,6 @@ bool
|
||||
sp_rcontext::find_handler(uint sql_errno,
|
||||
MYSQL_ERROR::enum_warning_level level)
|
||||
{
|
||||
if (in_handler)
|
||||
return 0; // Already executing a handler
|
||||
if (m_hfound >= 0)
|
||||
return 1; // Already got one
|
||||
|
||||
@@ -79,6 +77,13 @@ sp_rcontext::find_handler(uint sql_errno,
|
||||
while (i--)
|
||||
{
|
||||
sp_cond_type_t *cond= m_handler[i].cond;
|
||||
int j= m_ihsp;
|
||||
|
||||
while (j--)
|
||||
if (m_in_handler[j] == m_handler[i].handler)
|
||||
break;
|
||||
if (j >= 0)
|
||||
continue; // Already executing this handler
|
||||
|
||||
switch (cond->type)
|
||||
{
|
||||
|
||||
@@ -58,7 +58,6 @@ class sp_rcontext : public Sql_alloc
|
||||
|
||||
public:
|
||||
|
||||
bool in_handler;
|
||||
/*
|
||||
Arena used to (re) allocate items on . E.g. reallocate INOUT/OUT
|
||||
SP parameters when they don't fit into prealloced items. This
|
||||
@@ -169,6 +168,18 @@ class sp_rcontext : public Sql_alloc
|
||||
return m_hstack[--m_hsp];
|
||||
}
|
||||
|
||||
inline void
|
||||
enter_handler(int hid)
|
||||
{
|
||||
m_in_handler[m_ihsp++]= hid;
|
||||
}
|
||||
|
||||
inline void
|
||||
exit_handler()
|
||||
{
|
||||
m_ihsp-= 1;
|
||||
}
|
||||
|
||||
// Save variables starting at fp and up
|
||||
void
|
||||
save_variables(uint fp);
|
||||
@@ -203,12 +214,14 @@ private:
|
||||
|
||||
Item *m_result; // For FUNCTIONs
|
||||
|
||||
sp_handler_t *m_handler;
|
||||
uint m_hcount;
|
||||
uint *m_hstack;
|
||||
uint m_hsp;
|
||||
int m_hfound; // Set by find_handler; -1 if not found
|
||||
List<Item> m_saved; // Saved variables
|
||||
sp_handler_t *m_handler; // Visible handlers
|
||||
uint m_hcount; // Stack pointer for m_handler
|
||||
uint *m_hstack; // Return stack for continue handlers
|
||||
uint m_hsp; // Stack pointer for m_hstack
|
||||
uint *m_in_handler; // Active handler, for recursion check
|
||||
uint m_ihsp; // Stack pointer for m_in_handler
|
||||
int m_hfound; // Set by find_handler; -1 if not found
|
||||
List<Item> m_saved; // Saved variables during handler exec.
|
||||
|
||||
sp_cursor **m_cstack;
|
||||
uint m_ccount;
|
||||
|
||||
Reference in New Issue
Block a user