• unknown's avatar
    Fix LP BUG#718593 · 0f423665
    unknown authored
    Analysis:
    Build_equal_items_for_cond() rewrites the WHERE clause in such a way,
    that it may merge the list join->cond_equal->current_level with the
    list of child Items in an AND condition of the WHERE clause.
    
    The place where this is done is:
    static COND *build_equal_items_for_cond(THD *thd, COND *cond,
                                            COND_EQUAL *inherited)
    {
      ...
          if (and_level)
        {
          args->concat(&eq_list);
          args->concat((List<Item> *)&cond_equal.current_level);
        }
      ...
    }
    
    As a result, later transformations on the WHERE clause may change the
    structure of the list join->cond_equal->current_level without knowing this.
    
    Specifically in this bug, Item_in_subselect::inject_in_to_exists_cond
    creates a new AND of the old WHERE clause and the IN->EXISTS conditions.
    It then calls fix_fields() for the new AND. Among other things, fix_fields
    flattens all nested ANDs into one by merging the AND argument lists.
    
    When there is a cond_equal for the JOIN, its list of Item_equal objects
    is attached to the end of the original AND. When a lower-level AND is
    merged into the top-level one, the argument list of the lower-level AND
    is concatenated to the list of multiple equalities in the upper-level AND.
    
    As a result, when substitute_for_best_equal_field processes the 
    multiple equalities, it turns out that the multiple equality list contains
    the Items from the lower-level AND which were concatenated to the end of
    the join->cond_equal->current_level list. This results in a crash because
    this list must not contain any other Items except for the previously found
    Item_equal ones.
    
    Solution:
    When performing IN->EXIST predicate injection, and the where clause is an
    AND, detach the list of Item_equal objects before calling fix_fields on
    the injected where clause.
    
    After fix_fields is done, reattach back the multiple equalities list to
    the end of the argument list of the new AND.
    0f423665
sql_list.h 17.7 KB