• unknown's avatar
    Fix bug lp:833777 · f8dbbc01
    unknown authored
    Analysis:
    The optimizer distinguishes two kinds of 'constant' conditions:
    expensive ones, and non-expensive ones. The non-expensive conditions
    are evaluated inside make_join_select(), and if false, already the
    optimizer detects empty query results.
    
    In order to avoid arbitrarily expensive optimization, the evaluation of
    expensive constant conditions is delayed until execution. These conditions
    are attached to JOIN::exec_const_cond and evaluated in the beginning of
    JOIN::exec. The relevant execution logic is:
    
    JOIN::exec()
    {
      if (! join->exec_const_cond->val_int())
      {
        produce an empty result;
        stop execution
      }
      continue execution
      execute the original WHERE clause (that contains exec_const_cond)
     ...
    }
    
    As a result, when an expensive constant condition is
    TRUE, it is evaluated twice - once through
    JOIN::exec_const_cond, and once through JOIN::cond.
    When the expensive constant condition is a subquery,
    predicate, the subquery is evaluated twice. If we have
    many levels of subqueries, this logic results in a chain
    of recursive subquery executions that walk a perfect
    binary tree. The result is that for subquries with depth N,
    JOIN::exec is executed O(2^N) times.
    
    Solution:
    Notice that the second execution of the constant conditions
    happens inside do_select(), in the branch:
    if (join->table_count == join->const_tables) { ... }
    In this case exec_const_cond is equivalent to the whole WHERE
    clause, therefore the WHERE clause has already been checked in
    the beginnig of JOIN::exec, and has been found to be true.
    The bug is addressed by not evaluating the WHERE clause if there
    was exec_const_conds, and it was TRUE.
    f8dbbc01
subselect.result 189 KB