mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03: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:
@ -299,12 +299,6 @@ ERROR 42S22: Unknown column 'valname' in 'order clause'
|
|||||||
drop procedure bug1965|
|
drop procedure bug1965|
|
||||||
select 1 into a|
|
select 1 into a|
|
||||||
ERROR 42000: Undeclared variable: 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()
|
create function bug1654()
|
||||||
returns int
|
returns int
|
||||||
return (select sum(t.data) from test.t2 t)|
|
return (select sum(t.data) from test.t2 t)|
|
||||||
|
@ -1674,6 +1674,36 @@ create table t2 as select * from t;
|
|||||||
end|
|
end|
|
||||||
call bug4904()|
|
call bug4904()|
|
||||||
drop procedure 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|
|
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)
|
||||||
|
@ -400,16 +400,6 @@ drop procedure bug1965|
|
|||||||
--error 1326
|
--error 1326
|
||||||
select 1 into a|
|
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
|
# BUG#1654
|
||||||
#
|
#
|
||||||
|
@ -1808,6 +1808,42 @@ call bug4904()|
|
|||||||
|
|
||||||
drop procedure 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
|
# Some "real" examples
|
||||||
|
@ -1180,13 +1180,26 @@ sp_instr_set::execute(THD *thd, uint *nextp)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("sp_instr_set::execute");
|
DBUG_ENTER("sp_instr_set::execute");
|
||||||
DBUG_PRINT("info", ("offset: %u", m_offset));
|
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);
|
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;
|
*nextp = m_ip+1;
|
||||||
DBUG_RETURN(0);
|
if (thd->lock || thd->open_tables || thd->derived_tables)
|
||||||
|
close_thread_tables(thd);
|
||||||
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1265,15 +1278,28 @@ sp_instr_jump_if::execute(THD *thd, uint *nextp)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("sp_instr_jump_if::execute");
|
DBUG_ENTER("sp_instr_jump_if::execute");
|
||||||
DBUG_PRINT("info", ("destination: %u", m_dest));
|
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);
|
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
|
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
|
void
|
||||||
@ -1309,15 +1335,28 @@ sp_instr_jump_if_not::execute(THD *thd, uint *nextp)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("sp_instr_jump_if_not::execute");
|
DBUG_ENTER("sp_instr_jump_if_not::execute");
|
||||||
DBUG_PRINT("info", ("destination: %u", m_dest));
|
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);
|
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
|
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
|
void
|
||||||
@ -1352,13 +1391,24 @@ int
|
|||||||
sp_instr_freturn::execute(THD *thd, uint *nextp)
|
sp_instr_freturn::execute(THD *thd, uint *nextp)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("sp_instr_freturn::execute");
|
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);
|
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;
|
*nextp= UINT_MAX;
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -351,8 +351,10 @@ class sp_instr_set : public sp_instr
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TABLE_LIST *tables;
|
||||||
|
|
||||||
sp_instr_set(uint ip, uint offset, Item *val, enum enum_field_types type)
|
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()
|
virtual ~sp_instr_set()
|
||||||
@ -421,12 +423,14 @@ class sp_instr_jump_if : public sp_instr_jump
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TABLE_LIST *tables;
|
||||||
|
|
||||||
sp_instr_jump_if(uint ip, Item *i)
|
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_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()
|
virtual ~sp_instr_jump_if()
|
||||||
@ -457,12 +461,14 @@ class sp_instr_jump_if_not : public sp_instr_jump
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TABLE_LIST *tables;
|
||||||
|
|
||||||
sp_instr_jump_if_not(uint ip, Item *i)
|
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_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()
|
virtual ~sp_instr_jump_if_not()
|
||||||
@ -493,8 +499,10 @@ class sp_instr_freturn : public sp_instr
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
TABLE_LIST *tables;
|
||||||
|
|
||||||
sp_instr_freturn(uint ip, Item *val, enum enum_field_types type)
|
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()
|
virtual ~sp_instr_freturn()
|
||||||
|
@ -1434,7 +1434,8 @@ sp_opt_inout:
|
|||||||
|
|
||||||
sp_proc_stmts:
|
sp_proc_stmts:
|
||||||
/* Empty */ {}
|
/* Empty */ {}
|
||||||
| sp_proc_stmts sp_proc_stmt ';'
|
| sp_proc_stmts { Lex->query_tables= 0; } sp_proc_stmt ';'
|
||||||
|
|
||||||
;
|
;
|
||||||
|
|
||||||
sp_decls:
|
sp_decls:
|
||||||
@ -1483,6 +1484,8 @@ sp_decl:
|
|||||||
sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(),
|
sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(),
|
||||||
i, it, type);
|
i, it, type);
|
||||||
|
|
||||||
|
in->tables= lex->query_tables;
|
||||||
|
lex->query_tables= 0;
|
||||||
lex->sphead->add_instr(in);
|
lex->sphead->add_instr(in);
|
||||||
lex->spcont->set_isset(i, TRUE);
|
lex->spcont->set_isset(i, TRUE);
|
||||||
lex->spcont->set_default(i, it);
|
lex->spcont->set_default(i, it);
|
||||||
@ -1799,6 +1802,8 @@ sp_proc_stmt:
|
|||||||
dummy.str= (char *)"";
|
dummy.str= (char *)"";
|
||||||
dummy.length= 0;
|
dummy.length= 0;
|
||||||
lex->spcont->push_pvar(&dummy, MYSQL_TYPE_STRING, sp_param_in);
|
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->add_instr(i);
|
||||||
lex->sphead->m_simple_case= TRUE;
|
lex->sphead->m_simple_case= TRUE;
|
||||||
}
|
}
|
||||||
@ -2047,11 +2052,14 @@ sp_fetch_list:
|
|||||||
sp_if:
|
sp_if:
|
||||||
expr THEN_SYM
|
expr THEN_SYM
|
||||||
{
|
{
|
||||||
sp_head *sp= Lex->sphead;
|
LEX *lex= Lex;
|
||||||
sp_pcontext *ctx= Lex->spcont;
|
sp_head *sp= lex->sphead;
|
||||||
|
sp_pcontext *ctx= lex->spcont;
|
||||||
uint ip= sp->instructions();
|
uint ip= sp->instructions();
|
||||||
sp_instr_jump_if_not *i = new sp_instr_jump_if_not(ip, $1);
|
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->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
@ -2105,6 +2113,8 @@ sp_case:
|
|||||||
lex->variables_used= 1;
|
lex->variables_used= 1;
|
||||||
}
|
}
|
||||||
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
sp->push_backpatch(i, ctx->push_label((char *)"", 0));
|
||||||
|
i->tables= lex->query_tables;
|
||||||
|
lex->query_tables= 0;
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
sp_proc_stmts
|
sp_proc_stmts
|
||||||
@ -2240,6 +2250,8 @@ sp_unlabeled_control:
|
|||||||
|
|
||||||
/* Jumping forward */
|
/* Jumping forward */
|
||||||
sp->push_backpatch(i, lex->spcont->last_label());
|
sp->push_backpatch(i, lex->spcont->last_label());
|
||||||
|
i->tables= lex->query_tables;
|
||||||
|
lex->query_tables= 0;
|
||||||
sp->add_instr(i);
|
sp->add_instr(i);
|
||||||
}
|
}
|
||||||
sp_proc_stmts END WHILE_SYM
|
sp_proc_stmts END WHILE_SYM
|
||||||
@ -2258,6 +2270,8 @@ sp_unlabeled_control:
|
|||||||
sp_label_t *lab= lex->spcont->last_label(); /* Jumping back */
|
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);
|
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);
|
lex->sphead->add_instr(i);
|
||||||
}
|
}
|
||||||
;
|
;
|
||||||
@ -6776,11 +6790,6 @@ option_value:
|
|||||||
sp_instr_set *i;
|
sp_instr_set *i;
|
||||||
Item *it;
|
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);
|
spv= lex->spcont->find_pvar(&$1.base_name);
|
||||||
|
|
||||||
if ($3)
|
if ($3)
|
||||||
@ -6791,6 +6800,8 @@ option_value:
|
|||||||
it= new Item_null();
|
it= new Item_null();
|
||||||
i= new sp_instr_set(lex->sphead->instructions(),
|
i= new sp_instr_set(lex->sphead->instructions(),
|
||||||
spv->offset, it, spv->type);
|
spv->offset, it, spv->type);
|
||||||
|
i->tables= lex->query_tables;
|
||||||
|
lex->query_tables= 0;
|
||||||
lex->sphead->add_instr(i);
|
lex->sphead->add_instr(i);
|
||||||
spv->isset= TRUE;
|
spv->isset= TRUE;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user