Merge of fix for BUG#6976 continued: pulling in some Item_ref changes from 5.0
* Added Item_ref::set_properties * Item_ref::Item_ref now expects to get in *item either NULL - then fix_fields() will be called later or ptr to Item it will refer to - then an equivalent of fix_fields() call is performed
This commit is contained in:
parent
a8e52ef412
commit
3ceb04a5d8
29
sql/item.cc
29
sql/item.cc
@ -1488,16 +1488,24 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
|
|||||||
"forward reference in item list");
|
"forward reference in item list");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Here, a subset of actions performed by Item_ref::set_properties
|
||||||
|
is not enough. So we pass ptr to NULL into Item_[direct]_ref ctor,
|
||||||
|
so no initialization is performed, and call fix_fields() below.
|
||||||
|
*/
|
||||||
|
Item *save= last->ref_pointer_array[counter];
|
||||||
|
last->ref_pointer_array[counter]= NULL;
|
||||||
Item_ref *rf= (place == IN_HAVING ?
|
Item_ref *rf= (place == IN_HAVING ?
|
||||||
new Item_ref(last->ref_pointer_array + counter,
|
new Item_ref(last->ref_pointer_array + counter,
|
||||||
(char *)table_name,
|
(char *)table_name,
|
||||||
(char *)field_name, this) :
|
(char *)field_name) :
|
||||||
new Item_direct_ref(last->ref_pointer_array + counter,
|
new Item_direct_ref(last->ref_pointer_array + counter,
|
||||||
(char *)table_name,
|
(char *)table_name,
|
||||||
(char *)field_name, this));
|
(char *)field_name));
|
||||||
if (!rf)
|
if (!rf)
|
||||||
return 1;
|
return 1;
|
||||||
thd->change_item_tree(ref, rf);
|
thd->change_item_tree(ref, rf);
|
||||||
|
last->ref_pointer_array[counter]= save;
|
||||||
/*
|
/*
|
||||||
rf is Item_ref => never substitute other items (in this case)
|
rf is Item_ref => never substitute other items (in this case)
|
||||||
during fix_fields() => we can use rf after fix_fields()
|
during fix_fields() => we can use rf after fix_fields()
|
||||||
@ -2220,18 +2228,23 @@ bool Item_ref::fix_fields(THD *thd,TABLE_LIST *tables, Item **reference)
|
|||||||
"forward reference in item list"));
|
"forward reference in item list"));
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
max_length= (*ref)->max_length;
|
|
||||||
maybe_null= (*ref)->maybe_null;
|
set_properties();
|
||||||
decimals= (*ref)->decimals;
|
|
||||||
collation.set((*ref)->collation);
|
|
||||||
with_sum_func= (*ref)->with_sum_func;
|
|
||||||
fixed= 1;
|
|
||||||
|
|
||||||
if (ref && (*ref)->check_cols(1))
|
if (ref && (*ref)->check_cols(1))
|
||||||
return 1;
|
return 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Item_ref::set_properties()
|
||||||
|
{
|
||||||
|
max_length= (*ref)->max_length;
|
||||||
|
maybe_null= (*ref)->maybe_null;
|
||||||
|
decimals= (*ref)->decimals;
|
||||||
|
collation.set((*ref)->collation);
|
||||||
|
with_sum_func= (*ref)->with_sum_func;
|
||||||
|
fixed= 1;
|
||||||
|
}
|
||||||
|
|
||||||
void Item_ref::print(String *str)
|
void Item_ref::print(String *str)
|
||||||
{
|
{
|
||||||
|
41
sql/item.h
41
sql/item.h
@ -827,34 +827,35 @@ public:
|
|||||||
|
|
||||||
class Item_ref :public Item_ident
|
class Item_ref :public Item_ident
|
||||||
{
|
{
|
||||||
|
protected:
|
||||||
|
void set_properties();
|
||||||
public:
|
public:
|
||||||
Field *result_field; /* Save result here */
|
Field *result_field; /* Save result here */
|
||||||
Item **ref;
|
Item **ref;
|
||||||
Item_ref(const char *db_par, const char *table_name_par,
|
Item_ref(const char *db_par, const char *table_name_par,
|
||||||
const char *field_name_par)
|
const char *field_name_par)
|
||||||
:Item_ident(db_par, table_name_par, field_name_par), ref(0) {}
|
:Item_ident(db_par, table_name_par, field_name_par), ref(0) {}
|
||||||
Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
|
|
||||||
:Item_ident(NullS, table_name_par, field_name_par), ref(item) {}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
This constructor is used when processing GROUP BY and referred Item is
|
This constructor is used in two scenarios:
|
||||||
available. We set all properties here because fix_fields() will not be
|
A) *item = NULL
|
||||||
called for the created Item_ref. (see BUG#6976)
|
No initialization is performed, fix_fields() call will be necessary.
|
||||||
TODO check if we could get rid of *_name_par parameters and if we need to
|
|
||||||
perform similar initialization for other ctors.
|
B) *item points to an Item this Item_ref will refer to. This is
|
||||||
|
used for GROUP BY. fix_fields() will not be called in this case,
|
||||||
|
so we call set_properties to make this item "fixed". set_properties
|
||||||
|
performs a subset of action Item_ref::fix_fields does, and this subset
|
||||||
|
is enough for Item_ref's used in GROUP BY.
|
||||||
|
|
||||||
TODO we probably fix a superset of problems like in BUG#6658. Check this
|
TODO we probably fix a superset of problems like in BUG#6658. Check this
|
||||||
with Bar, and if we have a more broader set of problems like this.
|
with Bar, and if we have a more broader set of problems like this.
|
||||||
*/
|
*/
|
||||||
Item_ref(Item **item, const char *table_name_par,
|
Item_ref(Item **item, const char *table_name_par, const char *field_name_par)
|
||||||
const char *field_name_par, Item *src)
|
:Item_ident(NullS, table_name_par, field_name_par), ref(item)
|
||||||
: Item_ident(NullS, table_name_par, field_name_par), ref(item)
|
|
||||||
{
|
{
|
||||||
collation.set(src->collation);
|
if (*item)
|
||||||
max_length= src->max_length;
|
set_properties();
|
||||||
decimals= src->decimals;
|
|
||||||
with_sum_func= src->with_sum_func;
|
|
||||||
maybe_null= src->maybe_null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Constructor need to process subselect with temporary tables (see Item) */
|
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||||
Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), ref(item->ref) {}
|
Item_ref(THD *thd, Item_ref *item) :Item_ident(thd, item), ref(item->ref) {}
|
||||||
enum Type type() const { return REF_ITEM; }
|
enum Type type() const { return REF_ITEM; }
|
||||||
@ -862,29 +863,34 @@ public:
|
|||||||
{ return ref && (*ref)->eq(item, binary_cmp); }
|
{ return ref && (*ref)->eq(item, binary_cmp); }
|
||||||
double val()
|
double val()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
double tmp=(*ref)->val_result();
|
double tmp=(*ref)->val_result();
|
||||||
null_value=(*ref)->null_value;
|
null_value=(*ref)->null_value;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
longlong val_int()
|
longlong val_int()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
longlong tmp=(*ref)->val_int_result();
|
longlong tmp=(*ref)->val_int_result();
|
||||||
null_value=(*ref)->null_value;
|
null_value=(*ref)->null_value;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
String *val_str(String* tmp)
|
String *val_str(String* tmp)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
tmp=(*ref)->str_result(tmp);
|
tmp=(*ref)->str_result(tmp);
|
||||||
null_value=(*ref)->null_value;
|
null_value=(*ref)->null_value;
|
||||||
return tmp;
|
return tmp;
|
||||||
}
|
}
|
||||||
bool is_null()
|
bool is_null()
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
(void) (*ref)->val_int_result();
|
(void) (*ref)->val_int_result();
|
||||||
return (*ref)->null_value;
|
return (*ref)->null_value;
|
||||||
}
|
}
|
||||||
bool get_date(TIME *ltime,uint fuzzydate)
|
bool get_date(TIME *ltime,uint fuzzydate)
|
||||||
{
|
{
|
||||||
|
DBUG_ASSERT(fixed);
|
||||||
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
|
return (null_value=(*ref)->get_date_result(ltime,fuzzydate));
|
||||||
}
|
}
|
||||||
bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
|
bool send(Protocol *prot, String *tmp){ return (*ref)->send(prot, tmp); }
|
||||||
@ -922,9 +928,6 @@ public:
|
|||||||
:Item_ref(item, table_name_par, field_name_par) {}
|
:Item_ref(item, table_name_par, field_name_par) {}
|
||||||
/* Constructor need to process subselect with temporary tables (see Item) */
|
/* Constructor need to process subselect with temporary tables (see Item) */
|
||||||
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
|
Item_direct_ref(THD *thd, Item_direct_ref *item) : Item_ref(thd, item) {}
|
||||||
Item_direct_ref(Item **item, const char *table_name_par,
|
|
||||||
const char *field_name_par, Item *src)
|
|
||||||
: Item_ref(item, table_name_par, field_name_par, src) {}
|
|
||||||
|
|
||||||
double val()
|
double val()
|
||||||
{
|
{
|
||||||
|
@ -2022,8 +2022,8 @@ void Item_cond::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|||||||
{
|
{
|
||||||
Item **ref= li.ref();
|
Item **ref= li.ref();
|
||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name,
|
ref_pointer_array[el]= item;
|
||||||
item);
|
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
|
||||||
fields.push_front(item);
|
fields.push_front(item);
|
||||||
ref_pointer_array[el]= item;
|
ref_pointer_array[el]= item;
|
||||||
thd->change_item_tree(ref, new_item);
|
thd->change_item_tree(ref, new_item);
|
||||||
|
@ -349,7 +349,8 @@ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|||||||
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
|
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
|
||||||
{
|
{
|
||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name, item);
|
ref_pointer_array[el]= item;
|
||||||
|
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
|
||||||
new_item->collation.set(item->collation);
|
new_item->collation.set(item->collation);
|
||||||
fields.push_front(item);
|
fields.push_front(item);
|
||||||
ref_pointer_array[el]= item;
|
ref_pointer_array[el]= item;
|
||||||
|
@ -95,8 +95,8 @@ void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|||||||
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
|
else if ((*arg)->used_tables() || (*arg)->type() == SUM_FUNC_ITEM)
|
||||||
{
|
{
|
||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name,
|
ref_pointer_array[el]=*arg;
|
||||||
*arg);
|
Item *new_item= new Item_ref(ref_pointer_array + el, 0, (*arg)->name);
|
||||||
fields.push_front(*arg);
|
fields.push_front(*arg);
|
||||||
ref_pointer_array[el]= *arg;
|
ref_pointer_array[el]= *arg;
|
||||||
thd->change_item_tree(arg, new_item);
|
thd->change_item_tree(arg, new_item);
|
||||||
|
@ -1748,7 +1748,8 @@ void Item_func_make_set::split_sum_func(THD *thd, Item **ref_pointer_array,
|
|||||||
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
|
else if (item->used_tables() || item->type() == SUM_FUNC_ITEM)
|
||||||
{
|
{
|
||||||
uint el= fields.elements;
|
uint el= fields.elements;
|
||||||
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name,item);
|
ref_pointer_array[el]=item;
|
||||||
|
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
|
||||||
fields.push_front(item);
|
fields.push_front(item);
|
||||||
ref_pointer_array[el]= item;
|
ref_pointer_array[el]= item;
|
||||||
thd->change_item_tree(&item, new_item);
|
thd->change_item_tree(&item, new_item);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user