mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
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.
This commit is contained in:
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
|
@ -389,7 +389,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *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<Item> *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<Item_func_get_user_var*>(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<Item_func*>(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<Item_func_get_user_var*>(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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user