-
unknown authored
Analysis: The fix for bug lp:985667 implements the method Item_subselect::no_rows_in_result() for all main kinds of subqueries. The purpose of this method is to be called from return_zero_rows() and set Items to some default value in the case when a query returns no rows. Aggregates and subqueries require special treatment in this case. Every implementation of Item_subselect::no_rows_in_result() called Item_subselect::make_const() to set the subquery predicate to its default value irrespective of where the predicate was located in the query. Once the predicate was set to a constant it was never executed. At the same time, the JOIN object of the fake select for UNIONs (the one used for the final result of the UNION), was set after all subqueries in the union were executed. Since we set the subquery as constant, it was never executed, and the corresponding JOIN was never created. In order to decide whether the result of NOT IN is NULL or FALSE, Item_in_optimizer needs to check if the subquery result was empty or not. This is where we got the crash, because subselect_union_engine::no_rows() checks for unit->fake_select_lex->join->send_records, and the join object was NULL. Solution: If a subquery is in the HAVING clause it must be evaluated in order to know its result, so that we can properly filter the result records. Once subqueries in the HAVING clause are executed even in the case of no result rows, this specific crash will be solved, because the UNION will be executed, and its JOIN will be constructed. Therefore the fix for this crash is to narrow the fix for lp:985667, and to apply Item_subselect::no_rows_in_result() only when the subquery predicate is in the SELECT clause.
db6dbadb