From 12a0546da376a492b40e3b63c45470fa42ba3010 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 16 Oct 2003 15:45:27 +0200 Subject: [PATCH] Handle user variables (@-vars) as OUT and INOUT parameters in SPs. mysql-test/r/sp.result: Test cases for user variables (@-vars) as OUT and INOUT parameters. mysql-test/t/sp.test: Test cases for user variables (@-vars) as OUT and INOUT parameters. sql/item_func.h: We need to be able to detect Item_func_get_user_vars when used as arguments to SPs. sql/sp_head.cc: Handle user variables (@-vars) as OUT and INOUT parameters. But we still just ignore it, if it's anything else. --- mysql-test/r/sp.result | 16 +++++++++++++++- mysql-test/t/sp.test | 20 ++++++++++++++++++-- sql/item_func.h | 5 ++++- sql/sp_head.cc | 38 ++++++++++++++++++++++---------------- 4 files changed, 59 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index cec4f7a9935..ab253112ab3 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -93,8 +93,12 @@ id data zip 100 delete from t1; drop procedure zip; -drop procedure zap; drop procedure bar; +call zap(7, @zap); +select @zap; +@zap +8 +drop procedure zap; create procedure c1(x int) call c2("c", x); create procedure c2(s char(16), x int) @@ -132,7 +136,17 @@ io1 1 delete from t1; drop procedure iotest; drop procedure inc2; +create procedure incr(inout x int) +call inc(x); +select @zap; +@zap +8 +call incr(@zap); +select @zap; +@zap +9 drop procedure inc; +drop procedure incr; create procedure cbv1() begin declare y int default 3; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 230a76721a4..91d4fd45d3f 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -122,9 +122,14 @@ call zip("zip", 99)| select * from t1| delete from t1| drop procedure zip| -drop procedure zap| drop procedure bar| +# Top-level OUT parameter +call zap(7, @zap)| +select @zap| + +drop procedure zap| + # "Deep" calls... create procedure c1(x int) @@ -165,8 +170,19 @@ select * from t1| delete from t1| drop procedure iotest| drop procedure inc2| -drop procedure inc| +# Propagating top-level @-vars +create procedure incr(inout x int) + call inc(x)| + +# Before +select @zap| +call incr(@zap)| +# After +select @zap| + +drop procedure inc| +drop procedure incr| # Call-by-value test # The expected result is: diff --git a/sql/item_func.h b/sql/item_func.h index b15dea77c56..649ddfb9f78 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -46,7 +46,8 @@ public: SP_TOUCHES_FUNC,SP_CROSSES_FUNC,SP_WITHIN_FUNC, SP_CONTAINS_FUNC,SP_OVERLAPS_FUNC, SP_STARTPOINT,SP_ENDPOINT,SP_EXTERIORRING, - SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN}; + SP_POINTN,SP_GEOMETRYN,SP_INTERIORRINGN, + GUSERVAR_FUNC}; enum optimize_type { OPTIMIZE_NONE,OPTIMIZE_KEY,OPTIMIZE_OP, OPTIMIZE_NULL }; enum Type type() const { return FUNC_ITEM; } virtual enum Functype functype() const { return UNKNOWN_FUNC; } @@ -926,6 +927,8 @@ public: Item_func_get_user_var(LEX_STRING a): Item_func(), name(a) {} user_var_entry *get_entry(); + enum Functype functype() const { return GUSERVAR_FUNC; } + LEX_STRING get_name() { return name; } double val(); longlong val_int(); String *val_str(String* str); diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 521e5577577..3f3838a0650 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -389,7 +389,8 @@ sp_head::execute_procedure(THD *thd, List *args) else nctx->push_item(sp_eval_func_item(thd, it,pvar->type)); // IN or INOUT // Note: If it's OUT or INOUT, it must be a variable. - // QQ: Need to handle "global" user/host variables too!!! + // QQ: We can check for global variables here, or should we do it + // while parsing? if (pvar->mode == sp_param_in) nctx->set_oindex(i, -1); // IN else // OUT or INOUT @@ -427,22 +428,27 @@ sp_head::execute_procedure(THD *thd, List *args) if (! tmp_octx) octx->set_item(nctx->get_oindex(i), nctx->get_item(i)); else - { // A global user variable -#if NOT_USED_NOW - // QQ This works if the parameter really is a user variable, but - // for the moment we can't assure that, so it will crash if it's - // something else. So for now, we just do nothing, to avoid a crash. - // Note: This also assumes we have a get_name() method in - // the Item_func_get_user_var class. - Item *item= nctx->get_item(i); - Item_func_set_user_var *suv; - Item_func_get_user_var *guv= static_cast(it); + { + // QQ Currently we just silently ignore non-user-variable arguments. + // We should check this during parsing, when setting up the call + // above + if (it->type() == Item::FUNC_ITEM) + { + Item_func *fi= static_cast(it); - suv= new Item_func_set_user_var(guv->get_name(), item); - suv->fix_fields(thd, NULL, &item); - suv->fix_length_and_dec(); - suv->update(); -#endif + if (fi->functype() == Item_func::GUSERVAR_FUNC) + { // A global user variable + Item *item= nctx->get_item(i); + Item_func_set_user_var *suv; + Item_func_get_user_var *guv= + static_cast(fi); + + suv= new Item_func_set_user_var(guv->get_name(), item); + suv->fix_fields(thd, NULL, &item); + suv->fix_length_and_dec(); + suv->update(); + } + } } } }