mirror of
https://github.com/MariaDB/server.git
synced 2025-08-09 22:24:09 +03:00
MDEV-7950 Item_func::type() takes 0.26% in OLTP RO
Step#2: 1. Removes the function build_equal_items_for_cond() and introduces a new method Item::build_equal_items() instead, with specific implementations in the following Items: Item (the default implementation) Item_ident_or_func_or_sum Item_cond Item_cond_and 2. Adds a new abstract class Item_ident_or_func_or_sum, a common parent for Item_ident and Item_func_or_sum, as they have exactly the same build_equal_items(). 3. Renames Item_cond_and::cond_equal to Item_cond_and::m_cond_equal, to avoid confusion between the member and local variables named "cond_equal".
This commit is contained in:
@@ -734,7 +734,7 @@ Item_ident::Item_ident(TABLE_LIST *view_arg, const char *field_name_arg)
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Item_ident::Item_ident(THD *thd, Item_ident *item)
|
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_db_name(item->orig_db_name),
|
||||||
orig_table_name(item->orig_table_name),
|
orig_table_name(item->orig_table_name),
|
||||||
orig_field_name(item->orig_field_name),
|
orig_field_name(item->orig_field_name),
|
||||||
|
43
sql/item.h
43
sql/item.h
@@ -1127,6 +1127,12 @@ public:
|
|||||||
void print_item_w_name(String *, enum_query_type query_type);
|
void print_item_w_name(String *, enum_query_type query_type);
|
||||||
void print_value(String *);
|
void print_value(String *);
|
||||||
virtual void update_used_tables() {}
|
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,
|
virtual void split_sum_func(THD *thd, Item **ref_pointer_array,
|
||||||
List<Item> &fields) {}
|
List<Item> &fields) {}
|
||||||
/* Called for items that really have to be split */
|
/* Called for items that really have to be split */
|
||||||
@@ -2128,7 +2134,19 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
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:
|
protected:
|
||||||
/*
|
/*
|
||||||
@@ -3441,25 +3459,20 @@ public:
|
|||||||
An abstract class representing common features of
|
An abstract class representing common features of
|
||||||
regular functions and aggregate functions.
|
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:
|
public:
|
||||||
Item_func_or_sum()
|
Item_func_or_sum() :Item_args() {}
|
||||||
:Item_result_field(), Item_args() {}
|
Item_func_or_sum(Item *a) :Item_args(a) { }
|
||||||
Item_func_or_sum(Item *a)
|
Item_func_or_sum(Item *a, Item *b) :Item_args(a, b) { }
|
||||||
:Item_result_field(), Item_args(a) { }
|
Item_func_or_sum(Item *a, Item *b, Item *c) :Item_args(a, b, c) { }
|
||||||
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 *a, Item *b, Item *c, Item *d)
|
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_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_func_or_sum(THD *thd, Item_func_or_sum *item)
|
||||||
:Item_result_field(thd, item), Item_args(thd, item) { }
|
:Item_ident_or_func_or_sum(thd, item), Item_args(thd, item) { }
|
||||||
Item_func_or_sum(List<Item> &list)
|
Item_func_or_sum(List<Item> &list) :Item_args(list) { }
|
||||||
:Item_result_field(), Item_args(list) { }
|
|
||||||
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
|
bool walk(Item_processor processor, bool walk_subquery, uchar *arg)
|
||||||
{
|
{
|
||||||
if (walk_args(processor, walk_subquery, arg))
|
if (walk_args(processor, walk_subquery, arg))
|
||||||
|
@@ -1768,6 +1768,8 @@ public:
|
|||||||
used_tables_and_const_cache_init();
|
used_tables_and_const_cache_init();
|
||||||
used_tables_and_const_cache_update_and_join(list);
|
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);
|
virtual void print(String *str, enum_query_type query_type);
|
||||||
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
|
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,
|
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||||
@@ -2078,9 +2080,9 @@ public:
|
|||||||
class Item_cond_and :public Item_cond
|
class Item_cond_and :public Item_cond
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
COND_EQUAL cond_equal; /* contains list of Item_equal objects for
|
COND_EQUAL m_cond_equal; /* contains list of Item_equal objects for
|
||||||
the current and level and reference
|
the current and level and reference
|
||||||
to multiple equalities of upper and levels */
|
to multiple equalities of upper and levels */
|
||||||
Item_cond_and() :Item_cond() {}
|
Item_cond_and() :Item_cond() {}
|
||||||
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
|
Item_cond_and(Item *i1,Item *i2) :Item_cond(i1,i2) {}
|
||||||
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
|
Item_cond_and(THD *thd, Item_cond_and *item) :Item_cond(thd, item) {}
|
||||||
@@ -2101,6 +2103,8 @@ public:
|
|||||||
void mark_as_condition_AND_part(TABLE_LIST *embedding);
|
void mark_as_condition_AND_part(TABLE_LIST *embedding);
|
||||||
virtual uint exists2in_reserved_items() { return list.elements; };
|
virtual uint exists2in_reserved_items() { return list.elements; };
|
||||||
bool walk_top_and(Item_processor processor, uchar *arg);
|
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)
|
inline bool is_cond_and(Item *item)
|
||||||
|
@@ -3865,7 +3865,7 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
|
|||||||
conds= remove_eq_conds(join->thd, conds, &join->cond_value);
|
conds= remove_eq_conds(join->thd, conds, &join->cond_value);
|
||||||
if (conds && conds->type() == Item::COND_ITEM &&
|
if (conds && conds->type() == Item::COND_ITEM &&
|
||||||
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
|
((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;
|
join->select_lex->where= conds;
|
||||||
if (join->cond_value == Item::COND_FALSE)
|
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 &&
|
if (conds->type() == Item::COND_ITEM &&
|
||||||
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
|
((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 &&
|
else if (conds->type() == Item::FUNC_ITEM &&
|
||||||
((Item_func*) conds)->functype() == Item_func::MULT_EQUAL_FUNC)
|
((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_cond*) (join->conds))->functype() ==
|
||||||
Item_func::COND_AND_FUNC &&
|
Item_func::COND_AND_FUNC &&
|
||||||
join->cond_equal ==
|
join->cond_equal ==
|
||||||
&((Item_cond_and *) (join->conds))->cond_equal) ||
|
&((Item_cond_and *) (join->conds))->m_cond_equal) ||
|
||||||
(join->conds->type() == Item::FUNC_ITEM &&
|
(join->conds->type() == Item::FUNC_ITEM &&
|
||||||
((Item_func*) (join->conds))->functype() ==
|
((Item_func*) (join->conds))->functype() ==
|
||||||
Item_func::MULT_EQUAL_FUNC &&
|
Item_func::MULT_EQUAL_FUNC &&
|
||||||
@@ -12377,7 +12377,7 @@ finish:
|
|||||||
general case, its own constant for each fields from the multiple
|
general case, its own constant for each fields from the multiple
|
||||||
equality. But at the same time it would allow us to get rid
|
equality. But at the same time it would allow us to get rid
|
||||||
of constant propagation completely: it would be done by the call
|
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
|
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
|
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,
|
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.
|
all possible Item_equal objects in upper levels.
|
||||||
|
|
||||||
@param thd thread handle
|
@param thd thread handle
|
||||||
@param cond condition(expression) where to make replacement
|
|
||||||
@param inherited path to all inherited multiple equality items
|
@param inherited path to all inherited multiple equality items
|
||||||
|
|
||||||
@return
|
@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.
|
so no additional update_used_tables() is needed on the result.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static COND *build_equal_items_for_cond(THD *thd, COND *cond,
|
COND *Item_cond_and::build_equal_items(THD *thd,
|
||||||
COND_EQUAL *inherited,
|
COND_EQUAL *inherited,
|
||||||
bool link_item_fields)
|
bool link_item_fields)
|
||||||
{
|
{
|
||||||
Item_equal *item_equal;
|
Item_equal *item_equal;
|
||||||
COND_EQUAL cond_equal;
|
COND_EQUAL cond_equal;
|
||||||
cond_equal.upper_levels= inherited;
|
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;
|
PS/SP note: we can safely remove a node from AND-OR
|
||||||
bool and_level= cond_item->functype() == Item_func::COND_AND_FUNC;
|
structure here because it's restored before each
|
||||||
List<Item> *args= cond_item->argument_list();
|
re-execution of any prepared statement/stored procedure.
|
||||||
|
*/
|
||||||
List_iterator<Item> li(*args);
|
if (check_equality(thd, item, &cond_equal, &eq_list))
|
||||||
Item *item;
|
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
|
This is ok with PS/SP as the replacement is done for
|
||||||
that are subject to substitution by multiple equality items and
|
arguments of an AND/OR item, which are restored for each
|
||||||
removing each such predicate from the conjunction after having
|
execution of PS/SP.
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Check if we eliminated all the predicates of the level, e.g.
|
|
||||||
(a=a AND b=b AND a=a).
|
|
||||||
*/
|
*/
|
||||||
if (!args->elements &&
|
li.replace(new_item);
|
||||||
!cond_equal.current_level.elements &&
|
}
|
||||||
!eq_list.elements)
|
}
|
||||||
return new Item_int((longlong) 1, 1);
|
args->append(&eq_list);
|
||||||
|
args->append((List<Item> *)&cond_equal.current_level);
|
||||||
|
update_used_tables();
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
List_iterator_fast<Item_equal> it(cond_equal.current_level);
|
|
||||||
while ((item_equal= it++))
|
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 */
|
||||||
|
/*
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
used_tables_and_const_cache_join(new_item);
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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->fix_fields(thd, NULL);
|
||||||
item_equal->update_used_tables();
|
item_equal->update_used_tables();
|
||||||
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||||
item_equal->n_field_items());
|
item_equal->n_field_items());
|
||||||
|
item_equal->upper_levels= inherited;
|
||||||
|
return item_equal;
|
||||||
}
|
}
|
||||||
|
Item *res= eq_list.pop();
|
||||||
((Item_cond_and*)cond)->cond_equal.copy(cond_equal);
|
res->update_used_tables();
|
||||||
cond_equal.current_level=
|
return res;
|
||||||
((Item_cond_and*)cond)->cond_equal.current_level;
|
|
||||||
inherited= &(((Item_cond_and*)cond)->cond_equal);
|
|
||||||
}
|
}
|
||||||
/*
|
else
|
||||||
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);
|
|
||||||
}
|
|
||||||
if (and_level)
|
|
||||||
{
|
{
|
||||||
args->append(&eq_list);
|
/*
|
||||||
args->append((List<Item> *)&cond_equal.current_level);
|
Here a new AND level must be created. It can happen only
|
||||||
/*
|
when a row equality is processed as a standalone predicate.
|
||||||
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.
|
|
||||||
*/
|
*/
|
||||||
cond_item->update_used_tables();
|
Item_cond_and *and_cond= new Item_cond_and(eq_list);
|
||||||
}
|
and_cond->quick_fix_field();
|
||||||
return cond_item;
|
List<Item> *args= and_cond->argument_list();
|
||||||
}
|
List_iterator_fast<Item_equal> it(cond_equal.current_level);
|
||||||
else if (cond->type() == Item::FUNC_ITEM ||
|
while ((item_equal= it++))
|
||||||
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_length_and_dec();
|
||||||
{
|
item_equal->update_used_tables();
|
||||||
item_equal->fix_fields(thd, NULL);
|
set_if_bigger(thd->lex->current_select->max_equal_elems,
|
||||||
item_equal->update_used_tables();
|
item_equal->n_field_items());
|
||||||
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
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
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();
|
cond->update_used_tables();
|
||||||
return cond;
|
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
|
Build multiple equalities for a condition and all on expressions that
|
||||||
inherit these multiple equalities.
|
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
|
to build all multiple equalities for condition cond utilizing equalities
|
||||||
referred through the parameter inherited. The extended set of
|
referred through the parameter inherited. The extended set of
|
||||||
equalities is returned in the structure referred by the cond_equal_ref
|
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)
|
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 &&
|
if (cond->type() == Item::COND_ITEM &&
|
||||||
((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
|
((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 &&
|
else if (cond->type() == Item::FUNC_ITEM &&
|
||||||
((Item_cond*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
|
((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;
|
Item_func::COND_AND_FUNC;
|
||||||
if (and_level)
|
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. */
|
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);
|
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);
|
conds= remove_eq_conds(thd, conds, cond_value);
|
||||||
if (conds && conds->type() == Item::COND_ITEM &&
|
if (conds && conds->type() == Item::COND_ITEM &&
|
||||||
((Item_cond*) conds)->functype() == Item_func::COND_AND_FUNC)
|
((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_EXECUTE("info",print_where(conds,"after remove", QT_ORDINARY););
|
||||||
}
|
}
|
||||||
DBUG_RETURN(conds);
|
DBUG_RETURN(conds);
|
||||||
@@ -14708,8 +14725,8 @@ void propagate_new_equalities(THD *thd, Item *cond,
|
|||||||
if (and_level)
|
if (and_level)
|
||||||
{
|
{
|
||||||
Item_cond_and *cond_and= (Item_cond_and *) cond;
|
Item_cond_and *cond_and= (Item_cond_and *) cond;
|
||||||
List<Item_equal> *cond_equalities= &cond_and->cond_equal.current_level;
|
List<Item_equal> *cond_equalities= &cond_and->m_cond_equal.current_level;
|
||||||
cond_and->cond_equal.upper_levels= inherited;
|
cond_and->m_cond_equal.upper_levels= inherited;
|
||||||
if (!cond_equalities->is_empty() && cond_equalities != new_equalities)
|
if (!cond_equalities->is_empty() && cond_equalities != new_equalities)
|
||||||
{
|
{
|
||||||
Item_equal *equal_item;
|
Item_equal *equal_item;
|
||||||
@@ -14735,7 +14752,7 @@ void propagate_new_equalities(THD *thd, Item *cond,
|
|||||||
while ((item= li++))
|
while ((item= li++))
|
||||||
{
|
{
|
||||||
COND_EQUAL *new_inherited= and_level && item->type() == Item::COND_ITEM ?
|
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;
|
inherited;
|
||||||
propagate_new_equalities(thd, item, new_equalities, new_inherited,
|
propagate_new_equalities(thd, item, new_equalities, new_inherited,
|
||||||
is_simplifiable_cond);
|
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.
|
So it's easier to do it at one pass through the list of the equalities.
|
||||||
*/
|
*/
|
||||||
List<Item_equal> *cond_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);
|
cond_arg_list->disjoin((List<Item> *) cond_equalities);
|
||||||
List_iterator<Item_equal> it(*cond_equalities);
|
List_iterator<Item_equal> it(*cond_equalities);
|
||||||
Item_equal *eq_item;
|
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.
|
of cond_arg_list.
|
||||||
*/
|
*/
|
||||||
List<Item_equal> *new_item_equalities=
|
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())
|
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
|
These multiple equalities are to be merged into the
|
||||||
multiple equalities of cond_arg_list.
|
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;
|
List<Item_equal> *cond_equalities= &cond_equal->current_level;
|
||||||
cond_arg_list->disjoin((List<Item> *) cond_equalities);
|
cond_arg_list->disjoin((List<Item> *) cond_equalities);
|
||||||
Item_equal *equality;
|
Item_equal *equality;
|
||||||
|
Reference in New Issue
Block a user