diff --git a/sql/item.cc b/sql/item.cc
index 5433f1e..8392032 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -739,7 +739,7 @@ Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg)
*/
Item_ident::Item_ident(THD *thd, Item_ident *item)
- :Item_result_field(thd, item),
+ :Item_ident_or_func_or_sum(thd, item),
orig_db_name(item->orig_db_name),
orig_table_name(item->orig_table_name),
orig_field_name(item->orig_field_name),
diff --git a/sql/item.h b/sql/item.h
index 4b42db2..225686f 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1094,6 +1094,12 @@ class Item {
void print_item_w_name(String *, enum_query_type query_type);
void print_value(String *);
virtual void update_used_tables() {}
+ virtual COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
+ bool link_item_fields)
+ {
+ update_used_tables();
+ return this;
+ }
virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
List<Item> &fields) {}
/* Called for items that really have to be split */
@@ -2095,7 +2101,19 @@ class Item_result_field :public Item /* Item with result field */
};
-class Item_ident :public Item_result_field
+class Item_ident_or_func_or_sum: public Item_result_field
+{
+public:
+ Item_ident_or_func_or_sum(): Item_result_field() { }
+ Item_ident_or_func_or_sum(THD *thd, Item_ident_or_func_or_sum *item)
+ :Item_result_field(thd, item)
+ { }
+ COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
+ bool link_item_fields);
+};
+
+
+class Item_ident :public Item_ident_or_func_or_sum
{
protected:
/*
@@ -3398,25 +3416,20 @@ class Used_tables_and_const_cache
An abstract class representing common features of
regular functions and aggregate functions.
*/
-class Item_func_or_sum: public Item_result_field, public Item_args
+class Item_func_or_sum: public Item_ident_or_func_or_sum, public Item_args
{
public:
- Item_func_or_sum()
- :Item_result_field(), Item_args() {}
- Item_func_or_sum(Item *a)
- :Item_result_field(), Item_args(a) { }
- Item_func_or_sum(Item *a, Item *b)
- :Item_result_field(), Item_args(a, b) { }
- Item_func_or_sum(Item *a, Item *b, Item *c)
- :Item_result_field(), Item_args(a, b, c) { }
+ Item_func_or_sum() :Item_args() {}
+ Item_func_or_sum(Item *a) :Item_args(a) { }
+ Item_func_or_sum(Item *a, Item *b) :Item_args(a, b) { }
+ Item_func_or_sum(Item *a, Item *b, Item *c) :Item_args(a, b, c) { }
Item_func_or_sum(Item *a, Item *b, Item *c, Item *d)
- :Item_result_field(), Item_args(a, b, c, d) { }
+ :Item_args(a, b, c, d) { }
Item_func_or_sum(Item *a, Item *b, Item *c, Item *d, Item *e)
- :Item_result_field(), Item_args(a, b, c, d, e) { }
+ :Item_args(a, b, c, d, e) { }
Item_func_or_sum(THD *thd, Item_func_or_sum *item)
- :Item_result_field(thd, item), Item_args(thd, item) { }
- Item_func_or_sum(List<Item> &list)
- :Item_result_field(), Item_args(list) { }
+ :Item_ident_or_func_or_sum(thd, item), Item_args(thd, item) { }
+ Item_func_or_sum(List<Item> &list) :Item_args(list) { }
/*
This method is used for debug purposes to print the name of an
item to the debug log. The second use of this method is as
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index bf388ef..ae7bac0 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -1768,6 +1768,8 @@ class Item_cond :public Item_bool_func
used_tables_and_const_cache_init();
used_tables_and_const_cache_update_and_join(list);
}
+ COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
+ bool link_item_fields);
virtual void print(String *str, enum_query_type query_type);
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
@@ -2078,9 +2080,9 @@ class Item_equal_fields_iterator_slow
class Item_cond_and :public Item_cond
{
public:
- COND_EQUAL cond_equal; /* contains list of Item_equal objects for
- the current and level and reference
- to multiple equalities of upper and levels */
+ COND_EQUAL m_cond_equal; /* contains list of Item_equal objects for
+ the current and level and reference
+ to multiple equalities of upper and levels */
Item_cond_and() :Item_cond() {}
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
@@ -2101,6 +2103,8 @@ class Item_cond_and :public Item_cond
void mark_as_condition_AND_part(TABLE_LIST *embedding);
virtual uint exists2in_reserved_items() { return list.elements; };
bool walk_top_and(Item_processor processor, uchar *arg);
+ COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
+ bool link_item_fields);
};
inline bool is_cond_and(Item *item)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 476adb7..d0e0fae 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -3865,7 +3865,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
conds= remove_eq_conds(join->thd, conds, &join->cond_value);
if (conds && conds->type() == Item::COND_ITEM &&
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
- join->cond_equal= &((Item_cond_and*) conds)->cond_equal;
+ join->cond_equal= &((Item_cond_and*) conds)->m_cond_equal;
join->select_lex->where= conds;
if (join->cond_value == Item::COND_FALSE)
{
@@ -3878,7 +3878,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (conds->type() == Item::COND_ITEM &&
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
- join->cond_equal= (&((Item_cond_and *) conds)->cond_equal);
+ join->cond_equal= (&((Item_cond_and *) conds)->m_cond_equal);
else if (conds->type() == Item::FUNC_ITEM &&
((Item_func*) conds)->functype() == Item_func::MULT_EQUAL_FUNC)
{
@@ -4050,7 +4050,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
((Item_cond*) (join->conds))->functype() ==
Item_func::COND_AND_FUNC &&
join->cond_equal ==
- &((Item_cond_and *) (join->conds))->cond_equal) ||
+ &((Item_cond_and *) (join->conds))->m_cond_equal) ||
(join->conds->type() == Item::FUNC_ITEM &&
((Item_func*) (join->conds))->functype() ==
Item_func::MULT_EQUAL_FUNC &&
@@ -12377,7 +12377,7 @@ Item_equal *find_item_equal(COND_EQUAL *cond_equal, Field *field,
general case, its own constant for each fields from the multiple
equality. But at the same time it would allow us to get rid
of constant propagation completely: it would be done by the call
- to build_equal_items_for_cond.
+ to cond->build_equal_items().
The implementation does not follow exactly the above rules to
@@ -12710,7 +12710,10 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
/**
- Replace all equality predicates in a condition by multiple equality items.
+ Item_xxx::build_equal_items()
+
+ Replace all equality predicates in a condition referenced by "this"
+ by multiple equality items.
At each 'and' level the function detects items for equality predicates
and replaced them by a set of multiple equality items of class Item_equal,
@@ -12766,7 +12769,6 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
all possible Item_equal objects in upper levels.
@param thd thread handle
- @param cond condition(expression) where to make replacement
@param inherited path to all inherited multiple equality items
@return
@@ -12775,180 +12777,195 @@ static bool check_equality(THD *thd, Item *item, COND_EQUAL *cond_equal,
so no additional update_used_tables() is needed on the result.
*/
-static COND *build_equal_items_for_cond(THD *thd, COND *cond,
- COND_EQUAL *inherited,
- bool link_item_fields)
+COND *Item_cond_and::build_equal_items(THD *thd,
+ COND_EQUAL *inherited,
+ bool link_item_fields)
{
Item_equal *item_equal;
COND_EQUAL cond_equal;
cond_equal.upper_levels= inherited;
- if (cond->type() == Item::COND_ITEM)
+ List<Item> eq_list;
+ List<Item> *args= argument_list();
+
+ List_iterator<Item> li(*args);
+ Item *item;
+
+ /*
+ Retrieve all conjuncts of this level detecting the equality
+ that are subject to substitution by multiple equality items and
+ removing each such predicate from the conjunction after having
+ found/created a multiple equality whose inference the predicate is.
+ */
+ while ((item= li++))
{
- List<Item> eq_list;
- Item_cond *cond_item= (Item_cond*) cond;
- bool and_level= cond_item->functype() == Item_func::COND_AND_FUNC;
- List<Item> *args= cond_item->argument_list();
-
- List_iterator<Item> li(*args);
- Item *item;
+ /*
+ PS/SP note: we can safely remove a node from AND-OR
+ structure here because it's restored before each
+ re-execution of any prepared statement/stored procedure.
+ */
+ if (check_equality(thd, item, &cond_equal, &eq_list))
+ li.remove();
+ }
- if (and_level)
+ /*
+ Check if we eliminated all the predicates of the level, e.g.
+ (a=a AND b=b AND a=a).
+ */
+ if (!args->elements &&
+ !cond_equal.current_level.elements &&
+ !eq_list.elements)
+ return new Item_int((longlong) 1, 1);
+
+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
+ while ((item_equal= it++))
+ {
+ item_equal->set_link_equal_fields(link_item_fields);
+ item_equal->fix_fields(thd, NULL);
+ item_equal->update_used_tables();
+ set_if_bigger(thd->lex->current_select->max_equal_elems,
+ item_equal->n_field_items());
+ }
+
+ m_cond_equal.copy(cond_equal);
+ cond_equal.current_level= m_cond_equal.current_level;
+ inherited= &m_cond_equal;
+
+ /*
+ Make replacement of equality predicates for lower levels
+ of the condition expression.
+ */
+ li.rewind();
+ while ((item= li++))
+ {
+ Item *new_item;
+ if ((new_item= item->build_equal_items(thd, inherited, FALSE))
+ != item)
{
+ /* This replacement happens only for standalone equalities */
/*
- Retrieve all conjuncts of this level detecting the equality
- that are subject to substitution by multiple equality items and
- removing each such predicate from the conjunction after having
- found/created a multiple equality whose inference the predicate is.
- */
- while ((item= li++))
- {
- /*
- PS/SP note: we can safely remove a node from AND-OR
- structure here because it's restored before each
- re-execution of any prepared statement/stored procedure.
- */
- if (check_equality(thd, item, &cond_equal, &eq_list))
- li.remove();
- }
+ This is ok with PS/SP as the replacement is done for
+ arguments of an AND/OR item, which are restored for each
+ execution of PS/SP.
+ */
+ li.replace(new_item);
+ }
+ }
+ args->append(&eq_list);
+ args->append((List<Item> *)&cond_equal.current_level);
+ update_used_tables();
+ return this;
+}
+
+COND *Item_cond::build_equal_items(THD *thd,
+ COND_EQUAL *inherited,
+ bool link_item_fields)
+{
+ List<Item> *args= argument_list();
+
+ List_iterator<Item> li(*args);
+ Item *item;
+
+ /*
+ Make replacement of equality predicates for lower levels
+ of the condition expression.
+ Update used_tables_cache and const_item_cache on the way.
+ */
+ used_tables_and_const_cache_init();
+ while ((item= li++))
+ {
+ Item *new_item;
+ if ((new_item= item->build_equal_items(thd, inherited, FALSE))
+ != item)
+ {
+ /* This replacement happens only for standalone equalities */
/*
- Check if we eliminated all the predicates of the level, e.g.
- (a=a AND b=b AND a=a).
+ This is ok with PS/SP as the replacement is done for
+ arguments of an AND/OR item, which are restored for each
+ execution of PS/SP.
*/
- if (!args->elements &&
- !cond_equal.current_level.elements &&
- !eq_list.elements)
- return new Item_int((longlong) 1, 1);
+ li.replace(new_item);
+ }
+ used_tables_and_const_cache_join(new_item);
+ }
+ return this;
+}
- List_iterator_fast<Item_equal> it(cond_equal.current_level);
- while ((item_equal= it++))
+
+COND *Item_ident_or_func_or_sum::build_equal_items(THD *thd,
+ COND_EQUAL *inherited,
+ bool link_item_fields)
+{
+ COND_EQUAL cond_equal;
+ cond_equal.upper_levels= inherited;
+ List<Item> eq_list;
+ /*
+ If an equality predicate forms the whole and level,
+ we call it standalone equality and it's processed here.
+ E.g. in the following where condition
+ WHERE a=5 AND (b=5 or a=c)
+ (b=5) and (a=c) are standalone equalities.
+ In general we can't leave alone standalone eqalities:
+ for WHERE a=b AND c=d AND (b=c OR d=5)
+ b=c is replaced by =(a,b,c,d).
+ */
+ if (check_equality(thd, this, &cond_equal, &eq_list))
+ {
+ Item_equal *item_equal;
+ int n= cond_equal.current_level.elements + eq_list.elements;
+ if (n == 0)
+ return new Item_int((longlong) 1,1);
+ else if (n == 1)
+ {
+ if ((item_equal= cond_equal.current_level.pop()))
{
- item_equal->set_link_equal_fields(link_item_fields);
item_equal->fix_fields(thd, NULL);
item_equal->update_used_tables();
set_if_bigger(thd->lex->current_select->max_equal_elems,
item_equal->n_field_items());
+ item_equal->upper_levels= inherited;
+ return item_equal;
}
-
- ((Item_cond_and*)cond)->cond_equal.copy(cond_equal);
- cond_equal.current_level=
- ((Item_cond_and*)cond)->cond_equal.current_level;
- inherited= &(((Item_cond_and*)cond)->cond_equal);
- }
- /*
- Make replacement of equality predicates for lower levels
- of the condition expression.
- Update used_tables_cache and const_item_cache on the way.
- */
- li.rewind();
- cond_item->used_tables_and_const_cache_init();
- while ((item= li++))
- {
- Item *new_item;
- if ((new_item= build_equal_items_for_cond(thd, item, inherited, FALSE))
- != item)
- {
- /* This replacement happens only for standalone equalities */
- /*
- This is ok with PS/SP as the replacement is done for
- arguments of an AND/OR item, which are restored for each
- execution of PS/SP.
- */
- li.replace(new_item);
- }
- cond_item->used_tables_and_const_cache_join(new_item);
+ Item *res= eq_list.pop();
+ res->update_used_tables();
+ return res;
}
- if (and_level)
+ else
{
- args->append(&eq_list);
- args->append((List<Item> *)&cond_equal.current_level);
- /*
- Instead of the cond_item->update_used_tables() call below,
- we could do this:
-
- cond_item->used_tables_and_const_cache_update_and_join(eq_list);
- cond_item->used_tables_and_const_cache_update_and_join(
- *(List<Item> *) &cond_equal.current_level);
-
- But initializing 2 iterators will probably be even slower than
- redundant iterations over the topmost elements in "args",
- which were already processed in the "while" loop above.
+ /*
+ Here a new AND level must be created. It can happen only
+ when a row equality is processed as a standalone predicate.
*/
- cond_item->update_used_tables();
- }
- return cond_item;
- }
- else if (cond->type() == Item::FUNC_ITEM ||
- cond->real_item()->type() == Item::FIELD_ITEM)
- {
- List<Item> eq_list;
- /*
- If an equality predicate forms the whole and level,
- we call it standalone equality and it's processed here.
- E.g. in the following where condition
- WHERE a=5 AND (b=5 or a=c)
- (b=5) and (a=c) are standalone equalities.
- In general we can't leave alone standalone eqalities:
- for WHERE a=b AND c=d AND (b=c OR d=5)
- b=c is replaced by =(a,b,c,d).
- */
- if (check_equality(thd, cond, &cond_equal, &eq_list))
- {
- int n= cond_equal.current_level.elements + eq_list.elements;
- if (n == 0)
- return new Item_int((longlong) 1,1);
- else if (n == 1)
- {
- if ((item_equal= cond_equal.current_level.pop()))
- {
- item_equal->fix_fields(thd, NULL);
- item_equal->update_used_tables();
- set_if_bigger(thd->lex->current_select->max_equal_elems,
- item_equal->n_field_items());
- item_equal->upper_levels= inherited;
- return item_equal;
- }
- Item *res= eq_list.pop();
- res->update_used_tables();
- return res;
- }
- else
+ Item_cond_and *and_cond= new Item_cond_and(eq_list);
+ and_cond->quick_fix_field();
+ List<Item> *args= and_cond->argument_list();
+ List_iterator_fast<Item_equal> it(cond_equal.current_level);
+ while ((item_equal= it++))
{
- /*
- Here a new AND level must be created. It can happen only
- when a row equality is processed as a standalone predicate.
- */
- Item_cond_and *and_cond= new Item_cond_and(eq_list);
- and_cond->quick_fix_field();
- List<Item> *args= and_cond->argument_list();
- List_iterator_fast<Item_equal> it(cond_equal.current_level);
- while ((item_equal= it++))
- {
- item_equal->fix_length_and_dec();
- item_equal->update_used_tables();
- set_if_bigger(thd->lex->current_select->max_equal_elems,
- item_equal->n_field_items());
- }
- and_cond->cond_equal.copy(cond_equal);
- cond_equal.current_level= and_cond->cond_equal.current_level;
- args->append((List<Item> *)&cond_equal.current_level);
- and_cond->update_used_tables();
- return and_cond;
+ item_equal->fix_length_and_dec();
+ item_equal->update_used_tables();
+ set_if_bigger(thd->lex->current_select->max_equal_elems,
+ item_equal->n_field_items());
}
+ and_cond->m_cond_equal.copy(cond_equal);
+ cond_equal.current_level= and_cond->m_cond_equal.current_level;
+ args->append((List<Item> *)&cond_equal.current_level);
+ and_cond->update_used_tables();
+ return and_cond;
}
- /*
- For each field reference in cond, not from equal item predicates,
- set a pointer to the multiple equality it belongs to (if there is any)
- as soon the field is not of a string type or the field reference is
- an argument of a comparison predicate.
- */
- uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
- cond= cond->compile(&Item::subst_argument_checker,
- &is_subst_valid,
- &Item::equal_fields_propagator,
- (uchar *) inherited);
}
+ /*
+ For each field reference in cond, not from equal item predicates,
+ set a pointer to the multiple equality it belongs to (if there is any)
+ as soon the field is not of a string type or the field reference is
+ an argument of a comparison predicate.
+ */
+ uchar* is_subst_valid= (uchar *) Item::ANY_SUBST;
+ COND *cond= compile(&Item::subst_argument_checker,
+ &is_subst_valid,
+ &Item::equal_fields_propagator,
+ (uchar *) inherited);
cond->update_used_tables();
return cond;
}
@@ -12958,7 +12975,7 @@ static COND *build_equal_items_for_cond(THD *thd, COND *cond,
Build multiple equalities for a condition and all on expressions that
inherit these multiple equalities.
- The function first applies the build_equal_items_for_cond function
+ The function first applies the cond->build_equal_items() method
to build all multiple equalities for condition cond utilizing equalities
referred through the parameter inherited. The extended set of
equalities is returned in the structure referred by the cond_equal_ref
@@ -13035,10 +13052,10 @@ static COND *build_equal_items(JOIN *join, COND *cond,
if (cond)
{
- cond= build_equal_items_for_cond(thd, cond, inherited, link_equal_fields);
+ cond= cond->build_equal_items(thd, inherited, link_equal_fields);
if (cond->type() == Item::COND_ITEM &&
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
- cond_equal= &((Item_cond_and*) cond)->cond_equal;
+ cond_equal= &((Item_cond_and*) cond)->m_cond_equal;
else if (cond->type() == Item::FUNC_ITEM &&
((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
@@ -13516,7 +13533,7 @@ static COND* substitute_for_best_equal_field(JOIN_TAB *context_tab,
Item_func::COND_AND_FUNC;
if (and_level)
{
- cond_equal= &((Item_cond_and *) cond)->cond_equal;
+ cond_equal= &((Item_cond_and *) cond)->m_cond_equal;
cond_list->disjoin((List<Item> *) &cond_equal->current_level);/* remove Item_equal objects from the AND. */
List_iterator_fast<Item_equal> it(cond_equal->current_level);
@@ -14667,7 +14684,7 @@ optimize_cond(JOIN *join, COND *conds,
conds= remove_eq_conds(thd, conds, cond_value);
if (conds && conds->type() == Item::COND_ITEM &&
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
- *cond_equal= &((Item_cond_and*) conds)->cond_equal;
+ *cond_equal= &((Item_cond_and*) conds)->m_cond_equal;
DBUG_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
}
DBUG_RETURN(conds);
@@ -14708,8 +14725,8 @@ void propagate_new_equalities(THD *thd, Item *cond,
if (and_level)
{
Item_cond_and *cond_and= (Item_cond_and *) cond;
- List<Item_equal> *cond_equalities= &cond_and->cond_equal.current_level;
- cond_and->cond_equal.upper_levels= inherited;
+ List<Item_equal> *cond_equalities= &cond_and->m_cond_equal.current_level;
+ cond_and->m_cond_equal.upper_levels= inherited;
if (!cond_equalities->is_empty() && cond_equalities != new_equalities)
{
Item_equal *equal_item;
@@ -14735,7 +14752,7 @@ void propagate_new_equalities(THD *thd, Item *cond,
while ((item= li++))
{
COND_EQUAL *new_inherited= and_level && item->type() == Item::COND_ITEM ?
- &((Item_cond_and *) cond)->cond_equal :
+ &((Item_cond_and *) cond)->m_cond_equal :
inherited;
propagate_new_equalities(thd, item, new_equalities, new_inherited,
is_simplifiable_cond);
@@ -14920,7 +14937,7 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
So it's easier to do it at one pass through the list of the equalities.
*/
List<Item_equal> *cond_equalities=
- &((Item_cond_and *) cond)->cond_equal.current_level;
+ &((Item_cond_and *) cond)->m_cond_equal.current_level;
cond_arg_list->disjoin((List<Item> *) cond_equalities);
List_iterator<Item_equal> it(*cond_equalities);
Item_equal *eq_item;
@@ -14976,7 +14993,7 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
of cond_arg_list.
*/
List<Item_equal> *new_item_equalities=
- &((Item_cond_and *) new_item)->cond_equal.current_level;
+ &((Item_cond_and *) new_item)->m_cond_equal.current_level;
if (!new_item_equalities->is_empty())
{
/*
@@ -15062,7 +15079,7 @@ internal_remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
These multiple equalities are to be merged into the
multiple equalities of cond_arg_list.
*/
- COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->cond_equal;
+ COND_EQUAL *cond_equal= &((Item_cond_and *) cond)->m_cond_equal;
List<Item_equal> *cond_equalities= &cond_equal->current_level;
cond_arg_list->disjoin((List<Item> *) cond_equalities);
Item_equal *equality;