mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 12:02:42 +01:00
Fixed BUG#3157: Crash if stored procedure contains IF EXISTS,
and BUG#336: Subselects with tables does not work as values for local SP variables (which was closed before with a temp. fix, but not actually fixed). mysql-test/r/sp-error.result: Moved test case for BUG#336 to sp.test, as it's not generating an error any longer. mysql-test/r/sp.result: Move test case for BUG#336 from sp-error.test and added new test case for BUG#3157. mysql-test/t/sp-error.test: Moved test case for BUG#336 to sp.test, as it's not generating an error any longer. mysql-test/t/sp.test: Move test case for BUG#336 from sp-error.test and added new test case for BUG#3157. sql/sp_head.cc: Open and close tables in set, jump-if[-not] and freturn instructions if the value expression is a subselect. sql/sp_head.h: Store tables in set, jump-if[-not] and freturn instructions if the value expression is a subselect. sql/sql_yacc.yy: Store tables in set, jump-if[-not] and freturn instructions if the value expression is a subselect.
This commit is contained in:
parent
94e995d70b
commit
ac06195caa
7 changed files with 169 additions and 50 deletions
|
@ -299,12 +299,6 @@ ERROR 42S22: Unknown column 'valname' in 'order clause'
|
|||
drop procedure bug1965|
|
||||
select 1 into a|
|
||||
ERROR 42000: Undeclared variable: a
|
||||
create procedure bug336(id char(16))
|
||||
begin
|
||||
declare x int;
|
||||
set x = (select sum(t.data) from test.t2 t);
|
||||
end|
|
||||
ERROR 0A000: Subselect value not supported
|
||||
create function bug1654()
|
||||
returns int
|
||||
return (select sum(t.data) from test.t2 t)|
|
||||
|
|
|
@ -1674,6 +1674,36 @@ create table t2 as select * from t;
|
|||
end|
|
||||
call bug4904()|
|
||||
drop procedure bug4904|
|
||||
create procedure bug336(out y int)
|
||||
begin
|
||||
declare x int;
|
||||
set x = (select sum(t.data) from test.t1 t);
|
||||
set y = x;
|
||||
end|
|
||||
insert into t1 values ("a", 2), ("b", 3)|
|
||||
call bug336(@y)|
|
||||
select @y|
|
||||
@y
|
||||
5
|
||||
delete from t1|
|
||||
drop procedure bug336|
|
||||
create procedure bug3157()
|
||||
begin
|
||||
if exists(select * from t1) then
|
||||
set @n= @n + 1;
|
||||
end if;
|
||||
if (select count(*) from t1) then
|
||||
set @n= @n + 1;
|
||||
end if;
|
||||
end|
|
||||
set @n = 0|
|
||||
insert into t1 values ("a", 1)|
|
||||
call bug3157()|
|
||||
select @n|
|
||||
@n
|
||||
2
|
||||
delete from t1|
|
||||
drop procedure bug3157|
|
||||
drop table if exists fac|
|
||||
create table fac (n int unsigned not null primary key, f bigint unsigned)|
|
||||
create procedure ifac(n int unsigned)
|
||||
|
|
|
@ -400,16 +400,6 @@ drop procedure bug1965|
|
|||
--error 1326
|
||||
select 1 into a|
|
||||
|
||||
#
|
||||
# BUG#336
|
||||
#
|
||||
--error 1334
|
||||
create procedure bug336(id char(16))
|
||||
begin
|
||||
declare x int;
|
||||
set x = (select sum(t.data) from test.t2 t);
|
||||
end|
|
||||
|
||||
#
|
||||
# BUG#1654
|
||||
#
|
||||
|
|
|
@ -1808,6 +1808,42 @@ call bug4904()|
|
|||
|
||||
drop procedure bug4904|
|
||||
|
||||
#
|
||||
# BUG#336
|
||||
#
|
||||
create procedure bug336(out y int)
|
||||
begin
|
||||
declare x int;
|
||||
set x = (select sum(t.data) from test.t1 t);
|
||||
set y = x;
|
||||
end|
|
||||
|
||||
insert into t1 values ("a", 2), ("b", 3)|
|
||||
call bug336(@y)|
|
||||
select @y|
|
||||
delete from t1|
|
||||
drop procedure bug336|
|
||||
|
||||
#
|
||||
# BUG#3157
|
||||
#
|
||||
create procedure bug3157()
|
||||
begin
|
||||
if exists(select * from t1) then
|
||||
set @n= @n + 1;
|
||||
end if;
|
||||
if (select count(*) from t1) then
|
||||
set @n= @n + 1;
|
||||
end if;
|
||||
end|
|
||||
|
||||
set @n = 0|
|
||||
insert into t1 values ("a", 1)|
|
||||
call bug3157()|
|
||||
select @n|
|
||||
delete from t1|
|
||||
drop procedure bug3157|
|
||||
|
||||
|
||||
#
|
||||
# Some "real" examples
|
||||
|
|
|
@ -1180,13 +1180,26 @@ sp_instr_set::execute(THD *thd, uint *nextp)
|
|||
{
|
||||
DBUG_ENTER("sp_instr_set::execute");
|
||||
DBUG_PRINT("info", ("offset: %u", m_offset));
|
||||
Item *it= sp_eval_func_item(thd, m_value, m_type);
|
||||
Item *it;
|
||||
int res;
|
||||
|
||||
if (! it)
|
||||
if (tables &&
|
||||
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
|
||||
(res= open_and_lock_tables(thd, tables))))
|
||||
DBUG_RETURN(-1);
|
||||
thd->spcont->set_item(m_offset, it);
|
||||
|
||||
it= sp_eval_func_item(thd, m_value, m_type);
|
||||
if (! it)
|
||||
res= -1;
|
||||
else
|
||||
{
|
||||
res= 0;
|
||||
thd->spcont->set_item(m_offset, it);
|
||||
}
|
||||
*nextp = m_ip+1;
|
||||
DBUG_RETURN(0);
|
||||
if (thd->lock || thd->open_tables || thd->derived_tables)
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1265,15 +1278,28 @@ sp_instr_jump_if::execute(THD *thd, uint *nextp)
|
|||
{
|
||||
DBUG_ENTER("sp_instr_jump_if::execute");
|
||||
DBUG_PRINT("info", ("destination: %u", m_dest));
|
||||
Item *it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
|
||||
Item *it;
|
||||
int res;
|
||||
|
||||
if (!it)
|
||||
if (tables &&
|
||||
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
|
||||
(res= open_and_lock_tables(thd, tables))))
|
||||
DBUG_RETURN(-1);
|
||||
if (it->val_int())
|
||||
*nextp = m_dest;
|
||||
|
||||
it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
|
||||
if (!it)
|
||||
res= -1;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
DBUG_RETURN(0);
|
||||
{
|
||||
res= 0;
|
||||
if (it->val_int())
|
||||
*nextp = m_dest;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
}
|
||||
if (thd->lock || thd->open_tables || thd->derived_tables)
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1309,15 +1335,28 @@ sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
|
|||
{
|
||||
DBUG_ENTER("sp_instr_jump_if_not::execute");
|
||||
DBUG_PRINT("info", ("destination: %u", m_dest));
|
||||
Item *it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
|
||||
Item *it;
|
||||
int res;
|
||||
|
||||
if (! it)
|
||||
if (tables &&
|
||||
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
|
||||
(res= open_and_lock_tables(thd, tables))))
|
||||
DBUG_RETURN(-1);
|
||||
if (! it->val_int())
|
||||
*nextp = m_dest;
|
||||
|
||||
it= sp_eval_func_item(thd, m_expr, MYSQL_TYPE_TINY);
|
||||
if (! it)
|
||||
res= -1;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
DBUG_RETURN(0);
|
||||
{
|
||||
res= 0;
|
||||
if (! it->val_int())
|
||||
*nextp = m_dest;
|
||||
else
|
||||
*nextp = m_ip+1;
|
||||
}
|
||||
if (thd->lock || thd->open_tables || thd->derived_tables)
|
||||
close_thread_tables(thd);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1352,13 +1391,24 @@ int
|
|||
sp_instr_freturn::execute(THD *thd, uint *nextp)
|
||||
{
|
||||
DBUG_ENTER("sp_instr_freturn::execute");
|
||||
Item *it= sp_eval_func_item(thd, m_value, m_type);
|
||||
Item *it;
|
||||
int res;
|
||||
|
||||
if (! it)
|
||||
if (tables &&
|
||||
((res= check_table_access(thd, SELECT_ACL, tables, 0)) ||
|
||||
(res= open_and_lock_tables(thd, tables))))
|
||||
DBUG_RETURN(-1);
|
||||
thd->spcont->set_result(it);
|
||||
|
||||
it= sp_eval_func_item(thd, m_value, m_type);
|
||||
if (! it)
|
||||
res= -1;
|
||||
else
|
||||
{
|
||||
res= 0;
|
||||
thd->spcont->set_result(it);
|
||||
}
|
||||
*nextp= UINT_MAX;
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(res);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -351,8 +351,10 @@ class sp_instr_set : public sp_instr
|
|||
|
||||
public:
|
||||
|
||||
TABLE_LIST *tables;
|
||||
|
||||
sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
|
||||
: sp_instr(ip), m_offset(offset), m_value(val), m_type(type)
|
||||
: sp_instr(ip), tables(NULL), m_offset(offset), m_value(val), m_type(type)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_set()
|
||||
|
@ -421,12 +423,14 @@ class sp_instr_jump_if : public sp_instr_jump
|
|||
|
||||
public:
|
||||
|
||||
TABLE_LIST *tables;
|
||||
|
||||
sp_instr_jump_if(uint ip, Item *i)
|
||||
: sp_instr_jump(ip), m_expr(i)
|
||||
: sp_instr_jump(ip), tables(NULL), m_expr(i)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if(uint ip, Item *i, uint dest)
|
||||
: sp_instr_jump(ip, dest), m_expr(i)
|
||||
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if()
|
||||
|
@ -457,12 +461,14 @@ class sp_instr_jump_if_not : public sp_instr_jump
|
|||
|
||||
public:
|
||||
|
||||
TABLE_LIST *tables;
|
||||
|
||||
sp_instr_jump_if_not(uint ip, Item *i)
|
||||
: sp_instr_jump(ip), m_expr(i)
|
||||
: sp_instr_jump(ip), tables(NULL), m_expr(i)
|
||||
{}
|
||||
|
||||
sp_instr_jump_if_not(uint ip, Item *i, uint dest)
|
||||
: sp_instr_jump(ip, dest), m_expr(i)
|
||||
: sp_instr_jump(ip, dest), tables(NULL), m_expr(i)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_jump_if_not()
|
||||
|
@ -493,8 +499,10 @@ class sp_instr_freturn : public sp_instr
|
|||
|
||||
public:
|
||||
|
||||
TABLE_LIST *tables;
|
||||
|
||||
sp_instr_freturn(uint ip, Item *val, enum enum_field_types type)
|
||||
: sp_instr(ip), m_value(val), m_type(type)
|
||||
: sp_instr(ip), tables(NULL), m_value(val), m_type(type)
|
||||
{}
|
||||
|
||||
virtual ~sp_instr_freturn()
|
||||
|
|
|
@ -1434,7 +1434,8 @@ sp_opt_inout:
|
|||
|
||||
sp_proc_stmts:
|
||||
/* Empty */ {}
|
||||
| sp_proc_stmts sp_proc_stmt ';'
|
||||
| sp_proc_stmts { Lex->query_tables= 0; } sp_proc_stmt ';'
|
||||
|
||||
;
|
||||
|
||||
sp_decls:
|
||||
|
@ -1483,6 +1484,8 @@ sp_decl:
|
|||
sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(),
|
||||
i, it, type);
|
||||
|
||||
in->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
lex->sphead->add_instr(in);
|
||||
lex->spcont->set_isset(i, TRUE);
|
||||
lex->spcont->set_default(i, it);
|
||||
|
@ -1799,6 +1802,8 @@ sp_proc_stmt:
|
|||
dummy.str= (char *)"";
|
||||
dummy.length= 0;
|
||||
lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
lex->sphead->add_instr(i);
|
||||
lex->sphead->m_simple_case= TRUE;
|
||||
}
|
||||
|
@ -2047,11 +2052,14 @@ sp_fetch_list:
|
|||
sp_if:
|
||||
expr THEN_SYM
|
||||
{
|
||||
sp_head *sp= Lex->sphead;
|
||||
sp_pcontext *ctx= Lex->spcont;
|
||||
LEX *lex= Lex;
|
||||
sp_head *sp= lex->sphead;
|
||||
sp_pcontext *ctx= lex->spcont;
|
||||
uint ip= sp->instructions();
|
||||
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1);
|
||||
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||
sp->add_instr(i);
|
||||
}
|
||||
|
@ -2105,6 +2113,8 @@ sp_case:
|
|||
lex->variables_used= 1;
|
||||
}
|
||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
sp->add_instr(i);
|
||||
}
|
||||
sp_proc_stmts
|
||||
|
@ -2240,6 +2250,8 @@ sp_unlabeled_control:
|
|||
|
||||
/* Jumping forward */
|
||||
sp->push_backpatch(i, lex->spcont->last_label());
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
sp->add_instr(i);
|
||||
}
|
||||
sp_proc_stmts END WHILE_SYM
|
||||
|
@ -2258,6 +2270,8 @@ sp_unlabeled_control:
|
|||
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
|
||||
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $4, lab->ip);
|
||||
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
lex->sphead->add_instr(i);
|
||||
}
|
||||
;
|
||||
|
@ -6776,11 +6790,6 @@ option_value:
|
|||
sp_instr_set *i;
|
||||
Item *it;
|
||||
|
||||
if ($3 && $3->type() == Item::SUBSELECT_ITEM)
|
||||
{ /* QQ For now, just disallow subselects as values */
|
||||
send_error(lex->thd, ER_SP_SUBSELECT_NYI);
|
||||
YYABORT;
|
||||
}
|
||||
spv= lex->spcont->find_pvar(&$1.base_name);
|
||||
|
||||
if ($3)
|
||||
|
@ -6791,6 +6800,8 @@ option_value:
|
|||
it= new Item_null();
|
||||
i= new sp_instr_set(lex->sphead->instructions(),
|
||||
spv->offset, it, spv->type);
|
||||
i->tables= lex->query_tables;
|
||||
lex->query_tables= 0;
|
||||
lex->sphead->add_instr(i);
|
||||
spv->isset= TRUE;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue