-
Roy Lyseng authored
We have a query block with 12 EXISTS subquery predicates that are candidates for semijoin transformation. All subqueries except one are proper candidates. The last one (number 8) is always false, and is thus removed from the sj_candidates array. All remaining subquery predicates are transformed to semi-join, except for one (number 11), which is not transformed due to having too many tables in its query block. While transforming subquery predicate number 2, it is detected that the full condition is always false (due to the already transformed always false subquery predicate), so the subquery that was not transformed is removed from sj_candidates. Thus, the size of sj_candidates is down to 10 elements, however, the pointer to the end sj_candidates (subq_end) is not updated, and thus we actually meet the last subquery predicate twice during semijoin transformation. The second time it is inspected, the contents of the subquery has been deleted and we try to traverse a pointer that has been reset. The fix to the problem is to stop deleting subquery predicates from sj_candidates within Item_subselect::clean_up_after_removal() and rather set a DELETED flag which can be checked in Query_block::flatten_subqueries(), thus avoiding objects being deleted under our feet. Another transformation status (DELETED) has been added. The transformation status ALWAYS_FALSE is deleted, since we can go directly to DELETED. Query_block::remove_semijoin_candidate() is replaced with a new virtual function Item::notify_removal(). Reviewed by: Chaithra Gopalareddy <chaithra.gopalareddy@oracle.com>
Roy Lyseng authoredWe have a query block with 12 EXISTS subquery predicates that are candidates for semijoin transformation. All subqueries except one are proper candidates. The last one (number 8) is always false, and is thus removed from the sj_candidates array. All remaining subquery predicates are transformed to semi-join, except for one (number 11), which is not transformed due to having too many tables in its query block. While transforming subquery predicate number 2, it is detected that the full condition is always false (due to the already transformed always false subquery predicate), so the subquery that was not transformed is removed from sj_candidates. Thus, the size of sj_candidates is down to 10 elements, however, the pointer to the end sj_candidates (subq_end) is not updated, and thus we actually meet the last subquery predicate twice during semijoin transformation. The second time it is inspected, the contents of the subquery has been deleted and we try to traverse a pointer that has been reset. The fix to the problem is to stop deleting subquery predicates from sj_candidates within Item_subselect::clean_up_after_removal() and rather set a DELETED flag which can be checked in Query_block::flatten_subqueries(), thus avoiding objects being deleted under our feet. Another transformation status (DELETED) has been added. The transformation status ALWAYS_FALSE is deleted, since we can go directly to DELETED. Query_block::remove_semijoin_candidate() is replaced with a new virtual function Item::notify_removal(). Reviewed by: Chaithra Gopalareddy <chaithra.gopalareddy@oracle.com>
Loading