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:
unknown 2002-07-01 14:14:51 +03:00
parent 969919146e
commit e5b5f45319
23 changed files with 177 additions and 99 deletions

View File

@ -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; 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) b (select avg(t2.a+(select min(t3.a) from t3 where t3.a >= t4.a)) from t2)
8 7.5000 8 7.5000
8 6.0000 8 4.5000
9 5.5000 9 7.5000
select * from t3 where exists (select * from t2 where t2.b=t3.a); select * from t3 where exists (select * from t2 where t2.b=t3.a);
a a
7 7
@ -74,4 +74,12 @@ select * from t3 where not exists (select * from t2 where t2.b=t3.a);
a a
6 6
3 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; drop table t1,t2,t3,t4;

View File

@ -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 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 exists (select * from t2 where t2.b=t3.a);
select * from t3 where not 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; drop table t1,t2,t3,t4;

View File

@ -446,12 +446,13 @@ String *Item_copy_string::val_str(String *str)
/* ARGSUSED */ /* ARGSUSED */
bool Item::fix_fields(THD *thd, bool Item::fix_fields(THD *thd,
struct st_table_list *list) struct st_table_list *list,
Item ** ref)
{ {
return 0; 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 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 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. 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(); for (SELECT_LEX *sl= thd->lex.select->outer_select();
sl && !tmp; sl && !tmp;
sl= sl->outer_select()) sl= sl->outer_select())
@ -476,6 +477,8 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
if (!tmp) if (!tmp)
return 1; return 1;
else else
{
depended_from= last;
/* /*
Mark all selects from resolved to 1 before select where was Mark all selects from resolved to 1 before select where was
found table as depended (of select where was found table) 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= tbl->next)
tbl->shared= 1; tbl->shared= 1;
} }
}
} }
set_field(tmp); set_field(tmp);
} }
@ -504,6 +508,14 @@ bool Item_field::fix_fields(THD *thd,TABLE_LIST *tables)
table->used_fields++; table->used_fields++;
table->used_keys&=field->part_of_key; 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; return 0;
} }
@ -787,12 +799,50 @@ bool Item_null::send(THD *thd, String *packet)
Find field in select list having the same name 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)
{ {
if (!(ref=find_item_in_list(this,thd->lex.select->item_list))) if (!(ref= find_item_in_list(this,thd->lex.select->item_list)))
return 1; {
/*
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; max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null; maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals; decimals= (*ref)->decimals;

View File

@ -52,7 +52,7 @@ public:
virtual ~Item() { name=0; } /*lint -e1509 */ virtual ~Item() { name=0; } /*lint -e1509 */
void set_name(char* str,uint length=0); void set_name(char* str,uint length=0);
void init_make_field(Send_field *tmp_field,enum enum_field_types type); 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 bool save_in_field(Field *field);
virtual void save_org_in_field(Field *field) virtual void save_org_in_field(Field *field)
{ (void) save_in_field(field); } { (void) save_in_field(field); }
@ -85,15 +85,18 @@ public:
}; };
class st_select_lex;
class Item_ident :public Item class Item_ident :public Item
{ {
public: public:
const char *db_name; const char *db_name;
const char *table_name; const char *table_name;
const char *field_name; const char *field_name;
st_select_lex *depended_from;
Item_ident(const char *db_name_par,const char *table_name_par, Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_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; } { name = (char*) field_name_par; }
const char *full_name() const; const char *full_name() const;
}; };
@ -120,7 +123,7 @@ public:
String *str_result(String* tmp); String *str_result(String* tmp);
bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); } bool send(THD *thd, String *str_arg) { return result_field->send(thd,str_arg); }
void make_field(Send_field *field); 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); bool save_in_field(Field *field);
void save_org_in_field(Field *field); void save_org_in_field(Field *field);
table_map used_tables() const; table_map used_tables() const;
@ -390,7 +393,7 @@ public:
} }
bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); } bool send(THD *thd, String *tmp) { return (*ref)->send(thd, tmp); }
void make_field(Send_field *field) { (*ref)->make_field(field); } 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); } 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); } void save_org_in_field(Field *field) { (*ref)->save_org_in_field(field); }
enum Item_result result_type () const { return (*ref)->result_type(); } enum Item_result result_type () const { return (*ref)->result_type(); }

View File

@ -727,12 +727,12 @@ double Item_func_case::val()
bool 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) || if (first_expr && first_expr->fix_fields(thd, tables, &first_expr) ||
else_expr && else_expr->fix_fields(thd,tables)) else_expr && else_expr->fix_fields(thd, tables, &else_expr))
return 1; return 1;
if (Item_func::fix_fields(thd,tables)) if (Item_func::fix_fields(thd, tables, ref))
return 1; return 1;
if (first_expr) if (first_expr)
{ {
@ -1074,7 +1074,7 @@ longlong Item_func_bit_and::val_int()
bool 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); List_iterator<Item> li(list);
Item *item; Item *item;
@ -1096,7 +1096,7 @@ Item_cond::fix_fields(THD *thd,TABLE_LIST *tables)
#endif #endif
item= *li.ref(); // new current item item= *li.ref(); // new current item
} }
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, li.ref()))
return 1; /* purecov: inspected */ return 1; /* purecov: inspected */
used_tables_cache|=item->used_tables(); used_tables_cache|=item->used_tables();
with_sum_func= with_sum_func || item->with_sum_func; 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; 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; return 1;
/* /*
@ -1324,9 +1324,10 @@ bool Item_func_like::fix_fields(THD *thd,struct st_table_list *tlist)
#ifdef USE_REGEX #ifdef USE_REGEX
bool 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 */ return 1; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func; with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length=1; decimals=0; max_length=1; decimals=0;

View File

@ -177,9 +177,10 @@ public:
Item_func_interval(Item *a,List<Item> &list) Item_func_interval(Item *a,List<Item> &list)
:Item_int_func(list),item(a),intervals(0) {} :Item_int_func(list),item(a),intervals(0) {}
longlong val_int(); 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(); void fix_length_and_dec();
~Item_func_interval() { delete item; } ~Item_func_interval() { delete item; }
@ -259,7 +260,7 @@ public:
enum Item_result result_type () const { return cached_result_type; } enum Item_result result_type () const { return cached_result_type; }
const char *func_name() const { return "case"; } const char *func_name() const { return "case"; }
void print(String *str); 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); 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_func_in(Item *a,List<Item> &list)
:Item_int_func(list),item(a),array(0),in_item(0) {} :Item_int_func(list),item(a),array(0),in_item(0) {}
longlong val_int(); 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(); void fix_length_and_dec();
~Item_func_in() { delete item; delete array; delete in_item; } ~Item_func_in() { delete item; delete array; delete in_item; }
@ -505,7 +507,7 @@ public:
cond_result eq_cmp_result() const { return COND_TRUE; } cond_result eq_cmp_result() const { return COND_TRUE; }
const char *func_name() const { return "like"; } const char *func_name() const { return "like"; }
void fix_length_and_dec(); 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 #ifdef USE_REGEX
@ -523,7 +525,7 @@ public:
regex_compiled(0),regex_is_const(0) {} regex_compiled(0),regex_is_const(0) {}
~Item_func_regex(); ~Item_func_regex();
longlong val_int(); 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"; } const char *func_name() const { return "regex"; }
}; };
@ -552,7 +554,7 @@ public:
{ list.push_back(i1); list.push_back(i2); } { list.push_back(i1); list.push_back(i2); }
~Item_cond() { list.delete_elements(); } ~Item_cond() { list.delete_elements(); }
bool add(Item *item) { return list.push_back(item); } 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; } enum Type type() const { return COND_ITEM; }
List<Item>* argument_list() { return &list; } List<Item>* argument_list() { return &list; }

View File

@ -58,7 +58,7 @@ Item_func::Item_func(List<Item> &list)
} }
bool 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; Item **arg,**arg_end;
char buff[STACK_BUFF_ALLOC]; // Max argument in function 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 { // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++) 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 */ return 1; /* purecov: inspected */
if ((*arg)->maybe_null) if ((*arg)->maybe_null)
maybe_null=1; maybe_null=1;
@ -1102,7 +1102,7 @@ udf_handler::~udf_handler()
bool 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) uint arg_count, Item **arguments)
{ {
char buff[STACK_BUFF_ALLOC]; // Max argument in function 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 != arg_end ;
arg++,i++) arg++,i++)
{ {
if ((*arg)->fix_fields(thd,tables)) if ((*arg)->fix_fields(thd, tables, arg))
return 1; return 1;
if ((*arg)->binary) if ((*arg)->binary)
func->binary=1; 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) if (!thd)
thd=current_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))) !(entry= get_variable(&thd->user_vars, name, 1)))
return 1; return 1;
entry->update_query_id=thd->query_id; 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); List_iterator<Item> li(fields);
Item *item; 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 modifications to find_best and auto_close as complement to auto_init code
above. 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"); my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
return 1; return 1;
@ -2116,7 +2117,7 @@ bool Item_func_match::fix_fields(THD *thd,struct st_table_list *tlist)
while ((item=li++)) while ((item=li++))
{ {
if (item->fix_fields(thd,tlist)) if (item->fix_fields(thd, tlist, li.ref()))
return 1; return 1;
if (item->type() == Item::REF_ITEM) if (item->type() == Item::REF_ITEM)
li.replace(item= *((Item_ref *)item)->ref); li.replace(item= *((Item_ref *)item)->ref);

View File

@ -99,7 +99,7 @@ public:
} }
Item_func(List<Item> &list); Item_func(List<Item> &list);
~Item_func() {} /* Nothing to do; Items are freed automaticly */ ~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); void make_field(Send_field *field);
table_map used_tables() const; table_map used_tables() const;
void update_used_tables(); 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(Item *a,List<Item> &list) :Item_int_func(list),item(a) {}
~Item_func_field() { delete item; } ~Item_func_field() { delete item; }
longlong val_int(); 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() void update_used_tables()
{ {
@ -708,11 +709,11 @@ public:
:Item_func(list), udf(udf_arg) {} :Item_func(list), udf(udf_arg) {}
~Item_udf_func() {} ~Item_udf_func() {}
const char *func_name() const { return udf.name(); } 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); bool res= udf.fix_fields(thd, tables, this, arg_count, args);
used_tables_cache=udf.used_tables_cache; used_tables_cache= udf.used_tables_cache;
const_item_cache=udf.const_item_cache; const_item_cache= udf.const_item_cache;
return res; return res;
} }
Item_result result_type () const { return udf.result_type(); } 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); void update_hash(void *ptr, uint length, enum Item_result type);
bool update(); bool update();
enum Item_result result_type () const { return cached_result_type; } 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 fix_length_and_dec();
void print(String *str); void print(String *str);
const char *func_name() const { return "set_user_var"; } const char *func_name() const { return "set_user_var"; }
@ -941,7 +942,7 @@ public:
} }
enum Functype functype() const { return FT_FUNC; } enum Functype functype() const { return FT_FUNC; }
void update_used_tables() {} 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; bool eq(const Item *, bool binary_cmp) const;
longlong val_int() { return val()!=0.0; } longlong val_int() { return val()!=0.0; }
double val(); double val();

View File

@ -79,10 +79,10 @@ public:
String *val_str(String *); String *val_str(String *);
void fix_length_and_dec(); void fix_length_and_dec();
void update_used_tables(); 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) return (separator->fix_fields(thd, tlist, &separator)
|| Item_func::fix_fields(thd,tlist)); || Item_func::fix_fields(thd, tlist, ref));
} }
const char *func_name() const { return "concat_ws"; } const char *func_name() const { return "concat_ws"; }
}; };
@ -325,9 +325,10 @@ public:
double val(); double val();
longlong val_int(); longlong val_int();
String *val_str(String *str); 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 fix_length_and_dec();
void update_used_tables(); 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(Item *a,List<Item> &list) :Item_str_func(list),item(a) {}
~Item_func_make_set() { delete item; } ~Item_func_make_set() { delete item; }
String *val_str(String *str); 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 fix_length_and_dec();
void update_used_tables(); void update_used_tables();

View File

@ -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? // Is it one field subselect?
if (select_lex->item_list.elements > max_columns) if (select_lex->item_list.elements > max_columns)
{ {

View File

@ -63,7 +63,7 @@ public:
enum Type type() const; enum Type type() const;
bool is_null() { return null_value; } bool is_null() { return null_value; }
void make_field (Send_field *); 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; table_map used_tables() const;
friend class select_subselect; friend class select_subselect;

View File

@ -112,7 +112,7 @@ Item_sum_int::val_str(String *str)
bool 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) if (!thd->allow_sum_func)
{ {
@ -124,7 +124,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
maybe_null=0; maybe_null=0;
for (uint i=0 ; i < arg_count ; i++) 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; return 1;
if (decimals < args[i]->decimals) if (decimals < args[i]->decimals)
decimals=args[i]->decimals; decimals=args[i]->decimals;
@ -140,7 +140,7 @@ Item_sum_num::fix_fields(THD *thd,TABLE_LIST *tables)
bool 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]; Item *item=args[0];
if (!thd->allow_sum_func) if (!thd->allow_sum_func)
@ -149,7 +149,7 @@ Item_sum_hybrid::fix_fields(THD *thd,TABLE_LIST *tables)
return 1; return 1;
} }
thd->allow_sum_func=0; // No included group funcs thd->allow_sum_func=0; // No included group funcs
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, args))
return 1; return 1;
hybrid_type=item->result_type(); hybrid_type=item->result_type();
if (hybrid_type == INT_RESULT) 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)) !(tmp_table_param= new TMP_TABLE_PARAM))
return 1; return 1;
return 0; return 0;

View File

@ -80,7 +80,7 @@ public:
Item_sum_num(Item *item_par) :Item_sum(item_par) {} Item_sum_num(Item *item_par) :Item_sum(item_par) {}
Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {} Item_sum_num(Item *a, Item* b) :Item_sum(a,b) {}
Item_sum_num(List<Item> &list) :Item_sum(list) {} 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 */ longlong val_int() { return (longlong) val(); } /* Real as default */
String *val_str(String*str); String *val_str(String*str);
void reset_field(); void reset_field();
@ -146,7 +146,7 @@ class Item_sum_count_distinct :public Item_sum_int
{ {
TABLE *table; TABLE *table;
table_map used_table_cache; 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; uint32 *field_lengths;
TMP_TABLE_PARAM *tmp_table_param; TMP_TABLE_PARAM *tmp_table_param;
TREE tree; 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), Item_sum_hybrid(Item *item_par,int sign) :Item_sum(item_par),cmp_sign(sign),
used_table_cache(~(table_map) 0) 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; } table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; } bool const_item() const { return !used_table_cache; }
@ -382,7 +382,7 @@ public:
{ quick_group=0;} { quick_group=0;}
~Item_udf_sum() {} ~Item_udf_sum() {}
const char *func_name() const { return udf.name(); } 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); return udf.fix_fields(thd,tables,this,this->arg_count,this->args);
} }

View File

@ -42,5 +42,5 @@ public:
bool add() { return 0; } bool add() { return 0; }
void reset_field() {} void reset_field() {}
void update_field(int offset) {} 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;}
}; };

View File

@ -1874,7 +1874,7 @@ int setup_fields(THD *thd, TABLE_LIST *tables, List<Item> &fields,
} }
else else
{ {
if (item->fix_fields(thd,tables)) if (item->fix_fields(thd, tables, it.ref()))
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM && if (item->with_sum_func && item->type() != Item::SUM_FUNC_ITEM &&
sum_func_list) sum_func_list)
@ -2025,7 +2025,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
if (*conds) if (*conds)
{ {
thd->where="where clause"; thd->where="where clause";
if ((*conds)->fix_fields(thd,tables)) if ((*conds)->fix_fields(thd, tables, conds))
DBUG_RETURN(1); DBUG_RETURN(1);
} }
@ -2036,7 +2036,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
{ {
/* Make a join an a expression */ /* Make a join an a expression */
thd->where="on clause"; 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); DBUG_RETURN(1);
thd->cond_count++; thd->cond_count++;

View File

@ -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), THD::THD():user_time(0),fatal_error(0),last_insert_id_used(0),
insert_id_used(0), in_lock_tables(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=user=priv_user=db=query=ip=0;
host_or_ip="unknown ip"; host_or_ip="unknown ip";

View File

@ -453,7 +453,6 @@ public:
bool query_error, bootstrap, cleanup_done; bool query_error, bootstrap, cleanup_done;
bool safe_to_cache_query; bool safe_to_cache_query;
bool volatile killed; bool volatile killed;
bool having_fix_field; //TRUE when having fix field called
bool prepare_command; bool prepare_command;
ulong param_count,current_param_number; ulong param_count,current_param_number;
Error<mysql_st_error> err_list; Error<mysql_st_error> err_list;

View File

@ -106,7 +106,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
} }
tables->table=table; tables->table=table;
if (cond && cond->fix_fields(thd,tables)) if (cond && cond->fix_fields(thd, tables, &cond))
return -1; return -1;
if (keyname) if (keyname)

View File

@ -942,8 +942,8 @@ void st_select_lex::init_select()
interval_list.empty(); interval_list.empty();
use_index.empty(); use_index.empty();
ftfunc_list.empty(); ftfunc_list.empty();
linkage=UNSPECIFIED_TYPE; linkage= UNSPECIFIED_TYPE;
depended= 0; depended= having_fix_field= 0;
} }
/* /*

View File

@ -253,7 +253,10 @@ public:
uint in_sum_expr; uint in_sum_expr;
bool create_refs, bool create_refs,
braces, /* SELECT ... UNION (SELECT ... ) <- this braces */ 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_query();
void init_select(); void init_select();
st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; } st_select_lex_unit* master_unit() { return (st_select_lex_unit*) master; }

View File

@ -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, static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
List<Item> &fields, List<Item> &values, List<Item> &fields, List<Item> &values,
COND *conds, ORDER *order, ORDER *group, COND *conds, ORDER *order, ORDER *group,
Item *having,thr_lock_type lock_type) Item *having, thr_lock_type lock_type)
{ {
TABLE *table; TABLE *table;
bool hidden_group_fields; bool hidden_group_fields;
@ -470,7 +470,7 @@ static bool mysql_test_select_fields(THD *thd, TABLE_LIST *tables,
{ {
thd->where="having clause"; thd->where="having clause";
thd->allow_sum_func=1; 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); DBUG_RETURN(1);
if (having->with_sum_func) if (having->with_sum_func)
having->split_sum_func(all_fields); having->split_sum_func(all_fields);

View File

@ -227,10 +227,9 @@ JOIN::prepare(TABLE_LIST *tables_init,
{ {
thd->where="having clause"; thd->where="having clause";
thd->allow_sum_func=1; thd->allow_sum_func=1;
bool having_fix_field_store= thd->having_fix_field; select_lex->having_fix_field= 1;
thd->having_fix_field= 1; bool having_fix_rc= having->fix_fields(thd, tables_list, &having);
bool having_fix_rc= having->fix_fields(thd,tables_list); select_lex->having_fix_field= 0;
thd->having_fix_field= having_fix_field_store;
if (having_fix_rc || thd->fatal_error) if (having_fix_rc || thd->fatal_error)
DBUG_RETURN(-1); /* purecov: inspected */ DBUG_RETURN(-1); /* purecov: inspected */
if (having->with_sum_func) if (having->with_sum_func)
@ -349,7 +348,7 @@ JOIN::optimize()
} }
else if ((conds=new Item_cond_and(conds,having))) 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); conds->change_ref_to_fields(thd, tables_list);
having= 0; having= 0;
} }
@ -612,6 +611,15 @@ JOIN::reinit()
if (setup_tables(tables_list)) if (setup_tables(tables_list))
DBUG_RETURN(1); 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); DBUG_RETURN(0);
} }
@ -3381,7 +3389,7 @@ remove_eq_conds(COND *cond,Item::cond_result *cond_value)
21)))) 21))))
{ {
cond=new_cond; cond=new_cond;
cond->fix_fields(thd,0); cond->fix_fields(thd, 0, &cond);
} }
thd->insert_id(0); // Clear for next request 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)))) if ((new_cond= new Item_func_eq(args[0],new Item_int("0", 0, 2))))
{ {
cond=new_cond; 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; return 0;
} }
order->in_field_list=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 return 1; // Wrong field
all_fields.push_front(*order->item); // Add new field to field list all_fields.push_front(*order->item); // Add new field to field list
order->item=(Item**) all_fields.head_ref(); order->item=(Item**) all_fields.head_ref();
@ -6527,7 +6535,7 @@ setup_new_fields(THD *thd,TABLE_LIST *tables,List<Item> &fields,
else else
{ {
thd->where="procedure list"; 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 */ DBUG_RETURN(1); /* purecov: inspected */
thd->where=0; thd->where=0;
all_fields.push_front(*new_field->item); 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 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). 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) if (join_tab->select)
{ {
error=(int) cond->add(join_tab->select->cond); error=(int) cond->add(join_tab->select->cond);

View File

@ -2973,7 +2973,7 @@ kill:
KILL_SYM expr KILL_SYM expr
{ {
LEX *lex=Lex; 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); send_error(&lex->thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
@ -3469,7 +3469,8 @@ option_value:
| '@' ident_or_text equal expr | '@' ident_or_text equal expr
{ {
Item_func_set_user_var *item = new Item_func_set_user_var($2,$4); 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(&current_thd->net, ER_SET_CONSTANTS_ONLY); send_error(&current_thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;
@ -3501,7 +3502,7 @@ option_value:
{ {
THD *thd=current_thd; THD *thd=current_thd;
Item *item= $3; 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); send_error(&thd->net, ER_SET_CONSTANTS_ONLY);
YYABORT; YYABORT;