• Yuchen Pei's avatar
    MDEV-22534 Fix self-referencing Item_direct_view_ref · 5454f706
    Yuchen Pei authored
    The loop is created in substitute_for_best_equal_field().
    
    It calls Item_ref::transform (for the Item_direct_view_ref object)
    which calls:
    
      Item *new_item= (*ref)->transform(thd, transformer, arg); // TRANSFORM-CALL
    
    where transformer is Item::replace_equal_field().
    
    Consider *vr1->ref==field, where vr1 is an Item_direct_view_ref, and
    field is an Item_field that erroneously participates in a multiple
    equality. If field->replace_equal_field() returns vr2, another
    Item_direct_view_ref, with vr2->ref == vr1->ref. vr1->transform()
    will, after the call on field->transform() that returns vr2 for
    replacement, update its ref to point to vr2, so now *vr1->ref==vr2,
    and since vr2->ref==vr1->ref, this gives us *vr2->ref == vr2, a self
    reference.
    
    This can be generalised to nested Item_direct_view_refs too, if
    field->transform() returns an Item_direct_view_ref that has the same
    ref field as the ref field of any Item_direct_view_ref in the chain.
    
    On to the fix. If we maintain the rule that
    
      Objects inside Item_direct_view_ref do not participate in multiple
      equalities.
    
    then the TRANSFORM-CALL will have new_item == *ref. That is, the
    transform will be a no-op and no loop will be created.
    
    The participation of multiple equalities is set during call to
    Item::propagate_equal_fields(). This commit fixes
    Item_ref::propagate_equal_fields() so that the rule is not violated
    when a (non-Item_direct_view_ref) Item_ref points to an
    Item_direct_view_ref:
    
    Item_ref->Item_ref->...->Item_direct_view_ref->Item_direct_view_ref->...->Item_field
    
    More specifically, we now delegate to the dereferenced
    item (i.e. *ref) in such calls, rather than directly to the underlying
    Item_field. By doing this, the call to propagate_equal_fields() on
    toplevel Item_direct_view_ref will make it participate in the multiple
    equality, instead of any of its downstream items.
    5454f706
item_subselect.cc 212 KB