Commit e5b5f453 authored by unknown's avatar unknown

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
parent 96991914
......@@ -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;
......@@ -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;
......
......@@ -52,7 +52,7 @@ class Item {
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 @@ class Item {
};
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 @@ class Item_field :public Item_ident
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 @@ class Item_ref :public Item_ident
}
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 @@ class Item_func_interval :public Item_int_func
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 @@ class Item_func_case :public Item_func
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 @@ class Item_func_like :public Item_bool_func2
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 @@ class Item_func_regex :public Item_bool_func
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 @@ class Item_cond :public Item_bool_func
{ 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 @@ class Item_func :public Item_result_field
}
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 @@ class Item_func_field :public Item_int_func
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 @@ class Item_udf_func :public Item_func
: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 @@ class Item_func_set_user_var :public Item_func
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 @@ class Item_func_match :public Item_real_func
}
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 @@ class Item_func_concat_ws :public Item_str_func
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 @@ class Item_func_elt :public Item_str_func
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 @@ class Item_func_make_set :public Item_str_func
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 @@ class Item_subselect :public Item
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 @@ class Item_sum_num :public Item_sum
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 @@ class Item_udf_sum : public Item_sum
{ 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 @@ class Item_sum_unique_users :public Item_sum_num
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 @@ class THD :public ilink {
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 @@ class st_select_lex: public st_select_lex_node {
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(&current_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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment