• Tom Lane's avatar
    Still more fixes for planner's handling of LATERAL references. · acfcd45c
    Tom Lane authored
    More fuzz testing by Andreas Seltenreich exposed that the planner did not
    cope well with chains of lateral references.  If relation X references Y
    laterally, and Y references Z laterally, then we will have to scan X on the
    inside of a nestloop with Z, so for all intents and purposes X is laterally
    dependent on Z too.  The planner did not understand this and would generate
    intermediate joins that could not be used.  While that was usually harmless
    except for wasting some planning cycles, under the right circumstances it
    would lead to "failed to build any N-way joins" or "could not devise a
    query plan" planner failures.
    
    To fix that, convert the existing per-relation lateral_relids and
    lateral_referencers relid sets into their transitive closures; that is,
    they now show all relations on which a rel is directly or indirectly
    laterally dependent.  This not only fixes the chained-reference problem
    but allows some of the relevant tests to be made substantially simpler
    and faster, since they can be reduced to simple bitmap manipulations
    instead of searches of the LateralJoinInfo list.
    
    Also, when a PlaceHolderVar that is due to be evaluated at a join contains
    lateral references, we should treat those references as indirect lateral
    dependencies of each of the join's base relations.  This prevents us from
    trying to join any individual base relations to the lateral reference
    source before the join is formed, which again cannot work.
    
    Andreas' testing also exposed another oversight in the "dangerous
    PlaceHolderVar" test added in commit 85e5e222.  Simply rejecting
    unsafe join paths in joinpath.c is insufficient, because in some cases
    we will end up rejecting *all* possible paths for a particular join, again
    leading to "could not devise a query plan" failures.  The restriction has
    to be known also to join_is_legal and its cohort functions, so that they
    will not select a join for which that will happen.  I chose to move the
    supporting logic into joinrels.c where the latter functions are.
    
    Back-patch to 9.3 where LATERAL support was introduced.
    acfcd45c
pathnode.h 6.17 KB