Commit ac06195c authored by unknown's avatar unknown

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.
parent 94e995d7
......@@ -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;
}
......
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