diff options
-rw-r--r-- | mysql-test/r/sp-error.result | 6 | ||||
-rw-r--r-- | mysql-test/r/sp.result | 30 | ||||
-rw-r--r-- | mysql-test/t/sp-error.test | 10 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 36 | ||||
-rw-r--r-- | sql/sp_head.cc | 90 | ||||
-rw-r--r-- | sql/sp_head.h | 20 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 27 |
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; } |