-
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.
Roy Lyseng authoredThe 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