summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/sp-error.result6
-rw-r--r--mysql-test/r/sp.result30
-rw-r--r--mysql-test/t/sp-error.test10
-rw-r--r--mysql-test/t/sp.test36
-rw-r--r--sql/sp_head.cc90
-rw-r--r--sql/sp_head.h20
-rw-r--r--sql/sql_yacc.yy27
7 files changed, 169 insertions, 50 deletions
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 14e2090579b..f8d523484d8 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -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)|
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index 9b2e16e3fe9..5fb641a7db3 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -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)
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index 2c2dd10c676..71b2b91ccb1 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -401,16 +401,6 @@ drop procedure bug1965|
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
#
--error 1313
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 265223fd930..3b91725b6a3 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -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
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index bc6251903c2..5a58c32d2da 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -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
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 39a74366ccb..9c29297180d 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -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()
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index ec9c921f5cb..a01abd9141b 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -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;
}