mirror of
https://github.com/MariaDB/server.git
synced 2025-12-24 11:21:21 +03:00
Fixed BUG#822: Copying and clearing some things in thd/lex when
executing sub-statements (selects) prevents crashes intermittent crashes. Also fixed bug in sql_yacc.yy (generated a hpop instruction when not needed). mysql-test/r/sp.result: Test-case for BUG#822. mysql-test/t/sp.test: Test-case for BUG#822. sql/sp_head.cc: Fixed BUG#822; needed to copy and clear some stuff when calling sub-statements. sql/sql_yacc.yy: Only generate hpop instruction when we actually have handlers.
This commit is contained in:
@@ -500,6 +500,23 @@ id data
|
||||
hndlr3 13
|
||||
delete from t1;
|
||||
drop procedure hndlr3;
|
||||
create procedure bug822(a_id char(16), a_data int)
|
||||
begin
|
||||
declare n int;
|
||||
select count(*) into n from t1 where id = a_id and data = a_data;
|
||||
if n = 0 then
|
||||
insert into t1 (id, data) values (a_id, a_data);
|
||||
end if;
|
||||
end;
|
||||
call bug822('foo', 42);
|
||||
call bug822('foo', 42);
|
||||
call bug822('bar', 666);
|
||||
select * from t1;
|
||||
id data
|
||||
foo 42
|
||||
bar 666
|
||||
delete from t1;
|
||||
drop procedure bug822;
|
||||
drop table if exists fac;
|
||||
create table fac (n int unsigned not null primary key, f bigint unsigned);
|
||||
create procedure ifac(n int unsigned)
|
||||
|
||||
@@ -589,6 +589,23 @@ delete from t1|
|
||||
drop procedure hndlr3|
|
||||
|
||||
|
||||
create procedure bug822(a_id char(16), a_data int)
|
||||
begin
|
||||
declare n int;
|
||||
select count(*) into n from t1 where id = a_id and data = a_data;
|
||||
if n = 0 then
|
||||
insert into t1 (id, data) values (a_id, a_data);
|
||||
end if;
|
||||
end|
|
||||
|
||||
call bug822('foo', 42)|
|
||||
call bug822('foo', 42)|
|
||||
call bug822('bar', 666)|
|
||||
select * from t1|
|
||||
delete from t1|
|
||||
drop procedure bug822|
|
||||
|
||||
|
||||
#
|
||||
# Some "real" examples
|
||||
#
|
||||
|
||||
@@ -481,6 +481,13 @@ sp_head::restore_lex(THD *thd)
|
||||
// Update some state in the old one first
|
||||
oldlex->ptr= sublex->ptr;
|
||||
oldlex->next_state= sublex->next_state;
|
||||
// Save WHERE clause pointers to avoid damaging by optimisation
|
||||
for (SELECT_LEX *sl= sublex->all_selects_list ;
|
||||
sl ;
|
||||
sl= sl->next_select_in_list())
|
||||
{
|
||||
sl->prep_where= sl->where;
|
||||
}
|
||||
|
||||
// Collect some data from the sub statement lex.
|
||||
sp_merge_funs(oldlex, sublex);
|
||||
@@ -578,14 +585,31 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
|
||||
DBUG_ENTER("sp_instr_stmt::execute");
|
||||
DBUG_PRINT("info", ("command: %d", m_lex->sql_command));
|
||||
LEX *olex; // The other lex
|
||||
Item *freelist;
|
||||
int res;
|
||||
|
||||
olex= thd->lex; // Save the other lex
|
||||
thd->lex= m_lex; // Use my own lex
|
||||
thd->lex->thd = thd; // QQ Not reentrant!
|
||||
thd->lex->unit.thd= thd; // QQ Not reentrant
|
||||
freelist= thd->free_list;
|
||||
thd->free_list= NULL;
|
||||
thd->query_id= query_id++;
|
||||
|
||||
// Copy WHERE clause pointers to avoid damaging by optimisation
|
||||
// Also clear ref_pointer_arrays.
|
||||
for (SELECT_LEX *sl= m_lex->all_selects_list ;
|
||||
sl ;
|
||||
sl= sl->next_select_in_list())
|
||||
{
|
||||
sl->ref_pointer_array= 0;
|
||||
if (sl->prep_where)
|
||||
sl->where= sl->prep_where->copy_andor_structure(thd);
|
||||
DBUG_ASSERT(sl->join == 0);
|
||||
}
|
||||
|
||||
res= mysql_execute_command(thd);
|
||||
|
||||
if (thd->lock || thd->open_tables || thd->derived_tables)
|
||||
{
|
||||
thd->proc_info="closing tables";
|
||||
@@ -593,6 +617,7 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
|
||||
}
|
||||
|
||||
thd->lex= olex; // Restore the other lex
|
||||
thd->free_list= freelist;
|
||||
|
||||
*nextp = m_ip+1;
|
||||
DBUG_RETURN(res);
|
||||
|
||||
@@ -1644,13 +1644,15 @@ sp_unlabeled_control:
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
sp_instr_hpop *i;
|
||||
|
||||
sp->backpatch(ctx->pop_label());
|
||||
ctx->pop_pvar($3.vars);
|
||||
ctx->pop_cond($3.conds);
|
||||
i= new sp_instr_hpop(sp->instructions(), $3.hndlrs);
|
||||
sp->add_instr(i);
|
||||
if ($3.hndlrs)
|
||||
{
|
||||
sp_instr_hpop *i= new sp_instr_hpop(sp->instructions(),$3.hndlrs);
|
||||
sp->add_instr(i);
|
||||
}
|
||||
}
|
||||
| LOOP_SYM
|
||||
sp_proc_stmts END LOOP_SYM
|
||||
|
||||
Reference in New Issue
Block a user