diff options
author | unknown <pem@mysql.com> | 2005-09-13 12:50:21 +0200 |
---|---|---|
committer | unknown <pem@mysql.com> | 2005-09-13 12:50:21 +0200 |
commit | 902932a1e86ea728a8cc62d2ab5b1e0544d797ae (patch) | |
tree | e9be1a621c9e211cb4daf7e3f100a113c29249fd | |
parent | b50eb4cd42d2d5073afb2af5af8b19c825a9cca1 (diff) | |
download | mariadb-git-902932a1e86ea728a8cc62d2ab5b1e0544d797ae.tar.gz |
Fixed BUG#13133: Local variables in stored procedures are not initialized correctly.
Have to init. all local variables in their frames, not just once at the beginning
of invocation.
mysql-test/r/sp.result:
New test case for BUG#13133.
mysql-test/t/sp.test:
New test case for BUG#13133.
sql/sp_head.cc:
Just init. local variable slots in the fram to NULL. (Real init. will be done
in each block.)
sql/sp_pcontext.cc:
Removed isset flag, since it's not used.
sql/sp_pcontext.h:
Removed isset flag, since it's not used.
sql/sql_yacc.yy:
Initialize local variables in the block to null, or the default value, given.
(Untabifed block too.)
-rw-r--r-- | mysql-test/r/sp.result | 39 | ||||
-rw-r--r-- | mysql-test/t/sp.test | 45 | ||||
-rw-r--r-- | sql/sp_head.cc | 35 | ||||
-rw-r--r-- | sql/sp_pcontext.cc | 1 | ||||
-rw-r--r-- | sql/sp_pcontext.h | 10 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 67 |
6 files changed, 124 insertions, 73 deletions
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cb696f93f79..4454f818efb 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3225,4 +3225,43 @@ select @var| @var abcdabcd drop procedure bug12849_2| +drop procedure if exists bug131333| +drop function if exists bug131333| +create procedure bug131333() +begin +begin +declare a int; +select a; +set a = 1; +select a; +end; +begin +declare b int; +select b; +end; +end| +create function bug131333() +returns int +begin +begin +declare a int; +set a = 1; +end; +begin +declare b int; +return b; +end; +end| +call bug131333()| +a +NULL +a +1 +b +NULL +select bug131333()| +bug131333() +NULL +drop procedure bug131333| +drop function bug131333| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 3d315fa12df..2b705329961 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4064,6 +4064,51 @@ select @var| drop procedure bug12849_2| # +# BUG#13133: Local variables in stored procedures are not initialized correctly. +# +--disable_warnings +drop procedure if exists bug131333| +drop function if exists bug131333| +--enable_warnings +create procedure bug131333() +begin + begin + declare a int; + + select a; + set a = 1; + select a; + end; + begin + declare b int; + + select b; + end; +end| + +create function bug131333() + returns int +begin + begin + declare a int; + + set a = 1; + end; + begin + declare b int; + + return b; + end; +end| + +call bug131333()| +select bug131333()| + +drop procedure bug131333| +drop function bug131333| + + +# # BUG#NNNN: New bug synopsis # #--disable_warnings diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0444499de48..a11907373cd 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1078,7 +1078,6 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) sp_rcontext *octx = thd->spcont; sp_rcontext *nctx = NULL; uint i; - Item_null *nit; int ret= -1; // Assume error if (argcount != params) @@ -1109,22 +1108,15 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp) nctx->push_item(it); } + /* The rest of the frame are local variables which are all IN. - Default all variables to null (those with default clauses will - be set by an set instruction). + Push NULLs to get the right size (and make the reuse mechanism work) - + the will be initialized by set instructions in each frame. */ - - nit= NULL; // Re-use this, and only create if needed for (; i < csize ; i++) - { - if (! nit) - { - if (!(nit= new Item_null())) - DBUG_RETURN(-1); - } - nctx->push_item(nit); - } + nctx->push_item(NULL); + thd->spcont= nctx; binlog_save_options= thd->options; @@ -1321,23 +1313,14 @@ int sp_head::execute_procedure(THD *thd, List<Item> *args) close_thread_tables(thd, 0, 0); DBUG_PRINT("info",(" %.*s: eval args done", m_name.length, m_name.str)); + /* The rest of the frame are local variables which are all IN. - Default all variables to null (those with default clauses will - be set by an set instruction). + Push NULLs to get the right size (and make the reuse mechanism work) - + the will be initialized by set instructions in each frame. */ for (; i < csize ; i++) - { - if (! nit) - { - if (!(nit= new Item_null())) - { - ret= -1; - break; - } - } - nctx->push_item(nit); - } + nctx->push_item(NULL); } thd->spcont= nctx; diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index 0de7fe212c0..f873b676925 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -184,7 +184,6 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, p->type= type; p->mode= mode; p->offset= current_pvars(); - p->isset= (mode == sp_param_out ? FALSE : TRUE); p->dflt= NULL; insert_dynamic(&m_pvar, (gptr)&p); } diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index 196f9ccb24b..bd2259cb6fb 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -35,7 +35,6 @@ typedef struct sp_pvar enum enum_field_types type; sp_param_mode_t mode; uint offset; // Offset in current frame - my_bool isset; Item *dflt; } sp_pvar_t; @@ -148,15 +147,6 @@ class sp_pcontext : public Sql_alloc } inline void - set_isset(uint i, my_bool val) - { - sp_pvar_t *p= find_pvar(i); - - if (p) - p->isset= val; - } - - inline void set_default(uint i, Item *it) { sp_pvar_t *p= find_pvar(i); diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 520b6190410..104f9ca8445 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1657,42 +1657,41 @@ sp_decls: ; sp_decl: - DECLARE_SYM sp_decl_idents type + DECLARE_SYM sp_decl_idents type { Lex->sphead->reset_lex(YYTHD); } sp_opt_default - { - LEX *lex= Lex; - sp_pcontext *ctx= lex->spcont; - uint max= ctx->context_pvars(); - enum enum_field_types type= (enum enum_field_types)$3; - Item *it= $5; + { + LEX *lex= Lex; + sp_pcontext *ctx= lex->spcont; + uint max= ctx->context_pvars(); + enum enum_field_types type= (enum enum_field_types)$3; + Item *it= $5; + bool has_default= (it != NULL); - for (uint i = max-$2 ; i < max ; i++) - { - ctx->set_type(i, type); - if (! it) - ctx->set_isset(i, FALSE); - else - { - sp_instr_set *in= new sp_instr_set(lex->sphead->instructions(), - ctx, - ctx->pvar_context2index(i), - it, type, lex, - (i == max - 1)); - - /* - The last instruction is assigned to be responsible for - freeing LEX. - */ - lex->sphead->add_instr(in); - ctx->set_isset(i, TRUE); - ctx->set_default(i, it); - } - } + for (uint i = max-$2 ; i < max ; i++) + { + sp_instr_set *in; + + ctx->set_type(i, type); + if (! has_default) + it= new Item_null(); /* QQ Set to the type with null_value? */ + in = new sp_instr_set(lex->sphead->instructions(), + ctx, + ctx->pvar_context2index(i), + it, type, lex, + (i == max - 1)); + + /* + The last instruction is assigned to be responsible for + freeing LEX. + */ + lex->sphead->add_instr(in); + ctx->set_default(i, it); + } lex->sphead->restore_lex(YYTHD); - $$.vars= $2; - $$.conds= $$.hndlrs= $$.curs= 0; - } + $$.vars= $2; + $$.conds= $$.hndlrs= $$.curs= 0; + } | DECLARE_SYM ident CONDITION_SYM FOR_SYM sp_cond { LEX *lex= Lex; @@ -2268,7 +2267,6 @@ sp_fetch_list: sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction(); i->add_to_varlist(spv); - spv->isset= TRUE; } } | @@ -2290,7 +2288,6 @@ sp_fetch_list: sp_instr_cfetch *i= (sp_instr_cfetch *)sp->last_instruction(); i->add_to_varlist(spv); - spv->isset= TRUE; } } ; @@ -5894,7 +5891,6 @@ select_var_ident: else { ((select_dumpvar *)lex->result)->var_list.push_back( new my_var($1,1,t->offset,t->type)); - t->isset= TRUE; } } ; @@ -7925,7 +7921,6 @@ sys_option_value: sp_set= new sp_instr_set(lex->sphead->instructions(), ctx, spv->offset, it, spv->type, lex, TRUE); lex->sphead->add_instr(sp_set); - spv->isset= TRUE; } } | option_type TRANSACTION_SYM ISOLATION LEVEL_SYM isolation_types |