• unknown's avatar
    Fix bug lp:1008686 · db6dbadb
    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
subselect.result 206 KB