subselect in having clause
fixed bug in sum function in subselect mysql-test/r/subselect.result: subselect in having clause mysql-test/t/subselect.test: subselect in having clause sql/item.cc: subselect in having clause sql/item.h: subselect in having clause sql/item_cmpfunc.cc: subselect in having clause sql/item_cmpfunc.h: subselect in having clause sql/item_func.cc: subselect in having clause sql/item_func.h: subselect in having clause sql/item_strfunc.h: subselect in having clause sql/item_subselect.cc: subselect in having clause sql/item_subselect.h: subselect in having clause sql/item_uniq.h: subselect in having clause sql/sql_base.cc: subselect in having clause sql/sql_class.cc: subselect in having clause sql/sql_class.h: subselect in having clause sql/sql_handler.cc: subselect in having clause sql/sql_lex.cc: subselect in having clause sql/sql_lex.h: subselect in having clause sql/sql_prepare.cc: subselect in having clause sql/sql_yacc.yy: subselect in having clause
This commit is contained in:
parent
969919146e
commit
e5b5f45319
@ -65,8 +65,8 @@ a
|
||||
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
|
||||
b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
|
||||
8 7.5000
|
||||
8 6.0000
|
||||
9 5.5000
|
||||
8 4.5000
|
||||
9 7.5000
|
||||
select * from t3 where exists (select * from t2 where t2.b=t3.a);
|
||||
a
|
||||
7
|
||||
@ -74,4 +74,12 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a);
|
||||
a
|
||||
6
|
||||
3
|
||||
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
||||
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
||||
from t2 where t2.b=t4.b);
|
||||
b ma
|
||||
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
|
||||
from t2 where t2.b=t4.b);
|
||||
b ma
|
||||
7 12
|
||||
drop table t1,t2,t3,t4;
|
||||
|
@ -28,4 +28,9 @@ select * from t1 where t1.a=(select t2.a from t2 where t2.b=(select max(a) from
|
||||
select b,(select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2) from t4;
|
||||
select * from t3 where exists (select * from t2 where t2.b=t3.a);
|
||||
select * from t3 where not exists (select * from t2 where t2.b=t3.a);
|
||||
insert into t4 values (12,7),(1,7),(10,9),(9,6),(7,6),(3,9);
|
||||
select b,max(a) as ma from t4 group by b having b < (select max(t2.a)
|
||||
from t2 where t2.b=t4.b);
|
||||
select b,max(a) as ma from t4 group by b having b >= (select max(t2.a)
|
||||
from t2 where t2.b=t4.b);
|
||||
drop table t1,t2,t3,t4;
|
||||
|
62
sql/item.cc
62
sql/item.cc
@ -446,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
|
||||
|
||||
/* ARGSUSED */
|
||||
bool Item::fix_fields(THD *thd,
|
||||
struct st_table_list *list)
|
||||
struct st_table_list *list,
|
||||
Item ** ref)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
if (!field) // If field is not checked
|
||||
{
|
||||
@ -467,7 +468,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
mention of table name, but if we join tables in one list it will
|
||||
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
|
||||
*/
|
||||
SELECT_LEX *last;
|
||||
SELECT_LEX *last= 0;
|
||||
for (SELECT_LEX *sl= thd->lex.select->outer_select();
|
||||
sl && !tmp;
|
||||
sl= sl->outer_select())
|
||||
@ -476,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
if (!tmp)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
depended_from= last;
|
||||
/*
|
||||
Mark all selects from resolved to 1 before select where was
|
||||
found table as depended (of select where was found table)
|
||||
@ -493,6 +496,7 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
tbl= tbl->next)
|
||||
tbl->shared= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
set_field(tmp);
|
||||
}
|
||||
@ -504,6 +508,14 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
table->used_fields++;
|
||||
table->used_keys&=field->part_of_key;
|
||||
}
|
||||
if (depended_from != 0 && depended_from->having_fix_field)
|
||||
{
|
||||
*ref= new Item_ref((char *)db_name, (char *)table_name,
|
||||
(char *)field_name);
|
||||
if (!*ref)
|
||||
return 1;
|
||||
return (*ref)->fix_fields(thd, tables, ref);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -787,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
|
||||
Find field in select list having the same name
|
||||
*/
|
||||
|
||||
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
||||
{
|
||||
if (!ref)
|
||||
{
|
||||
if (!(ref=find_item_in_list(this,thd->lex.select->item_list)))
|
||||
return 1;
|
||||
if (!(ref= find_item_in_list(this,thd->lex.select->item_list)))
|
||||
{
|
||||
/*
|
||||
We can't find table field in table list of current select,
|
||||
consequently we have to find it in outer subselect(s).
|
||||
We can't join lists of outer & current select, because of scope
|
||||
of view rules. For example if both tables (outer & current) have
|
||||
field 'field' it is not mistake to refer to this field without
|
||||
mention of table name, but if we join tables in one list it will
|
||||
cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
|
||||
*/
|
||||
SELECT_LEX *last=0;
|
||||
for (SELECT_LEX *sl= thd->lex.select->outer_select();
|
||||
sl && !ref;
|
||||
sl= sl->outer_select())
|
||||
ref= find_item_in_list(this, (last= sl)->item_list);
|
||||
if (!ref)
|
||||
return 1;
|
||||
else
|
||||
{
|
||||
depended_from= last;
|
||||
/*
|
||||
Mark all selects from resolved to 1 before select where was
|
||||
found table as depended (of select where was found table)
|
||||
*/
|
||||
for (SELECT_LEX *s= thd->lex.select;
|
||||
s &&s != last;
|
||||
s= s->outer_select())
|
||||
if( !s->depended )
|
||||
{
|
||||
s->depended= 1; //Select is depended of outer select
|
||||
//Tables will be reopened many times
|
||||
for (TABLE_LIST *tbl=
|
||||
(TABLE_LIST*)s->table_list.first;
|
||||
tbl;
|
||||
tbl= tbl->next)
|
||||
tbl->shared= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
max_length= (*ref)->max_length;
|
||||
maybe_null= (*ref)->maybe_null;
|
||||
decimals= (*ref)->decimals;
|
||||
|
11
sql/item.h
11
sql/item.h
@ -52,7 +52,7 @@ public:
|
||||
virtual ~Item() { name=0; } /*lint -e1509 */
|
||||
void set_name(char* str,uint length=0);
|
||||
void init_make_field(Send_field *tmp_field,enum enum_field_types type);
|
||||
virtual bool fix_fields(THD *,struct st_table_list *);
|
||||
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
virtual bool save_in_field(Field *field);
|
||||
virtual void save_org_in_field(Field *field)
|
||||
{ (void) save_in_field(field); }
|
||||
@ -85,15 +85,18 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class st_select_lex;
|
||||
class Item_ident :public Item
|
||||
{
|
||||
public:
|
||||
const char *db_name;
|
||||
const char *table_name;
|
||||
const char *field_name;
|
||||
st_select_lex *depended_from;
|
||||
Item_ident(const char *db_name_par,const char *table_name_par,
|
||||
const char *field_name_par)
|
||||
:db_name(db_name_par),table_name(table_name_par),field_name(field_name_par)
|
||||
:db_name(db_name_par),table_name(table_name_par),
|
||||
field_name(field_name_par), depended_from(0)
|
||||
{ name = (char*) field_name_par; }
|
||||
const char *full_name() const;
|
||||
};
|
||||
@ -120,7 +123,7 @@ public:
|
||||
String *str_result(String* tmp);
|
||||
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
|
||||
void make_field(Send_field *field);
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool save_in_field(Field *field);
|
||||
void save_org_in_field(Field *field);
|
||||
table_map used_tables() const;
|
||||
@ -390,7 +393,7 @@ public:
|
||||
}
|
||||
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
|
||||
void make_field(Send_field *field) { (*ref)->make_field(field); }
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **);
|
||||
bool save_in_field(Field *field) { return (*ref)->save_in_field(field); }
|
||||
void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
|
||||
enum Item_result result_type () const { return (*ref)->result_type(); }
|
||||
|
@ -727,12 +727,12 @@ double Item_func_case::val()
|
||||
|
||||
|
||||
bool
|
||||
Item_func_case::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_func_case::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
if (first_expr && first_expr->fix_fields(thd,tables) ||
|
||||
else_expr && else_expr->fix_fields(thd,tables))
|
||||
if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) ||
|
||||
else_expr && else_expr->fix_fields(thd, tables, &else_expr))
|
||||
return 1;
|
||||
if (Item_func::fix_fields(thd,tables))
|
||||
if (Item_func::fix_fields(thd, tables, ref))
|
||||
return 1;
|
||||
if (first_expr)
|
||||
{
|
||||
@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int()
|
||||
|
||||
|
||||
bool
|
||||
Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
List_iterator<Item> li(list);
|
||||
Item *item;
|
||||
@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
#endif
|
||||
item= *li.ref(); // new current item
|
||||
}
|
||||
if (item->fix_fields(thd,tables))
|
||||
if (item->fix_fields(thd, tables, li.ref()))
|
||||
return 1; /* purecov: inspected */
|
||||
used_tables_cache|=item->used_tables();
|
||||
with_sum_func= with_sum_func || item->with_sum_func;
|
||||
@ -1272,9 +1272,9 @@ Item_func::optimize_type Item_func_like::select_optimize() const
|
||||
return OPTIMIZE_NONE;
|
||||
}
|
||||
|
||||
bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
|
||||
{
|
||||
if (Item_bool_func2::fix_fields(thd, tlist))
|
||||
if (Item_bool_func2::fix_fields(thd, tlist, ref))
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
#ifdef USE_REGEX
|
||||
|
||||
bool
|
||||
Item_func_regex::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
if (args[0]->fix_fields(thd,tables) || args[1]->fix_fields(thd,tables))
|
||||
if (args[0]->fix_fields(thd, tables, args) ||
|
||||
args[1]->fix_fields(thd,tables, args + 1))
|
||||
return 1; /* purecov: inspected */
|
||||
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
|
||||
max_length=1; decimals=0;
|
||||
|
@ -177,9 +177,10 @@ public:
|
||||
Item_func_interval(Item *a,List<Item> &list)
|
||||
:Item_int_func(list),item(a),intervals(0) {}
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
|
||||
{
|
||||
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
|
||||
return (item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
~Item_func_interval() { delete item; }
|
||||
@ -259,7 +260,7 @@ public:
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
const char *func_name() const { return "case"; }
|
||||
void print(String *str);
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
Item *find_item(String *str);
|
||||
};
|
||||
|
||||
@ -409,9 +410,10 @@ class Item_func_in :public Item_int_func
|
||||
Item_func_in(Item *a,List<Item> &list)
|
||||
:Item_int_func(list),item(a),array(0),in_item(0) {}
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref)
|
||||
{
|
||||
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
|
||||
return (item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
~Item_func_in() { delete item; delete array; delete in_item; }
|
||||
@ -505,7 +507,7 @@ public:
|
||||
cond_result eq_cmp_result() const { return COND_TRUE; }
|
||||
const char *func_name() const { return "like"; }
|
||||
void fix_length_and_dec();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
};
|
||||
|
||||
#ifdef USE_REGEX
|
||||
@ -523,7 +525,7 @@ public:
|
||||
regex_compiled(0),regex_is_const(0) {}
|
||||
~Item_func_regex();
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
const char *func_name() const { return "regex"; }
|
||||
};
|
||||
|
||||
@ -552,7 +554,7 @@ public:
|
||||
{ list.push_back(i1); list.push_back(i2); }
|
||||
~Item_cond() { list.delete_elements(); }
|
||||
bool add(Item *item) { return list.push_back(item); }
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *, struct st_table_list *, Item **ref);
|
||||
|
||||
enum Type type() const { return COND_ITEM; }
|
||||
List<Item>* argument_list() { return &list; }
|
||||
|
@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
|
||||
}
|
||||
|
||||
bool
|
||||
Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
Item **arg,**arg_end;
|
||||
char buff[STACK_BUFF_ALLOC]; // Max argument in function
|
||||
@ -72,7 +72,7 @@ Item_func::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
{ // Print purify happy
|
||||
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
|
||||
{
|
||||
if ((*arg)->fix_fields(thd,tables))
|
||||
if ((*arg)->fix_fields(thd, tables, arg))
|
||||
return 1; /* purecov: inspected */
|
||||
if ((*arg)->maybe_null)
|
||||
maybe_null=1;
|
||||
@ -1102,7 +1102,7 @@ udf_handler::~udf_handler()
|
||||
|
||||
|
||||
bool
|
||||
udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
|
||||
udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
|
||||
uint arg_count, Item **arguments)
|
||||
{
|
||||
char buff[STACK_BUFF_ALLOC]; // Max argument in function
|
||||
@ -1146,7 +1146,7 @@ udf_handler::fix_fields(THD *thd,TABLE_LIST *tables,Item_result_field *func,
|
||||
arg != arg_end ;
|
||||
arg++,i++)
|
||||
{
|
||||
if ((*arg)->fix_fields(thd,tables))
|
||||
if ((*arg)->fix_fields(thd, tables, arg))
|
||||
return 1;
|
||||
if ((*arg)->binary)
|
||||
func->binary=1;
|
||||
@ -1765,11 +1765,12 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
|
||||
}
|
||||
|
||||
|
||||
bool Item_func_set_user_var::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||
Item **ref)
|
||||
{
|
||||
if (!thd)
|
||||
thd=current_thd;
|
||||
if (Item_func::fix_fields(thd,tables) ||
|
||||
if (Item_func::fix_fields(thd, tables, ref) ||
|
||||
!(entry= get_variable(&thd->user_vars, name, 1)))
|
||||
return 1;
|
||||
entry->update_query_id=thd->query_id;
|
||||
@ -2095,7 +2096,7 @@ void Item_func_match::init_search(bool no_order)
|
||||
}
|
||||
}
|
||||
|
||||
bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
{
|
||||
List_iterator<Item> li(fields);
|
||||
Item *item;
|
||||
@ -2108,7 +2109,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
modifications to find_best and auto_close as complement to auto_init code
|
||||
above.
|
||||
*/
|
||||
if (Item_func::fix_fields(thd,tlist) || !const_item())
|
||||
if (Item_func::fix_fields(thd, tlist, ref) || !const_item())
|
||||
{
|
||||
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
|
||||
return 1;
|
||||
@ -2116,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
|
||||
while ((item=li++))
|
||||
{
|
||||
if (item->fix_fields(thd,tlist))
|
||||
if (item->fix_fields(thd, tlist, li.ref()))
|
||||
return 1;
|
||||
if (item->type() == Item::REF_ITEM)
|
||||
li.replace(item= *((Item_ref *)item)->ref);
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
}
|
||||
Item_func(List<Item> &list);
|
||||
~Item_func() {} /* Nothing to do; Items are freed automaticly */
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *,struct st_table_list *, Item **ref);
|
||||
void make_field(Send_field *field);
|
||||
table_map used_tables() const;
|
||||
void update_used_tables();
|
||||
@ -567,9 +567,10 @@ public:
|
||||
Item_func_field(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
|
||||
~Item_func_field() { delete item; }
|
||||
longlong val_int();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist, Item **ref)
|
||||
{
|
||||
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
|
||||
return (item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
void update_used_tables()
|
||||
{
|
||||
@ -708,11 +709,11 @@ public:
|
||||
:Item_func(list), udf(udf_arg) {}
|
||||
~Item_udf_func() {}
|
||||
const char *func_name() const { return udf.name(); }
|
||||
bool fix_fields(THD *thd,struct st_table_list *tables)
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref)
|
||||
{
|
||||
bool res=udf.fix_fields(thd,tables,this,arg_count,args);
|
||||
used_tables_cache=udf.used_tables_cache;
|
||||
const_item_cache=udf.const_item_cache;
|
||||
bool res= udf.fix_fields(thd, tables, this, arg_count, args);
|
||||
used_tables_cache= udf.used_tables_cache;
|
||||
const_item_cache= udf.const_item_cache;
|
||||
return res;
|
||||
}
|
||||
Item_result result_type () const { return udf.result_type(); }
|
||||
@ -867,7 +868,7 @@ public:
|
||||
void update_hash(void *ptr, uint length, enum Item_result type);
|
||||
bool update();
|
||||
enum Item_result result_type () const { return cached_result_type; }
|
||||
bool fix_fields(THD *thd,struct st_table_list *tables);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tables, Item **ref);
|
||||
void fix_length_and_dec();
|
||||
void print(String *str);
|
||||
const char *func_name() const { return "set_user_var"; }
|
||||
@ -941,7 +942,7 @@ public:
|
||||
}
|
||||
enum Functype functype() const { return FT_FUNC; }
|
||||
void update_used_tables() {}
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist);
|
||||
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
|
||||
bool eq(const Item *, bool binary_cmp) const;
|
||||
longlong val_int() { return val()!=0.0; }
|
||||
double val();
|
||||
|
@ -79,10 +79,10 @@ public:
|
||||
String *val_str(String *);
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
{
|
||||
return (separator->fix_fields(thd,tlist)
|
||||
|| Item_func::fix_fields(thd,tlist));
|
||||
return (separator->fix_fields(thd, tlist, &separator)
|
||||
|| Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
const char *func_name() const { return "concat_ws"; }
|
||||
};
|
||||
@ -325,9 +325,10 @@ public:
|
||||
double val();
|
||||
longlong val_int();
|
||||
String *val_str(String *str);
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
{
|
||||
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
|
||||
return (item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
@ -344,9 +345,10 @@ public:
|
||||
Item_func_make_set(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
|
||||
~Item_func_make_set() { delete item; }
|
||||
String *val_str(String *str);
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist)
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
|
||||
{
|
||||
return (item->fix_fields(thd,tlist) || Item_func::fix_fields(thd,tlist));
|
||||
return (item->fix_fields(thd, tlist, &item) ||
|
||||
Item_func::fix_fields(thd, tlist, ref));
|
||||
}
|
||||
void fix_length_and_dec();
|
||||
void update_used_tables();
|
||||
|
@ -75,15 +75,8 @@ void Item_subselect::make_field (Send_field *tmp_field)
|
||||
}
|
||||
}
|
||||
|
||||
bool Item_subselect::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_subselect::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
|
||||
if (thd->having_fix_field)
|
||||
{
|
||||
//TODO: subselects in having do not suported now
|
||||
my_printf_error(ER_SYNTAX_ERROR, ER(ER_SYNTAX_ERROR), MYF(0));
|
||||
return 1;
|
||||
}
|
||||
// Is it one field subselect?
|
||||
if (select_lex->item_list.elements > max_columns)
|
||||
{
|
||||
|
@ -63,7 +63,7 @@ public:
|
||||
enum Type type() const;
|
||||
bool is_null() { return null_value; }
|
||||
void make_field (Send_field *);
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables);
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
table_map used_tables() const;
|
||||
|
||||
friend class select_subselect;
|
||||
|
@ -112,7 +112,7 @@ Item_sum_int::val_str(String *str)
|
||||
|
||||
|
||||
bool
|
||||
Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
if (!thd->allow_sum_func)
|
||||
{
|
||||
@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
maybe_null=0;
|
||||
for (uint i=0 ; i < arg_count ; i++)
|
||||
{
|
||||
if (args[i]->fix_fields(thd,tables))
|
||||
if (args[i]->fix_fields(thd, tables, args + i))
|
||||
return 1;
|
||||
if (decimals < args[i]->decimals)
|
||||
decimals=args[i]->decimals;
|
||||
@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
|
||||
|
||||
bool
|
||||
Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
Item *item=args[0];
|
||||
if (!thd->allow_sum_func)
|
||||
@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
return 1;
|
||||
}
|
||||
thd->allow_sum_func=0; // No included group funcs
|
||||
if (item->fix_fields(thd,tables))
|
||||
if (item->fix_fields(thd, tables, args))
|
||||
return 1;
|
||||
hybrid_type=item->result_type();
|
||||
if (hybrid_type == INT_RESULT)
|
||||
@ -930,9 +930,10 @@ Item_sum_count_distinct::~Item_sum_count_distinct()
|
||||
}
|
||||
|
||||
|
||||
bool Item_sum_count_distinct::fix_fields(THD *thd,TABLE_LIST *tables)
|
||||
bool Item_sum_count_distinct::fix_fields(THD *thd, TABLE_LIST *tables,
|
||||
Item **ref)
|
||||
{
|
||||
if (Item_sum_num::fix_fields(thd,tables) ||
|
||||
if (Item_sum_num::fix_fields(thd, tables, ref) ||
|
||||
!(tmp_table_param= new TMP_TABLE_PARAM))
|
||||
return 1;
|
||||
return 0;
|
||||
|
@ -80,7 +80,7 @@ public:
|
||||
Item_sum_num(Item *item_par) :Item_sum(item_par) {}
|
||||
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
|
||||
Item_sum_num(List<Item> &list) :Item_sum(list) {}
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
longlong val_int() { return (longlong) val(); } /* Real as default */
|
||||
String *val_str(String*str);
|
||||
void reset_field();
|
||||
@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
|
||||
{
|
||||
TABLE *table;
|
||||
table_map used_table_cache;
|
||||
bool fix_fields(THD *thd,TABLE_LIST *tables);
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref);
|
||||
uint32 *field_lengths;
|
||||
TMP_TABLE_PARAM *tmp_table_param;
|
||||
TREE tree;
|
||||
@ -283,7 +283,7 @@ class Item_sum_hybrid :public Item_sum
|
||||
Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
|
||||
used_table_cache(~(table_map) 0)
|
||||
{}
|
||||
bool fix_fields(THD *,struct st_table_list *);
|
||||
bool fix_fields(THD *, TABLE_LIST *, Item **);
|
||||
table_map used_tables() const { return used_table_cache; }
|
||||
bool const_item() const { return !used_table_cache; }
|
||||
|
||||
@ -382,7 +382,7 @@ public:
|
||||
{ quick_group=0;}
|
||||
~Item_udf_sum() {}
|
||||
const char *func_name() const { return udf.name(); }
|
||||
bool fix_fields(THD *thd,struct st_table_list *tables)
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
||||
{
|
||||
return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
|
||||
}
|
||||
|
@ -42,5 +42,5 @@ public:
|
||||
bool add() { return 0; }
|
||||
void reset_field() {}
|
||||
void update_field(int offset) {}
|
||||
bool fix_fields(THD *thd,struct st_table_list *tlist) { return 0;}
|
||||
bool fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref) { return 0;}
|
||||
};
|
||||
|
@ -1874,7 +1874,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
|
||||
}
|
||||
else
|
||||
{
|
||||
if (item->fix_fields(thd,tables))
|
||||
if (item->fix_fields(thd, tables, it.ref()))
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
|
||||
sum_func_list)
|
||||
@ -2025,7 +2025,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
||||
if (*conds)
|
||||
{
|
||||
thd->where="where clause";
|
||||
if ((*conds)->fix_fields(thd,tables))
|
||||
if ((*conds)->fix_fields(thd, tables, conds))
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
@ -2036,7 +2036,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
|
||||
{
|
||||
/* Make a join an a expression */
|
||||
thd->where="on clause";
|
||||
if (table->on_expr->fix_fields(thd,tables))
|
||||
if (table->on_expr->fix_fields(thd, tables, &table->on_expr))
|
||||
DBUG_RETURN(1);
|
||||
thd->cond_count++;
|
||||
|
||||
|
@ -81,7 +81,7 @@ static void free_var(user_var_entry *entry)
|
||||
|
||||
THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
|
||||
insert_id_used(0), in_lock_tables(0),
|
||||
global_read_lock(0), bootstrap(0), having_fix_field(0)
|
||||
global_read_lock(0), bootstrap(0)
|
||||
{
|
||||
host=user=priv_user=db=query=ip=0;
|
||||
host_or_ip="unknown ip";
|
||||
|
@ -453,7 +453,6 @@ public:
|
||||
bool query_error, bootstrap, cleanup_done;
|
||||
bool safe_to_cache_query;
|
||||
bool volatile killed;
|
||||
bool having_fix_field; //TRUE when having fix field called
|
||||
bool prepare_command;
|
||||
ulong param_count,current_param_number;
|
||||
Error<mysql_st_error> err_list;
|
||||
|
@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
|
||||
}
|
||||
tables->table=table;
|
||||
|
||||
if (cond && cond->fix_fields(thd,tables))
|
||||
if (cond && cond->fix_fields(thd, tables, &cond))
|
||||
return -1;
|
||||
|
||||
if (keyname)
|
||||
|
@ -942,8 +942,8 @@ void st_select_lex::init_select()
|
||||
interval_list.empty();
|
||||
use_index.empty();
|
||||
ftfunc_list.empty();
|
||||
linkage=UNSPECIFIED_TYPE;
|
||||
depended= 0;
|
||||
linkage= UNSPECIFIED_TYPE;
|
||||
depended= having_fix_field= 0;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -253,7 +253,10 @@ public:
|
||||
uint in_sum_expr;
|
||||
bool create_refs,
|
||||
braces, /* SELECT ... UNION (SELECT ... ) <- this braces */
|
||||
depended; /* depended from outer select subselect */
|
||||
depended, /* depended from outer select subselect */
|
||||
/* TRUE when having fix field called in processing of this SELECT */
|
||||
having_fix_field;
|
||||
|
||||
void init_query();
|
||||
void init_select();
|
||||
st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }
|
||||
|
@ -448,7 +448,7 @@ static bool mysql_test_upd_fields(THD *thd, TABLE_LIST *table_list,
|
||||
static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
|
||||
List<Item> &fields, List<Item> &values,
|
||||
COND *conds, ORDER *order, ORDER *group,
|
||||
Item *having,thr_lock_type lock_type)
|
||||
Item *having, thr_lock_type lock_type)
|
||||
{
|
||||
TABLE *table;
|
||||
bool hidden_group_fields;
|
||||
@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
|
||||
{
|
||||
thd->where="having clause";
|
||||
thd->allow_sum_func=1;
|
||||
if (having->fix_fields(thd,tables) || thd->fatal_error)
|
||||
if (having->fix_fields(thd, tables, &having) || thd->fatal_error)
|
||||
DBUG_RETURN(1);
|
||||
if (having->with_sum_func)
|
||||
having->split_sum_func(all_fields);
|
||||
|
@ -227,10 +227,9 @@ JOIN::prepare(TABLE_LIST *tables_init,
|
||||
{
|
||||
thd->where="having clause";
|
||||
thd->allow_sum_func=1;
|
||||
bool having_fix_field_store= thd->having_fix_field;
|
||||
thd->having_fix_field= 1;
|
||||
bool having_fix_rc= having->fix_fields(thd,tables_list);
|
||||
thd->having_fix_field= having_fix_field_store;
|
||||
select_lex->having_fix_field= 1;
|
||||
bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
|
||||
select_lex->having_fix_field= 0;
|
||||
if (having_fix_rc || thd->fatal_error)
|
||||
DBUG_RETURN(-1); /* purecov: inspected */
|
||||
if (having->with_sum_func)
|
||||
@ -349,7 +348,7 @@ JOIN::optimize()
|
||||
}
|
||||
else if ((conds=new Item_cond_and(conds,having)))
|
||||
{
|
||||
conds->fix_fields(thd, tables_list);
|
||||
conds->fix_fields(thd, tables_list, &conds);
|
||||
conds->change_ref_to_fields(thd, tables_list);
|
||||
having= 0;
|
||||
}
|
||||
@ -612,6 +611,15 @@ JOIN::reinit()
|
||||
|
||||
if (setup_tables(tables_list))
|
||||
DBUG_RETURN(1);
|
||||
|
||||
// Reset of sum functions
|
||||
first_record= 0;
|
||||
if (sum_funcs)
|
||||
{
|
||||
Item_sum *func, **func_ptr= sum_funcs;
|
||||
while ((func= *(func_ptr++)))
|
||||
func->null_value= 1;
|
||||
}
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
@ -3381,7 +3389,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
||||
21))))
|
||||
{
|
||||
cond=new_cond;
|
||||
cond->fix_fields(thd,0);
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
}
|
||||
thd->insert_id(0); // Clear for next request
|
||||
}
|
||||
@ -3395,7 +3403,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
|
||||
if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
|
||||
{
|
||||
cond=new_cond;
|
||||
cond->fix_fields(thd,0);
|
||||
cond->fix_fields(thd, 0, &cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6429,7 +6437,7 @@ find_order_in_list(THD *thd,TABLE_LIST *tables,ORDER *order,List<Item> &fields,
|
||||
return 0;
|
||||
}
|
||||
order->in_field_list=0;
|
||||
if ((*order->item)->fix_fields(thd,tables) || thd->fatal_error)
|
||||
if ((*order->item)->fix_fields(thd, tables, order->item) || thd->fatal_error)
|
||||
return 1; // Wrong field
|
||||
all_fields.push_front(*order->item); // Add new field to field list
|
||||
order->item=(Item**) all_fields.head_ref();
|
||||
@ -6527,7 +6535,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
|
||||
else
|
||||
{
|
||||
thd->where="procedure list";
|
||||
if ((*new_field->item)->fix_fields(thd,tables))
|
||||
if ((*new_field->item)->fix_fields(thd, tables, new_field->item))
|
||||
DBUG_RETURN(1); /* purecov: inspected */
|
||||
thd->where=0;
|
||||
all_fields.push_front(*new_field->item);
|
||||
@ -7092,7 +7100,7 @@ static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab)
|
||||
Here we pass 0 as the first argument to fix_fields that don't need
|
||||
to do any stack checking (This is already done in the initial fix_fields).
|
||||
*/
|
||||
cond->fix_fields((THD *) 0,(TABLE_LIST *) 0);
|
||||
cond->fix_fields((THD *) 0,(TABLE_LIST *) 0, (Item**)&cond);
|
||||
if (join_tab->select)
|
||||
{
|
||||
error=(int) cond->add(join_tab->select->cond);
|
||||
|
@ -2973,7 +2973,7 @@ kill:
|
||||
KILL_SYM expr
|
||||
{
|
||||
LEX *lex=Lex;
|
||||
if ($2->fix_fields(lex->thd,0))
|
||||
if ($2->fix_fields(lex->thd, 0, &$2))
|
||||
{
|
||||
send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
|
||||
YYABORT;
|
||||
@ -3469,7 +3469,8 @@ option_value:
|
||||
| '@' ident_or_text equal expr
|
||||
{
|
||||
Item_func_set_user_var *item = new Item_func_set_user_var($2,$4);
|
||||
if (item->fix_fields(current_thd,0) || item->update())
|
||||
if (item->fix_fields(current_thd, 0, (Item**) &item) ||
|
||||
item->update())
|
||||
{
|
||||
send_error(¤t_thd->net, ER_SET_CONSTANTS_ONLY);
|
||||
YYABORT;
|
||||
@ -3501,7 +3502,7 @@ option_value:
|
||||
{
|
||||
THD *thd=current_thd;
|
||||
Item *item= $3;
|
||||
if (item->fix_fields(current_thd,0))
|
||||
if (item->fix_fields(current_thd, 0, &item))
|
||||
{
|
||||
send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
|
||||
YYABORT;
|
||||
|
Loading…
x
Reference in New Issue
Block a user