← Back to team overview

maria-developers team mailing list archive

Re: MDEV-7950 Item_func::type() takes 0.26% in OLTP RO

 

Hi Alexander,

this looks very good. I failed to understand just one thing:
why in Item_cond_and::build_equal_items() there're no calls to
used_tables_and_const_cache_init/used_tables_and_const_cache_join
like in Item_cond::build_equal_items? They were also present in
original code.

Regards,
Sergey

On Thu, Apr 23, 2015 at 07:17:50PM +0400, Alexander Barkov wrote:
> Hi Sergey,
> 
> Can you please review the "step 2" part of MDEV-7950?
> 
> This is rather a mechanical cut-and-paste change.
> 
> It does the following things:
> 
> 
> 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".
> 
> 
> 
> The main purpose of this patch is to prepare to the next
> step in MDEV-7950. But it already improves performance per se:
> it gets rid of some virtual calls:
> 
> 
> 
> - The former call for "((Item_cond*) cond)->functype()" is not
> needed any more, because Item_cond and Item_cond_and now have different
> implementations of the method build_equal_items().
> 
> 
> - This condition:
>   "else if (cond->type() == Item::FUNC_ITEM ||
>             cond->real_item()->type() == Item::FIELD_ITEM)"
> 
> 
> (which used to cover Item_func, Item_ident and Item_ref)
> consisted of three virtual calls.
> 
> It's now replaced by a single virtual call for
> Item_ident_or_func_or_sum::build_equal_items(),
> which covers all three item types.
> 
> 
> Thanks.

> 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;



Follow ups

References