Skip to content
  • Roy Lyseng's avatar
    46111b35
    Bug#22176604: Wrong result on outer join with uncorrelated subquery, derived · 46111b35
    Roy Lyseng authored
    The problem may occur when we have a derived table that is used on
    the inner side of an outer join. The value of a column selected from
    such derived table is NULL if the outer join is null-complemented.
    We attempt to indicate this by pointing to the first table of the
    derived table and see if its null_row property is true. This strategy
    works fine for derived tables with a single table in it, but it may
    fail for multiple tables: A derived table which itself is an outer join
    may have tables with null_row = true, even though the derived table
    does produce a row (with null extension from the second table), or
    the tables are accessed in different order due to plan selection.
    
    It is the second case above that occurs here. The derived table is on
    the form t2 JOIN t3, but the plan is t3 - t2. In the regular case,
    this works. But sometimes when we have already completed a null
    extension for the same tables, the null_row property is on for a table,
    even though we have not yet checked the new rows.
    
    The solution to the problem is to reset the null_row property for
    a table just before returning from
    evaluate_null_complemented_join_record() after calling
    evaluate_join_record(). That way, the null_row property is always
    correct (it can only be true when we positively know that we
    have a null-extension for the inner tables of the outer join).
    
    As part of the fix, mark_as_null_row(TABLE *) is converted to a
    member function for struct TABLE and renamed to set_null_row().
    A corresponding function TABLE::reset_null_row() is also added, as well
    as a propery function TABLE::has_null_row().
    
    However, TABLE::null_row is still not made private. Some functions
    may take the address of this field, and we did not want to tamper
    with this property now.
    
    Join buffering is changed similarly: A call to TABLE::reset_null_row()
    is added in JOIN_CACHE::join_null_complements() just after calling
    generate_full_extensions(). However, no test case has been crafted
    to exercise this change.
    46111b35
    Bug#22176604: Wrong result on outer join with uncorrelated subquery, derived
    Roy Lyseng authored
    The problem may occur when we have a derived table that is used on
    the inner side of an outer join. The value of a column selected from
    such derived table is NULL if the outer join is null-complemented.
    We attempt to indicate this by pointing to the first table of the
    derived table and see if its null_row property is true. This strategy
    works fine for derived tables with a single table in it, but it may
    fail for multiple tables: A derived table which itself is an outer join
    may have tables with null_row = true, even though the derived table
    does produce a row (with null extension from the second table), or
    the tables are accessed in different order due to plan selection.
    
    It is the second case above that occurs here. The derived table is on
    the form t2 JOIN t3, but the plan is t3 - t2. In the regular case,
    this works. But sometimes when we have already completed a null
    extension for the same tables, the null_row property is on for a table,
    even though we have not yet checked the new rows.
    
    The solution to the problem is to reset the null_row property for
    a table just before returning from
    evaluate_null_complemented_join_record() after calling
    evaluate_join_record(). That way, the null_row property is always
    correct (it can only be true when we positively know that we
    have a null-extension for the inner tables of the outer join).
    
    As part of the fix, mark_as_null_row(TABLE *) is converted to a
    member function for struct TABLE and renamed to set_null_row().
    A corresponding function TABLE::reset_null_row() is also added, as well
    as a propery function TABLE::has_null_row().
    
    However, TABLE::null_row is still not made private. Some functions
    may take the address of this field, and we did not want to tamper
    with this property now.
    
    Join buffering is changed similarly: A call to TABLE::reset_null_row()
    is added in JOIN_CACHE::join_null_complements() just after calling
    generate_full_extensions(). However, no test case has been crafted
    to exercise this change.
Loading