LCOV - code coverage report
Current view: top level - src/backend/optimizer/path - joinpath.c (source / functions) Hit Total Coverage
Test: PostgreSQL 19devel Lines: 522 535 97.6 %
Date: 2026-02-07 16:18:03 Functions: 18 18 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * joinpath.c
       4             :  *    Routines to find all possible paths for processing a set of joins
       5             :  *
       6             :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/optimizer/path/joinpath.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "executor/executor.h"
      18             : #include "foreign/fdwapi.h"
      19             : #include "nodes/nodeFuncs.h"
      20             : #include "optimizer/cost.h"
      21             : #include "optimizer/optimizer.h"
      22             : #include "optimizer/pathnode.h"
      23             : #include "optimizer/paths.h"
      24             : #include "optimizer/placeholder.h"
      25             : #include "optimizer/planmain.h"
      26             : #include "optimizer/restrictinfo.h"
      27             : #include "utils/lsyscache.h"
      28             : #include "utils/typcache.h"
      29             : 
      30             : /* Hooks for plugins to get control in add_paths_to_joinrel() */
      31             : set_join_pathlist_hook_type set_join_pathlist_hook = NULL;
      32             : join_path_setup_hook_type join_path_setup_hook = NULL;
      33             : 
      34             : /*
      35             :  * Paths parameterized by a parent rel can be considered to be parameterized
      36             :  * by any of its children, when we are performing partitionwise joins.  These
      37             :  * macros simplify checking for such cases.  Beware multiple eval of args.
      38             :  */
      39             : #define PATH_PARAM_BY_PARENT(path, rel) \
      40             :     ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), \
      41             :                                        (rel)->top_parent_relids))
      42             : #define PATH_PARAM_BY_REL_SELF(path, rel)  \
      43             :     ((path)->param_info && bms_overlap(PATH_REQ_OUTER(path), (rel)->relids))
      44             : 
      45             : #define PATH_PARAM_BY_REL(path, rel)    \
      46             :     (PATH_PARAM_BY_REL_SELF(path, rel) || PATH_PARAM_BY_PARENT(path, rel))
      47             : 
      48             : static void try_partial_mergejoin_path(PlannerInfo *root,
      49             :                                        RelOptInfo *joinrel,
      50             :                                        Path *outer_path,
      51             :                                        Path *inner_path,
      52             :                                        List *pathkeys,
      53             :                                        List *mergeclauses,
      54             :                                        List *outersortkeys,
      55             :                                        List *innersortkeys,
      56             :                                        JoinType jointype,
      57             :                                        JoinPathExtraData *extra);
      58             : static void sort_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
      59             :                                  RelOptInfo *outerrel, RelOptInfo *innerrel,
      60             :                                  JoinType jointype, JoinPathExtraData *extra);
      61             : static void match_unsorted_outer(PlannerInfo *root, RelOptInfo *joinrel,
      62             :                                  RelOptInfo *outerrel, RelOptInfo *innerrel,
      63             :                                  JoinType jointype, JoinPathExtraData *extra);
      64             : static void consider_parallel_nestloop(PlannerInfo *root,
      65             :                                        RelOptInfo *joinrel,
      66             :                                        RelOptInfo *outerrel,
      67             :                                        RelOptInfo *innerrel,
      68             :                                        JoinType jointype,
      69             :                                        JoinPathExtraData *extra);
      70             : static void consider_parallel_mergejoin(PlannerInfo *root,
      71             :                                         RelOptInfo *joinrel,
      72             :                                         RelOptInfo *outerrel,
      73             :                                         RelOptInfo *innerrel,
      74             :                                         JoinType jointype,
      75             :                                         JoinPathExtraData *extra,
      76             :                                         Path *inner_cheapest_total);
      77             : static void hash_inner_and_outer(PlannerInfo *root, RelOptInfo *joinrel,
      78             :                                  RelOptInfo *outerrel, RelOptInfo *innerrel,
      79             :                                  JoinType jointype, JoinPathExtraData *extra);
      80             : static List *select_mergejoin_clauses(PlannerInfo *root,
      81             :                                       RelOptInfo *joinrel,
      82             :                                       RelOptInfo *outerrel,
      83             :                                       RelOptInfo *innerrel,
      84             :                                       List *restrictlist,
      85             :                                       JoinType jointype,
      86             :                                       bool *mergejoin_allowed);
      87             : static void generate_mergejoin_paths(PlannerInfo *root,
      88             :                                      RelOptInfo *joinrel,
      89             :                                      RelOptInfo *innerrel,
      90             :                                      Path *outerpath,
      91             :                                      JoinType jointype,
      92             :                                      JoinPathExtraData *extra,
      93             :                                      bool useallclauses,
      94             :                                      Path *inner_cheapest_total,
      95             :                                      List *merge_pathkeys,
      96             :                                      bool is_partial);
      97             : 
      98             : 
      99             : /*
     100             :  * add_paths_to_joinrel
     101             :  *    Given a join relation and two component rels from which it can be made,
     102             :  *    consider all possible paths that use the two component rels as outer
     103             :  *    and inner rel respectively.  Add these paths to the join rel's pathlist
     104             :  *    if they survive comparison with other paths (and remove any existing
     105             :  *    paths that are dominated by these paths).
     106             :  *
     107             :  * Modifies the pathlist field of the joinrel node to contain the best
     108             :  * paths found so far.
     109             :  *
     110             :  * jointype is not necessarily the same as sjinfo->jointype; it might be
     111             :  * "flipped around" if we are considering joining the rels in the opposite
     112             :  * direction from what's indicated in sjinfo.
     113             :  *
     114             :  * Also, this routine accepts the special JoinTypes JOIN_UNIQUE_OUTER and
     115             :  * JOIN_UNIQUE_INNER to indicate that the outer or inner relation has been
     116             :  * unique-ified and a regular inner join should then be applied.  These values
     117             :  * are not allowed to propagate outside this routine, however.  Path cost
     118             :  * estimation code, as well as match_unsorted_outer, may need to recognize that
     119             :  * it's dealing with such a case --- the combination of nominal jointype INNER
     120             :  * with sjinfo->jointype == JOIN_SEMI indicates that.
     121             :  */
     122             : void
     123      781440 : add_paths_to_joinrel(PlannerInfo *root,
     124             :                      RelOptInfo *joinrel,
     125             :                      RelOptInfo *outerrel,
     126             :                      RelOptInfo *innerrel,
     127             :                      JoinType jointype,
     128             :                      SpecialJoinInfo *sjinfo,
     129             :                      List *restrictlist)
     130             : {
     131      781440 :     JoinType    save_jointype = jointype;
     132             :     JoinPathExtraData extra;
     133      781440 :     bool        mergejoin_allowed = true;
     134             :     ListCell   *lc;
     135             :     Relids      joinrelids;
     136             : 
     137             :     /*
     138             :      * PlannerInfo doesn't contain the SpecialJoinInfos created for joins
     139             :      * between child relations, even if there is a SpecialJoinInfo node for
     140             :      * the join between the topmost parents. So, while calculating Relids set
     141             :      * representing the restriction, consider relids of topmost parent of
     142             :      * partitions.
     143             :      */
     144      781440 :     if (joinrel->reloptkind == RELOPT_OTHER_JOINREL)
     145       64948 :         joinrelids = joinrel->top_parent_relids;
     146             :     else
     147      716492 :         joinrelids = joinrel->relids;
     148             : 
     149      781440 :     extra.restrictlist = restrictlist;
     150      781440 :     extra.mergeclause_list = NIL;
     151      781440 :     extra.sjinfo = sjinfo;
     152      781440 :     extra.param_source_rels = NULL;
     153      781440 :     extra.pgs_mask = joinrel->pgs_mask;
     154             : 
     155             :     /*
     156             :      * Give extensions a chance to take control. In particular, an extension
     157             :      * might want to modify extra.pgs_mask. It's possible to override pgs_mask
     158             :      * on a query-wide basis using join_search_hook, or for a particular
     159             :      * relation using joinrel_setup_hook, but extensions that want to provide
     160             :      * different advice for the same joinrel based on the choice of innerrel
     161             :      * and outerrel will need to use this hook.
     162             :      *
     163             :      * A very simple way for an extension to use this hook is to set
     164             :      * extra.pgs_mask &= ~PGS_JOIN_ANY, if it simply doesn't want any of the
     165             :      * paths generated by this call to add_paths_to_joinrel() to be selected.
     166             :      * An extension could use this technique to constrain the join order,
     167             :      * since it could thereby arrange to reject all paths from join orders
     168             :      * that it does not like. An extension can also selectively clear bits
     169             :      * from extra.pgs_mask to rule out specific techniques for specific joins,
     170             :      * or could even set additional bits to re-allow methods disabled at some
     171             :      * higher level.
     172             :      *
     173             :      * NB: Below this point, this function should be careful to reference
     174             :      * extra.pgs_mask rather than rel->pgs_mask to avoid disregarding any
     175             :      * changes made by the hook we're about to call.
     176             :      */
     177      781440 :     if (join_path_setup_hook)
     178           0 :         join_path_setup_hook(root, joinrel, outerrel, innerrel,
     179             :                              jointype, &extra);
     180             : 
     181             :     /*
     182             :      * See if the inner relation is provably unique for this outer rel.
     183             :      *
     184             :      * We have some special cases: for JOIN_SEMI, it doesn't matter since the
     185             :      * executor can make the equivalent optimization anyway.  It also doesn't
     186             :      * help enable use of Memoize, since a semijoin with a provably unique
     187             :      * inner side should have been reduced to an inner join in that case.
     188             :      * Therefore, we need not expend planner cycles on proofs.  (For
     189             :      * JOIN_ANTI, although it doesn't help the executor for the same reason,
     190             :      * it can benefit Memoize paths.)  For JOIN_UNIQUE_INNER, we must be
     191             :      * considering a semijoin whose inner side is not provably unique (else
     192             :      * reduce_unique_semijoins would've simplified it), so there's no point in
     193             :      * calling innerrel_is_unique.  However, if the LHS covers all of the
     194             :      * semijoin's min_lefthand, then it's appropriate to set inner_unique
     195             :      * because the unique relation produced by create_unique_paths will be
     196             :      * unique relative to the LHS.  (If we have an LHS that's only part of the
     197             :      * min_lefthand, that is *not* true.)  For JOIN_UNIQUE_OUTER, pass
     198             :      * JOIN_INNER to avoid letting that value escape this module.
     199             :      */
     200      781440 :     switch (jointype)
     201             :     {
     202        7652 :         case JOIN_SEMI:
     203        7652 :             extra.inner_unique = false; /* well, unproven */
     204        7652 :             break;
     205        6336 :         case JOIN_UNIQUE_INNER:
     206       12672 :             extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
     207        6336 :                                                outerrel->relids);
     208        6336 :             break;
     209        6336 :         case JOIN_UNIQUE_OUTER:
     210        6336 :             extra.inner_unique = innerrel_is_unique(root,
     211             :                                                     joinrel->relids,
     212             :                                                     outerrel->relids,
     213             :                                                     innerrel,
     214             :                                                     JOIN_INNER,
     215             :                                                     restrictlist,
     216             :                                                     false);
     217        6336 :             break;
     218      761116 :         default:
     219      761116 :             extra.inner_unique = innerrel_is_unique(root,
     220             :                                                     joinrel->relids,
     221             :                                                     outerrel->relids,
     222             :                                                     innerrel,
     223             :                                                     jointype,
     224             :                                                     restrictlist,
     225             :                                                     false);
     226      761116 :             break;
     227             :     }
     228             : 
     229             :     /*
     230             :      * If the outer or inner relation has been unique-ified, handle as a plain
     231             :      * inner join.
     232             :      */
     233      781440 :     if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
     234       12672 :         jointype = JOIN_INNER;
     235             : 
     236             :     /*
     237             :      * Find potential mergejoin clauses.  We can skip this if we are not
     238             :      * interested in doing a mergejoin.  However, mergejoin may be our only
     239             :      * way of implementing a full outer join, so in that case we don't care
     240             :      * whether mergejoins are disabled.
     241             :      */
     242      781440 :     if ((extra.pgs_mask & PGS_MERGEJOIN_ANY) != 0 || jointype == JOIN_FULL)
     243      777496 :         extra.mergeclause_list = select_mergejoin_clauses(root,
     244             :                                                           joinrel,
     245             :                                                           outerrel,
     246             :                                                           innerrel,
     247             :                                                           restrictlist,
     248             :                                                           jointype,
     249             :                                                           &mergejoin_allowed);
     250             : 
     251             :     /*
     252             :      * If it's SEMI, ANTI, or inner_unique join, compute correction factors
     253             :      * for cost estimation.  These will be the same for all paths.
     254             :      */
     255      781440 :     if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique)
     256      223956 :         compute_semi_anti_join_factors(root, joinrel, outerrel, innerrel,
     257             :                                        jointype, sjinfo, restrictlist,
     258             :                                        &extra.semifactors);
     259             : 
     260             :     /*
     261             :      * Decide whether it's sensible to generate parameterized paths for this
     262             :      * joinrel, and if so, which relations such paths should require.  There
     263             :      * is usually no need to create a parameterized result path unless there
     264             :      * is a join order restriction that prevents joining one of our input rels
     265             :      * directly to the parameter source rel instead of joining to the other
     266             :      * input rel.  (But see allow_star_schema_join().)  This restriction
     267             :      * reduces the number of parameterized paths we have to deal with at
     268             :      * higher join levels, without compromising the quality of the resulting
     269             :      * plan.  We express the restriction as a Relids set that must overlap the
     270             :      * parameterization of any proposed join path.  Note: param_source_rels
     271             :      * should contain only baserels, not OJ relids, so starting from
     272             :      * all_baserels not all_query_rels is correct.
     273             :      */
     274     1519444 :     foreach(lc, root->join_info_list)
     275             :     {
     276      738004 :         SpecialJoinInfo *sjinfo2 = (SpecialJoinInfo *) lfirst(lc);
     277             : 
     278             :         /*
     279             :          * SJ is relevant to this join if we have some part of its RHS
     280             :          * (possibly not all of it), and haven't yet joined to its LHS.  (This
     281             :          * test is pretty simplistic, but should be sufficient considering the
     282             :          * join has already been proven legal.)  If the SJ is relevant, it
     283             :          * presents constraints for joining to anything not in its RHS.
     284             :          */
     285      738004 :         if (bms_overlap(joinrelids, sjinfo2->min_righthand) &&
     286      489512 :             !bms_overlap(joinrelids, sjinfo2->min_lefthand))
     287       21936 :             extra.param_source_rels = bms_join(extra.param_source_rels,
     288       21936 :                                                bms_difference(root->all_baserels,
     289       21936 :                                                               sjinfo2->min_righthand));
     290             : 
     291             :         /* full joins constrain both sides symmetrically */
     292      742920 :         if (sjinfo2->jointype == JOIN_FULL &&
     293        4916 :             bms_overlap(joinrelids, sjinfo2->min_lefthand) &&
     294        4860 :             !bms_overlap(joinrelids, sjinfo2->min_righthand))
     295         672 :             extra.param_source_rels = bms_join(extra.param_source_rels,
     296         672 :                                                bms_difference(root->all_baserels,
     297         672 :                                                               sjinfo2->min_lefthand));
     298             :     }
     299             : 
     300             :     /*
     301             :      * However, when a LATERAL subquery is involved, there will simply not be
     302             :      * any paths for the joinrel that aren't parameterized by whatever the
     303             :      * subquery is parameterized by, unless its parameterization is resolved
     304             :      * within the joinrel.  So we might as well allow additional dependencies
     305             :      * on whatever residual lateral dependencies the joinrel will have.
     306             :      */
     307     1562880 :     extra.param_source_rels = bms_add_members(extra.param_source_rels,
     308      781440 :                                               joinrel->lateral_relids);
     309             : 
     310             :     /*
     311             :      * 1. Consider mergejoin paths where both relations must be explicitly
     312             :      * sorted.  Skip this if we can't mergejoin.
     313             :      */
     314      781440 :     if (mergejoin_allowed)
     315      763798 :         sort_inner_and_outer(root, joinrel, outerrel, innerrel,
     316             :                              jointype, &extra);
     317             : 
     318             :     /*
     319             :      * 2. Consider paths where the outer relation need not be explicitly
     320             :      * sorted. This includes both nestloops and mergejoins where the outer
     321             :      * path is already ordered.  Again, skip this if we can't mergejoin.
     322             :      * (That's okay because we know that nestloop can't handle
     323             :      * right/right-anti/right-semi/full joins at all, so it wouldn't work in
     324             :      * the prohibited cases either.)
     325             :      */
     326      781440 :     if (mergejoin_allowed)
     327      763798 :         match_unsorted_outer(root, joinrel, outerrel, innerrel,
     328             :                              jointype, &extra);
     329             : 
     330             : #ifdef NOT_USED
     331             : 
     332             :     /*
     333             :      * 3. Consider paths where the inner relation need not be explicitly
     334             :      * sorted.  This includes mergejoins only (nestloops were already built in
     335             :      * match_unsorted_outer).
     336             :      *
     337             :      * Diked out as redundant 2/13/2000 -- tgl.  There isn't any really
     338             :      * significant difference between the inner and outer side of a mergejoin,
     339             :      * so match_unsorted_inner creates no paths that aren't equivalent to
     340             :      * those made by match_unsorted_outer when add_paths_to_joinrel() is
     341             :      * invoked with the two rels given in the other order.
     342             :      */
     343             :     if (mergejoin_allowed)
     344             :         match_unsorted_inner(root, joinrel, outerrel, innerrel,
     345             :                              jointype, &extra);
     346             : #endif
     347             : 
     348             :     /*
     349             :      * 4. Consider paths where both outer and inner relations must be hashed
     350             :      * before being joined.  As above, when it's a full join, we must try this
     351             :      * even when the path type is disabled, because it may be our only option.
     352             :      */
     353      781440 :     if ((extra.pgs_mask & PGS_HASHJOIN) != 0 || jointype == JOIN_FULL)
     354      776096 :         hash_inner_and_outer(root, joinrel, outerrel, innerrel,
     355             :                              jointype, &extra);
     356             : 
     357             :     /*
     358             :      * 5. If inner and outer relations are foreign tables (or joins) belonging
     359             :      * to the same server and assigned to the same user to check access
     360             :      * permissions as, give the FDW a chance to push down joins.
     361             :      */
     362      781440 :     if ((extra.pgs_mask & PGS_FOREIGNJOIN) != 0 && joinrel->fdwroutine &&
     363        2724 :         joinrel->fdwroutine->GetForeignJoinPaths)
     364        2720 :         joinrel->fdwroutine->GetForeignJoinPaths(root, joinrel,
     365             :                                                  outerrel, innerrel,
     366             :                                                  save_jointype, &extra);
     367             : 
     368             :     /*
     369             :      * 6. Finally, give extensions a chance to manipulate the path list.  They
     370             :      * could add new paths (such as CustomPaths) by calling add_path(), or
     371             :      * add_partial_path() if parallel aware.
     372             :      *
     373             :      * In theory, extensions could also use this hook to delete or modify
     374             :      * paths added by the core code, but in practice this is difficult to make
     375             :      * work, since it's too late to get back any paths that have already been
     376             :      * discarded by add_path() or add_partial_path(). If you're trying to
     377             :      * suppress paths, consider using join_path_setup_hook instead.
     378             :      */
     379      781440 :     if (set_join_pathlist_hook)
     380           0 :         set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
     381             :                                save_jointype, &extra);
     382      781440 : }
     383             : 
     384             : /*
     385             :  * We override the param_source_rels heuristic to accept nestloop paths in
     386             :  * which the outer rel satisfies some but not all of the inner path's
     387             :  * parameterization.  This is necessary to get good plans for star-schema
     388             :  * scenarios, in which a parameterized path for a large table may require
     389             :  * parameters from multiple small tables that will not get joined directly to
     390             :  * each other.  We can handle that by stacking nestloops that have the small
     391             :  * tables on the outside; but this breaks the rule the param_source_rels
     392             :  * heuristic is based on, namely that parameters should not be passed down
     393             :  * across joins unless there's a join-order-constraint-based reason to do so.
     394             :  * So we ignore the param_source_rels restriction when this case applies.
     395             :  *
     396             :  * allow_star_schema_join() returns true if the param_source_rels restriction
     397             :  * should be overridden, ie, it's okay to perform this join.
     398             :  */
     399             : static inline bool
     400      324656 : allow_star_schema_join(PlannerInfo *root,
     401             :                        Relids outerrelids,
     402             :                        Relids inner_paramrels)
     403             : {
     404             :     /*
     405             :      * It's a star-schema case if the outer rel provides some but not all of
     406             :      * the inner rel's parameterization.
     407             :      */
     408      381334 :     return (bms_overlap(inner_paramrels, outerrelids) &&
     409       56678 :             bms_nonempty_difference(inner_paramrels, outerrelids));
     410             : }
     411             : 
     412             : /*
     413             :  * If the parameterization is only partly satisfied by the outer rel,
     414             :  * the unsatisfied part can't include any outer-join relids that could
     415             :  * null rels of the satisfied part.  That would imply that we're trying
     416             :  * to use a clause involving a Var with nonempty varnullingrels at
     417             :  * a join level where that value isn't yet computable.
     418             :  *
     419             :  * In practice, this test never finds a problem because earlier join order
     420             :  * restrictions prevent us from attempting a join that would cause a problem.
     421             :  * (That's unsurprising, because the code worked before we ever added
     422             :  * outer-join relids to expression relids.)  It still seems worth checking
     423             :  * as a backstop, but we only do so in assert-enabled builds.
     424             :  */
     425             : #ifdef USE_ASSERT_CHECKING
     426             : static inline bool
     427             : have_unsafe_outer_join_ref(PlannerInfo *root,
     428             :                            Relids outerrelids,
     429             :                            Relids inner_paramrels)
     430             : {
     431             :     bool        result = false;
     432             :     Relids      unsatisfied = bms_difference(inner_paramrels, outerrelids);
     433             :     Relids      satisfied = bms_intersect(inner_paramrels, outerrelids);
     434             : 
     435             :     if (bms_overlap(unsatisfied, root->outer_join_rels))
     436             :     {
     437             :         ListCell   *lc;
     438             : 
     439             :         foreach(lc, root->join_info_list)
     440             :         {
     441             :             SpecialJoinInfo *sjinfo = (SpecialJoinInfo *) lfirst(lc);
     442             : 
     443             :             if (!bms_is_member(sjinfo->ojrelid, unsatisfied))
     444             :                 continue;       /* not relevant */
     445             :             if (bms_overlap(satisfied, sjinfo->min_righthand) ||
     446             :                 (sjinfo->jointype == JOIN_FULL &&
     447             :                  bms_overlap(satisfied, sjinfo->min_lefthand)))
     448             :             {
     449             :                 result = true;  /* doesn't work */
     450             :                 break;
     451             :             }
     452             :         }
     453             :     }
     454             : 
     455             :     /* Waste no memory when we reject a path here */
     456             :     bms_free(unsatisfied);
     457             :     bms_free(satisfied);
     458             : 
     459             :     return result;
     460             : }
     461             : #endif                          /* USE_ASSERT_CHECKING */
     462             : 
     463             : /*
     464             :  * paraminfo_get_equal_hashops
     465             :  *      Determine if the clauses in param_info and innerrel's lateral vars
     466             :  *      can be hashed.
     467             :  *      Returns true if hashing is possible, otherwise false.
     468             :  *
     469             :  * Additionally, on success we collect the outer expressions and the
     470             :  * appropriate equality operators for each hashable parameter to innerrel.
     471             :  * These are returned in parallel lists in *param_exprs and *operators.
     472             :  * We also set *binary_mode to indicate whether strict binary matching is
     473             :  * required.
     474             :  */
     475             : static bool
     476      400834 : paraminfo_get_equal_hashops(PlannerInfo *root, ParamPathInfo *param_info,
     477             :                             RelOptInfo *outerrel, RelOptInfo *innerrel,
     478             :                             List *ph_lateral_vars, List **param_exprs,
     479             :                             List **operators, bool *binary_mode)
     480             : 
     481             : {
     482             :     List       *lateral_vars;
     483             :     ListCell   *lc;
     484             : 
     485      400834 :     *param_exprs = NIL;
     486      400834 :     *operators = NIL;
     487      400834 :     *binary_mode = false;
     488             : 
     489             :     /* Add join clauses from param_info to the hash key */
     490      400834 :     if (param_info != NULL)
     491             :     {
     492      400834 :         List       *clauses = param_info->ppi_clauses;
     493             : 
     494      756616 :         foreach(lc, clauses)
     495             :         {
     496      435932 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     497             :             OpExpr     *opexpr;
     498             :             Node       *expr;
     499             :             Oid         hasheqoperator;
     500             : 
     501      435932 :             opexpr = (OpExpr *) rinfo->clause;
     502             : 
     503             :             /*
     504             :              * Bail if the rinfo is not compatible.  We need a join OpExpr
     505             :              * with 2 args.
     506             :              */
     507      435932 :             if (!IsA(opexpr, OpExpr) || list_length(opexpr->args) != 2 ||
     508      418054 :                 !clause_sides_match_join(rinfo, outerrel->relids,
     509             :                                          innerrel->relids))
     510             :             {
     511       80060 :                 list_free(*operators);
     512       80060 :                 list_free(*param_exprs);
     513       80150 :                 return false;
     514             :             }
     515             : 
     516      355872 :             if (rinfo->outer_is_left)
     517             :             {
     518      197864 :                 expr = (Node *) linitial(opexpr->args);
     519      197864 :                 hasheqoperator = rinfo->left_hasheqoperator;
     520             :             }
     521             :             else
     522             :             {
     523      158008 :                 expr = (Node *) lsecond(opexpr->args);
     524      158008 :                 hasheqoperator = rinfo->right_hasheqoperator;
     525             :             }
     526             : 
     527             :             /* can't do memoize if we can't hash the outer type */
     528      355872 :             if (!OidIsValid(hasheqoperator))
     529             :             {
     530          90 :                 list_free(*operators);
     531          90 :                 list_free(*param_exprs);
     532          90 :                 return false;
     533             :             }
     534             : 
     535             :             /*
     536             :              * 'expr' may already exist as a parameter from a previous item in
     537             :              * ppi_clauses.  No need to include it again, however we'd better
     538             :              * ensure we do switch into binary mode if required.  See below.
     539             :              */
     540      355782 :             if (!list_member(*param_exprs, expr))
     541             :             {
     542      355776 :                 *operators = lappend_oid(*operators, hasheqoperator);
     543      355776 :                 *param_exprs = lappend(*param_exprs, expr);
     544             :             }
     545             : 
     546             :             /*
     547             :              * When the join operator is not hashable then it's possible that
     548             :              * the operator will be able to distinguish something that the
     549             :              * hash equality operator could not. For example with floating
     550             :              * point types -0.0 and +0.0 are classed as equal by the hash
     551             :              * function and equality function, but some other operator may be
     552             :              * able to tell those values apart.  This means that we must put
     553             :              * memoize into binary comparison mode so that it does bit-by-bit
     554             :              * comparisons rather than a "logical" comparison as it would
     555             :              * using the hash equality operator.
     556             :              */
     557      355782 :             if (!OidIsValid(rinfo->hashjoinoperator))
     558        1270 :                 *binary_mode = true;
     559             :         }
     560             :     }
     561             : 
     562             :     /* Now add any lateral vars to the cache key too */
     563      320684 :     lateral_vars = list_concat(ph_lateral_vars, innerrel->lateral_vars);
     564      328446 :     foreach(lc, lateral_vars)
     565             :     {
     566        7960 :         Node       *expr = (Node *) lfirst(lc);
     567             :         TypeCacheEntry *typentry;
     568             : 
     569             :         /* Reject if there are any volatile functions in lateral vars */
     570        7960 :         if (contain_volatile_functions(expr))
     571             :         {
     572           0 :             list_free(*operators);
     573           0 :             list_free(*param_exprs);
     574         198 :             return false;
     575             :         }
     576             : 
     577        7960 :         typentry = lookup_type_cache(exprType(expr),
     578             :                                      TYPECACHE_HASH_PROC | TYPECACHE_EQ_OPR);
     579             : 
     580             :         /* can't use memoize without a valid hash proc and equals operator */
     581        7960 :         if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
     582             :         {
     583         198 :             list_free(*operators);
     584         198 :             list_free(*param_exprs);
     585         198 :             return false;
     586             :         }
     587             : 
     588             :         /*
     589             :          * 'expr' may already exist as a parameter from the ppi_clauses.  No
     590             :          * need to include it again, however we'd better ensure we do switch
     591             :          * into binary mode.
     592             :          */
     593        7762 :         if (!list_member(*param_exprs, expr))
     594             :         {
     595        7264 :             *operators = lappend_oid(*operators, typentry->eq_opr);
     596        7264 :             *param_exprs = lappend(*param_exprs, expr);
     597             :         }
     598             : 
     599             :         /*
     600             :          * We must go into binary mode as we don't have too much of an idea of
     601             :          * how these lateral Vars are being used.  See comment above when we
     602             :          * set *binary_mode for the non-lateral Var case. This could be
     603             :          * relaxed a bit if we had the RestrictInfos and knew the operators
     604             :          * being used, however for cases like Vars that are arguments to
     605             :          * functions we must operate in binary mode as we don't have
     606             :          * visibility into what the function is doing with the Vars.
     607             :          */
     608        7762 :         *binary_mode = true;
     609             :     }
     610             : 
     611             :     /* We're okay to use memoize */
     612      320486 :     return true;
     613             : }
     614             : 
     615             : /*
     616             :  * extract_lateral_vars_from_PHVs
     617             :  *    Extract lateral references within PlaceHolderVars that are due to be
     618             :  *    evaluated at 'innerrelids'.
     619             :  */
     620             : static List *
     621     1496124 : extract_lateral_vars_from_PHVs(PlannerInfo *root, Relids innerrelids)
     622             : {
     623     1496124 :     List       *ph_lateral_vars = NIL;
     624             :     ListCell   *lc;
     625             : 
     626             :     /* Nothing would be found if the query contains no LATERAL RTEs */
     627     1496124 :     if (!root->hasLateralRTEs)
     628     1438510 :         return NIL;
     629             : 
     630             :     /*
     631             :      * No need to consider PHVs that are due to be evaluated at joinrels,
     632             :      * since we do not add Memoize nodes on top of joinrel paths.
     633             :      */
     634       57614 :     if (bms_membership(innerrelids) == BMS_MULTIPLE)
     635       22332 :         return NIL;
     636             : 
     637       38146 :     foreach(lc, root->placeholder_list)
     638             :     {
     639        2864 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
     640             :         List       *vars;
     641             :         ListCell   *cell;
     642             : 
     643             :         /* PHV is uninteresting if no lateral refs */
     644        2864 :         if (phinfo->ph_lateral == NULL)
     645        1638 :             continue;
     646             : 
     647             :         /* PHV is uninteresting if not due to be evaluated at innerrelids */
     648        1226 :         if (!bms_equal(phinfo->ph_eval_at, innerrelids))
     649         982 :             continue;
     650             : 
     651             :         /*
     652             :          * If the PHV does not reference any rels in innerrelids, use its
     653             :          * contained expression as a cache key rather than extracting the
     654             :          * Vars/PHVs from it and using those.  This can be beneficial in cases
     655             :          * where the expression results in fewer distinct values to cache
     656             :          * tuples for.
     657             :          */
     658         244 :         if (!bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr),
     659             :                          innerrelids))
     660             :         {
     661         232 :             ph_lateral_vars = lappend(ph_lateral_vars, phinfo->ph_var->phexpr);
     662         232 :             continue;
     663             :         }
     664             : 
     665             :         /* Fetch Vars and PHVs of lateral references within PlaceHolderVars */
     666          12 :         vars = pull_vars_of_level((Node *) phinfo->ph_var->phexpr, 0);
     667          36 :         foreach(cell, vars)
     668             :         {
     669          24 :             Node       *node = (Node *) lfirst(cell);
     670             : 
     671          24 :             if (IsA(node, Var))
     672             :             {
     673          12 :                 Var        *var = (Var *) node;
     674             : 
     675             :                 Assert(var->varlevelsup == 0);
     676             : 
     677          12 :                 if (bms_is_member(var->varno, phinfo->ph_lateral))
     678           0 :                     ph_lateral_vars = lappend(ph_lateral_vars, node);
     679             :             }
     680          12 :             else if (IsA(node, PlaceHolderVar))
     681             :             {
     682          12 :                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
     683             : 
     684             :                 Assert(phv->phlevelsup == 0);
     685             : 
     686          12 :                 if (bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
     687          12 :                                   phinfo->ph_lateral))
     688          12 :                     ph_lateral_vars = lappend(ph_lateral_vars, node);
     689             :             }
     690             :             else
     691             :                 Assert(false);
     692             :         }
     693             : 
     694          12 :         list_free(vars);
     695             :     }
     696             : 
     697       35282 :     return ph_lateral_vars;
     698             : }
     699             : 
     700             : /*
     701             :  * get_memoize_path
     702             :  *      If possible, make and return a Memoize path atop of 'inner_path'.
     703             :  *      Otherwise return NULL.
     704             :  *
     705             :  * Note that currently we do not add Memoize nodes on top of join relation
     706             :  * paths.  This is because the ParamPathInfos for join relation paths do not
     707             :  * maintain ppi_clauses, as the set of relevant clauses varies depending on how
     708             :  * the join is formed.  In addition, joinrels do not maintain lateral_vars.  So
     709             :  * we do not have a way to extract cache keys from joinrels.
     710             :  */
     711             : static Path *
     712     2102878 : get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel,
     713             :                  RelOptInfo *outerrel, Path *inner_path,
     714             :                  Path *outer_path, JoinType jointype,
     715             :                  JoinPathExtraData *extra)
     716             : {
     717             :     List       *param_exprs;
     718             :     List       *hash_operators;
     719             :     ListCell   *lc;
     720             :     bool        binary_mode;
     721             :     List       *ph_lateral_vars;
     722             : 
     723             :     /* Obviously not if it's disabled */
     724     2102878 :     if ((extra->pgs_mask & PGS_NESTLOOP_MEMOIZE) == 0)
     725        6412 :         return NULL;
     726             : 
     727             :     /*
     728             :      * We can safely not bother with all this unless we expect to perform more
     729             :      * than one inner scan.  The first scan is always going to be a cache
     730             :      * miss.  This would likely fail later anyway based on costs, so this is
     731             :      * really just to save some wasted effort.
     732             :      */
     733     2096466 :     if (outer_path->parent->rows < 2)
     734      600342 :         return NULL;
     735             : 
     736             :     /*
     737             :      * Extract lateral Vars/PHVs within PlaceHolderVars that are due to be
     738             :      * evaluated at innerrel.  These lateral Vars/PHVs could be used as
     739             :      * memoize cache keys.
     740             :      */
     741     1496124 :     ph_lateral_vars = extract_lateral_vars_from_PHVs(root, innerrel->relids);
     742             : 
     743             :     /*
     744             :      * We can only have a memoize node when there's some kind of cache key,
     745             :      * either parameterized path clauses or lateral Vars.  No cache key sounds
     746             :      * more like something a Materialize node might be more useful for.
     747             :      */
     748     1496124 :     if ((inner_path->param_info == NULL ||
     749      543688 :          inner_path->param_info->ppi_clauses == NIL) &&
     750      985666 :         innerrel->lateral_vars == NIL &&
     751             :         ph_lateral_vars == NIL)
     752      978552 :         return NULL;
     753             : 
     754             :     /*
     755             :      * Currently we don't do this for SEMI and ANTI joins, because nested loop
     756             :      * SEMI/ANTI joins don't scan the inner node to completion, which means
     757             :      * memoize cannot mark the cache entry as complete.  Nor can we mark the
     758             :      * cache entry as complete after fetching the first inner tuple, because
     759             :      * if that tuple and the current outer tuple don't satisfy the join
     760             :      * clauses, a second inner tuple that satisfies the parameters would find
     761             :      * the cache entry already marked as complete.  The only exception is when
     762             :      * the inner relation is provably unique, as in that case, there won't be
     763             :      * a second matching tuple and we can safely mark the cache entry as
     764             :      * complete after fetching the first inner tuple.  Note that in such
     765             :      * cases, the SEMI join should have been reduced to an inner join by
     766             :      * reduce_unique_semijoins.
     767             :      */
     768      517572 :     if ((jointype == JOIN_SEMI || jointype == JOIN_ANTI) &&
     769        9734 :         !extra->inner_unique)
     770        5942 :         return NULL;
     771             : 
     772             :     /*
     773             :      * Memoize normally marks cache entries as complete when it runs out of
     774             :      * tuples to read from its subplan.  However, with unique joins, Nested
     775             :      * Loop will skip to the next outer tuple after finding the first matching
     776             :      * inner tuple.  This means that we may not read the inner side of the
     777             :      * join to completion which leaves no opportunity to mark the cache entry
     778             :      * as complete.  To work around that, when the join is unique we
     779             :      * automatically mark cache entries as complete after fetching the first
     780             :      * tuple.  This works when the entire join condition is parameterized.
     781             :      * Otherwise, when the parameterization is only a subset of the join
     782             :      * condition, we can't be sure which part of it causes the join to be
     783             :      * unique.  This means there are no guarantees that only 1 tuple will be
     784             :      * read.  We cannot mark the cache entry as complete after reading the
     785             :      * first tuple without that guarantee.  This means the scope of Memoize
     786             :      * node's usefulness is limited to only outer rows that have no join
     787             :      * partner as this is the only case where Nested Loop would exhaust the
     788             :      * inner scan of a unique join.  Since the scope is limited to that, we
     789             :      * just don't bother making a memoize path in this case.
     790             :      *
     791             :      * Lateral vars needn't be considered here as they're not considered when
     792             :      * determining if the join is unique.
     793             :      */
     794      511630 :     if (extra->inner_unique)
     795             :     {
     796             :         Bitmapset  *ppi_serials;
     797             : 
     798      305168 :         if (inner_path->param_info == NULL)
     799           0 :             return NULL;
     800             : 
     801      305168 :         ppi_serials = inner_path->param_info->ppi_serials;
     802             : 
     803      732122 :         foreach_node(RestrictInfo, rinfo, extra->restrictlist)
     804             :         {
     805      343062 :             if (!bms_is_member(rinfo->rinfo_serial, ppi_serials))
     806      110638 :                 return NULL;
     807             :         }
     808             :     }
     809             : 
     810             :     /*
     811             :      * We can't use a memoize node if there are volatile functions in the
     812             :      * inner rel's target list or restrict list.  A cache hit could reduce the
     813             :      * number of calls to these functions.
     814             :      */
     815      400992 :     if (contain_volatile_functions((Node *) innerrel->reltarget))
     816           0 :         return NULL;
     817             : 
     818      647524 :     foreach(lc, innerrel->baserestrictinfo)
     819             :     {
     820      246688 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     821             : 
     822      246688 :         if (contain_volatile_functions((Node *) rinfo))
     823         156 :             return NULL;
     824             :     }
     825             : 
     826             :     /*
     827             :      * Also check the parameterized path restrictinfos for volatile functions.
     828             :      * Indexed functions must be immutable so shouldn't have any volatile
     829             :      * functions, however, with a lateral join the inner scan may not be an
     830             :      * index scan.
     831             :      */
     832      400836 :     if (inner_path->param_info != NULL)
     833             :     {
     834      867454 :         foreach(lc, inner_path->param_info->ppi_clauses)
     835             :         {
     836      466620 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     837             : 
     838      466620 :             if (contain_volatile_functions((Node *) rinfo))
     839           2 :                 return NULL;
     840             :         }
     841             :     }
     842             : 
     843             :     /* Check if we have hash ops for each parameter to the path */
     844      400834 :     if (paraminfo_get_equal_hashops(root,
     845             :                                     inner_path->param_info,
     846      400834 :                                     outerrel->top_parent ?
     847             :                                     outerrel->top_parent : outerrel,
     848             :                                     innerrel,
     849             :                                     ph_lateral_vars,
     850             :                                     &param_exprs,
     851             :                                     &hash_operators,
     852             :                                     &binary_mode))
     853             :     {
     854      320486 :         return (Path *) create_memoize_path(root,
     855             :                                             innerrel,
     856             :                                             inner_path,
     857             :                                             param_exprs,
     858             :                                             hash_operators,
     859      320486 :                                             extra->inner_unique,
     860             :                                             binary_mode,
     861             :                                             outer_path->rows);
     862             :     }
     863             : 
     864       80348 :     return NULL;
     865             : }
     866             : 
     867             : /*
     868             :  * try_nestloop_path
     869             :  *    Consider a nestloop join path; if it appears useful, push it into
     870             :  *    the joinrel's pathlist via add_path().
     871             :  */
     872             : static void
     873     3509284 : try_nestloop_path(PlannerInfo *root,
     874             :                   RelOptInfo *joinrel,
     875             :                   Path *outer_path,
     876             :                   Path *inner_path,
     877             :                   List *pathkeys,
     878             :                   JoinType jointype,
     879             :                   uint64 nestloop_subtype,
     880             :                   JoinPathExtraData *extra)
     881             : {
     882             :     Relids      required_outer;
     883             :     JoinCostWorkspace workspace;
     884     3509284 :     RelOptInfo *innerrel = inner_path->parent;
     885     3509284 :     RelOptInfo *outerrel = outer_path->parent;
     886             :     Relids      innerrelids;
     887             :     Relids      outerrelids;
     888     3509284 :     Relids      inner_paramrels = PATH_REQ_OUTER(inner_path);
     889     3509284 :     Relids      outer_paramrels = PATH_REQ_OUTER(outer_path);
     890             : 
     891             :     /*
     892             :      * If we are forming an outer join at this join, it's nonsensical to use
     893             :      * an input path that uses the outer join as part of its parameterization.
     894             :      * (This can happen despite our join order restrictions, since those apply
     895             :      * to what is in an input relation not what its parameters are.)
     896             :      */
     897     4200626 :     if (extra->sjinfo->ojrelid != 0 &&
     898     1382684 :         (bms_is_member(extra->sjinfo->ojrelid, inner_paramrels) ||
     899      691342 :          bms_is_member(extra->sjinfo->ojrelid, outer_paramrels)))
     900      322600 :         return;
     901             : 
     902             :     /*
     903             :      * Any parameterization of the input paths refers to topmost parents of
     904             :      * the relevant relations, because reparameterize_path_by_child() hasn't
     905             :      * been called yet.  So we must consider topmost parents of the relations
     906             :      * being joined, too, while determining parameterization of the result and
     907             :      * checking for disallowed parameterization cases.
     908             :      */
     909     3509164 :     if (innerrel->top_parent_relids)
     910      172816 :         innerrelids = innerrel->top_parent_relids;
     911             :     else
     912     3336348 :         innerrelids = innerrel->relids;
     913             : 
     914     3509164 :     if (outerrel->top_parent_relids)
     915      172816 :         outerrelids = outerrel->top_parent_relids;
     916             :     else
     917     3336348 :         outerrelids = outerrel->relids;
     918             : 
     919             :     /*
     920             :      * Check to see if proposed path is still parameterized, and reject if the
     921             :      * parameterization wouldn't be sensible --- unless allow_star_schema_join
     922             :      * says to allow it anyway.
     923             :      */
     924     3509164 :     required_outer = calc_nestloop_required_outer(outerrelids, outer_paramrels,
     925             :                                                   innerrelids, inner_paramrels);
     926     3509164 :     if (required_outer &&
     927      375204 :         !bms_overlap(required_outer, extra->param_source_rels) &&
     928      324656 :         !allow_star_schema_join(root, outerrelids, inner_paramrels))
     929             :     {
     930             :         /* Waste no memory when we reject a path here */
     931      322480 :         bms_free(required_outer);
     932      322480 :         return;
     933             :     }
     934             : 
     935             :     /* If we got past that, we shouldn't have any unsafe outer-join refs */
     936             :     Assert(!have_unsafe_outer_join_ref(root, outerrelids, inner_paramrels));
     937             : 
     938             :     /*
     939             :      * If the inner path is parameterized, it is parameterized by the topmost
     940             :      * parent of the outer rel, not the outer rel itself.  We will need to
     941             :      * translate the parameterization, if this path is chosen, during
     942             :      * create_plan().  Here we just check whether we will be able to perform
     943             :      * the translation, and if not avoid creating a nestloop path.
     944             :      */
     945     3186684 :     if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
     946       12988 :         !path_is_reparameterizable_by_child(inner_path, outer_path->parent))
     947             :     {
     948           0 :         bms_free(required_outer);
     949           0 :         return;
     950             :     }
     951             : 
     952             :     /*
     953             :      * Do a precheck to quickly eliminate obviously-inferior paths.  We
     954             :      * calculate a cheap lower bound on the path's cost and then use
     955             :      * add_path_precheck() to see if the path is clearly going to be dominated
     956             :      * by some existing path for the joinrel.  If not, do the full pushup with
     957             :      * creating a fully valid path structure and submitting it to add_path().
     958             :      * The latter two steps are expensive enough to make this two-phase
     959             :      * methodology worthwhile.
     960             :      */
     961     3186684 :     initial_cost_nestloop(root, &workspace, jointype,
     962             :                           nestloop_subtype | PGS_CONSIDER_NONPARTIAL,
     963             :                           outer_path, inner_path, extra);
     964             : 
     965     3186684 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
     966             :                           workspace.startup_cost, workspace.total_cost,
     967             :                           pathkeys, required_outer))
     968             :     {
     969     1479500 :         add_path(joinrel, (Path *)
     970     1479500 :                  create_nestloop_path(root,
     971             :                                       joinrel,
     972             :                                       jointype,
     973             :                                       &workspace,
     974             :                                       extra,
     975             :                                       outer_path,
     976             :                                       inner_path,
     977             :                                       extra->restrictlist,
     978             :                                       pathkeys,
     979             :                                       required_outer));
     980             :     }
     981             :     else
     982             :     {
     983             :         /* Waste no memory when we reject a path here */
     984     1707184 :         bms_free(required_outer);
     985             :     }
     986             : }
     987             : 
     988             : /*
     989             :  * try_partial_nestloop_path
     990             :  *    Consider a partial nestloop join path; if it appears useful, push it into
     991             :  *    the joinrel's partial_pathlist via add_partial_path().
     992             :  */
     993             : static void
     994      201914 : try_partial_nestloop_path(PlannerInfo *root,
     995             :                           RelOptInfo *joinrel,
     996             :                           Path *outer_path,
     997             :                           Path *inner_path,
     998             :                           List *pathkeys,
     999             :                           JoinType jointype,
    1000             :                           uint64 nestloop_subtype,
    1001             :                           JoinPathExtraData *extra)
    1002             : {
    1003             :     JoinCostWorkspace workspace;
    1004             : 
    1005             :     /*
    1006             :      * If the inner path is parameterized, the parameterization must be fully
    1007             :      * satisfied by the proposed outer path.  Parameterized partial paths are
    1008             :      * not supported.  The caller should already have verified that no lateral
    1009             :      * rels are required here.
    1010             :      */
    1011             :     Assert(bms_is_empty(joinrel->lateral_relids));
    1012             :     Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
    1013      201914 :     if (inner_path->param_info != NULL)
    1014             :     {
    1015       15478 :         Relids      inner_paramrels = inner_path->param_info->ppi_req_outer;
    1016       15478 :         RelOptInfo *outerrel = outer_path->parent;
    1017             :         Relids      outerrelids;
    1018             : 
    1019             :         /*
    1020             :          * The inner and outer paths are parameterized, if at all, by the top
    1021             :          * level parents, not the child relations, so we must use those relids
    1022             :          * for our parameterization tests.
    1023             :          */
    1024       15478 :         if (outerrel->top_parent_relids)
    1025       11412 :             outerrelids = outerrel->top_parent_relids;
    1026             :         else
    1027        4066 :             outerrelids = outerrel->relids;
    1028             : 
    1029       15478 :         if (!bms_is_subset(inner_paramrels, outerrelids))
    1030      157870 :             return;
    1031             :     }
    1032             : 
    1033             :     /*
    1034             :      * If the inner path is parameterized, it is parameterized by the topmost
    1035             :      * parent of the outer rel, not the outer rel itself.  We will need to
    1036             :      * translate the parameterization, if this path is chosen, during
    1037             :      * create_plan().  Here we just check whether we will be able to perform
    1038             :      * the translation, and if not avoid creating a nestloop path.
    1039             :      */
    1040      200550 :     if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
    1041       10440 :         !path_is_reparameterizable_by_child(inner_path, outer_path->parent))
    1042           0 :         return;
    1043             : 
    1044             :     /*
    1045             :      * Before creating a path, get a quick lower bound on what it is likely to
    1046             :      * cost.  Bail out right away if it looks terrible.
    1047             :      */
    1048      200550 :     initial_cost_nestloop(root, &workspace, jointype, nestloop_subtype,
    1049             :                           outer_path, inner_path, extra);
    1050      200550 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1051             :                                    workspace.total_cost, pathkeys))
    1052      156506 :         return;
    1053             : 
    1054             :     /* Might be good enough to be worth trying, so let's try it. */
    1055       44044 :     add_partial_path(joinrel, (Path *)
    1056       44044 :                      create_nestloop_path(root,
    1057             :                                           joinrel,
    1058             :                                           jointype,
    1059             :                                           &workspace,
    1060             :                                           extra,
    1061             :                                           outer_path,
    1062             :                                           inner_path,
    1063             :                                           extra->restrictlist,
    1064             :                                           pathkeys,
    1065             :                                           NULL));
    1066             : }
    1067             : 
    1068             : /*
    1069             :  * try_mergejoin_path
    1070             :  *    Consider a merge join path; if it appears useful, push it into
    1071             :  *    the joinrel's pathlist via add_path().
    1072             :  */
    1073             : static void
    1074     1501404 : try_mergejoin_path(PlannerInfo *root,
    1075             :                    RelOptInfo *joinrel,
    1076             :                    Path *outer_path,
    1077             :                    Path *inner_path,
    1078             :                    List *pathkeys,
    1079             :                    List *mergeclauses,
    1080             :                    List *outersortkeys,
    1081             :                    List *innersortkeys,
    1082             :                    JoinType jointype,
    1083             :                    JoinPathExtraData *extra,
    1084             :                    bool is_partial)
    1085             : {
    1086             :     Relids      required_outer;
    1087     1501404 :     int         outer_presorted_keys = 0;
    1088             :     JoinCostWorkspace workspace;
    1089             : 
    1090     1501404 :     if (is_partial)
    1091             :     {
    1092       23350 :         try_partial_mergejoin_path(root,
    1093             :                                    joinrel,
    1094             :                                    outer_path,
    1095             :                                    inner_path,
    1096             :                                    pathkeys,
    1097             :                                    mergeclauses,
    1098             :                                    outersortkeys,
    1099             :                                    innersortkeys,
    1100             :                                    jointype,
    1101             :                                    extra);
    1102       64500 :         return;
    1103             :     }
    1104             : 
    1105             :     /*
    1106             :      * If we are forming an outer join at this join, it's nonsensical to use
    1107             :      * an input path that uses the outer join as part of its parameterization.
    1108             :      * (This can happen despite our join order restrictions, since those apply
    1109             :      * to what is in an input relation not what its parameters are.)
    1110             :      */
    1111     1864454 :     if (extra->sjinfo->ojrelid != 0 &&
    1112      772800 :         (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
    1113      386400 :          bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
    1114          12 :         return;
    1115             : 
    1116             :     /*
    1117             :      * Check to see if proposed path is still parameterized, and reject if the
    1118             :      * parameterization wouldn't be sensible.
    1119             :      */
    1120     1478042 :     required_outer = calc_non_nestloop_required_outer(outer_path,
    1121             :                                                       inner_path);
    1122     1478042 :     if (required_outer &&
    1123       47520 :         !bms_overlap(required_outer, extra->param_source_rels))
    1124             :     {
    1125             :         /* Waste no memory when we reject a path here */
    1126       41138 :         bms_free(required_outer);
    1127       41138 :         return;
    1128             :     }
    1129             : 
    1130             :     /*
    1131             :      * If the given paths are already well enough ordered, we can skip doing
    1132             :      * an explicit sort.
    1133             :      *
    1134             :      * We need to determine the number of presorted keys of the outer path to
    1135             :      * decide whether explicit incremental sort can be applied when
    1136             :      * outersortkeys is not NIL.  We do not need to do the same for the inner
    1137             :      * path though, as incremental sort currently does not support
    1138             :      * mark/restore.
    1139             :      */
    1140     2155346 :     if (outersortkeys &&
    1141      718442 :         pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
    1142             :                                     &outer_presorted_keys))
    1143       17914 :         outersortkeys = NIL;
    1144     2602144 :     if (innersortkeys &&
    1145     1165240 :         pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
    1146       31372 :         innersortkeys = NIL;
    1147             : 
    1148             :     /*
    1149             :      * See comments in try_nestloop_path().
    1150             :      */
    1151     1436904 :     initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
    1152             :                            outer_path, inner_path,
    1153             :                            outersortkeys, innersortkeys,
    1154             :                            outer_presorted_keys,
    1155             :                            extra);
    1156             : 
    1157     1436904 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
    1158             :                           workspace.startup_cost, workspace.total_cost,
    1159             :                           pathkeys, required_outer))
    1160             :     {
    1161      407838 :         add_path(joinrel, (Path *)
    1162      407838 :                  create_mergejoin_path(root,
    1163             :                                        joinrel,
    1164             :                                        jointype,
    1165             :                                        &workspace,
    1166             :                                        extra,
    1167             :                                        outer_path,
    1168             :                                        inner_path,
    1169             :                                        extra->restrictlist,
    1170             :                                        pathkeys,
    1171             :                                        required_outer,
    1172             :                                        mergeclauses,
    1173             :                                        outersortkeys,
    1174             :                                        innersortkeys,
    1175             :                                        outer_presorted_keys));
    1176             :     }
    1177             :     else
    1178             :     {
    1179             :         /* Waste no memory when we reject a path here */
    1180     1029066 :         bms_free(required_outer);
    1181             :     }
    1182             : }
    1183             : 
    1184             : /*
    1185             :  * try_partial_mergejoin_path
    1186             :  *    Consider a partial merge join path; if it appears useful, push it into
    1187             :  *    the joinrel's pathlist via add_partial_path().
    1188             :  */
    1189             : static void
    1190       99914 : try_partial_mergejoin_path(PlannerInfo *root,
    1191             :                            RelOptInfo *joinrel,
    1192             :                            Path *outer_path,
    1193             :                            Path *inner_path,
    1194             :                            List *pathkeys,
    1195             :                            List *mergeclauses,
    1196             :                            List *outersortkeys,
    1197             :                            List *innersortkeys,
    1198             :                            JoinType jointype,
    1199             :                            JoinPathExtraData *extra)
    1200             : {
    1201       99914 :     int         outer_presorted_keys = 0;
    1202             :     JoinCostWorkspace workspace;
    1203             : 
    1204             :     /*
    1205             :      * See comments in try_partial_hashjoin_path().
    1206             :      */
    1207             :     Assert(bms_is_empty(joinrel->lateral_relids));
    1208             :     Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
    1209       99914 :     if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
    1210       34018 :         return;
    1211             : 
    1212             :     /*
    1213             :      * If the given paths are already well enough ordered, we can skip doing
    1214             :      * an explicit sort.
    1215             :      *
    1216             :      * We need to determine the number of presorted keys of the outer path to
    1217             :      * decide whether explicit incremental sort can be applied when
    1218             :      * outersortkeys is not NIL.  We do not need to do the same for the inner
    1219             :      * path though, as incremental sort currently does not support
    1220             :      * mark/restore.
    1221             :      */
    1222      176478 :     if (outersortkeys &&
    1223       76564 :         pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
    1224             :                                     &outer_presorted_keys))
    1225         246 :         outersortkeys = NIL;
    1226      196580 :     if (innersortkeys &&
    1227       96666 :         pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
    1228         642 :         innersortkeys = NIL;
    1229             : 
    1230             :     /*
    1231             :      * See comments in try_partial_nestloop_path().
    1232             :      */
    1233       99914 :     initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
    1234             :                            outer_path, inner_path,
    1235             :                            outersortkeys, innersortkeys,
    1236             :                            outer_presorted_keys,
    1237             :                            extra);
    1238             : 
    1239       99914 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1240             :                                    workspace.total_cost, pathkeys))
    1241       34018 :         return;
    1242             : 
    1243             :     /* Might be good enough to be worth trying, so let's try it. */
    1244       65896 :     add_partial_path(joinrel, (Path *)
    1245       65896 :                      create_mergejoin_path(root,
    1246             :                                            joinrel,
    1247             :                                            jointype,
    1248             :                                            &workspace,
    1249             :                                            extra,
    1250             :                                            outer_path,
    1251             :                                            inner_path,
    1252             :                                            extra->restrictlist,
    1253             :                                            pathkeys,
    1254             :                                            NULL,
    1255             :                                            mergeclauses,
    1256             :                                            outersortkeys,
    1257             :                                            innersortkeys,
    1258             :                                            outer_presorted_keys));
    1259             : }
    1260             : 
    1261             : /*
    1262             :  * try_hashjoin_path
    1263             :  *    Consider a hash join path; if it appears useful, push it into
    1264             :  *    the joinrel's pathlist via add_path().
    1265             :  */
    1266             : static void
    1267      880994 : try_hashjoin_path(PlannerInfo *root,
    1268             :                   RelOptInfo *joinrel,
    1269             :                   Path *outer_path,
    1270             :                   Path *inner_path,
    1271             :                   List *hashclauses,
    1272             :                   JoinType jointype,
    1273             :                   JoinPathExtraData *extra)
    1274             : {
    1275             :     Relids      required_outer;
    1276             :     JoinCostWorkspace workspace;
    1277             : 
    1278             :     /*
    1279             :      * If we are forming an outer join at this join, it's nonsensical to use
    1280             :      * an input path that uses the outer join as part of its parameterization.
    1281             :      * (This can happen despite our join order restrictions, since those apply
    1282             :      * to what is in an input relation not what its parameters are.)
    1283             :      */
    1284     1135192 :     if (extra->sjinfo->ojrelid != 0 &&
    1285      508366 :         (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
    1286      254168 :          bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
    1287      129080 :         return;
    1288             : 
    1289             :     /*
    1290             :      * Check to see if proposed path is still parameterized, and reject if the
    1291             :      * parameterization wouldn't be sensible.
    1292             :      */
    1293      880934 :     required_outer = calc_non_nestloop_required_outer(outer_path,
    1294             :                                                       inner_path);
    1295      880934 :     if (required_outer &&
    1296      146972 :         !bms_overlap(required_outer, extra->param_source_rels))
    1297             :     {
    1298             :         /* Waste no memory when we reject a path here */
    1299      129020 :         bms_free(required_outer);
    1300      129020 :         return;
    1301             :     }
    1302             : 
    1303             :     /*
    1304             :      * See comments in try_nestloop_path().  Also note that hashjoin paths
    1305             :      * never have any output pathkeys, per comments in create_hashjoin_path.
    1306             :      */
    1307      751914 :     initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
    1308             :                           outer_path, inner_path, extra, false);
    1309             : 
    1310      751914 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
    1311             :                           workspace.startup_cost, workspace.total_cost,
    1312             :                           NIL, required_outer))
    1313             :     {
    1314      359044 :         add_path(joinrel, (Path *)
    1315      359044 :                  create_hashjoin_path(root,
    1316             :                                       joinrel,
    1317             :                                       jointype,
    1318             :                                       &workspace,
    1319             :                                       extra,
    1320             :                                       outer_path,
    1321             :                                       inner_path,
    1322             :                                       false,    /* parallel_hash */
    1323             :                                       extra->restrictlist,
    1324             :                                       required_outer,
    1325             :                                       hashclauses));
    1326             :     }
    1327             :     else
    1328             :     {
    1329             :         /* Waste no memory when we reject a path here */
    1330      392870 :         bms_free(required_outer);
    1331             :     }
    1332             : }
    1333             : 
    1334             : /*
    1335             :  * try_partial_hashjoin_path
    1336             :  *    Consider a partial hashjoin join path; if it appears useful, push it into
    1337             :  *    the joinrel's partial_pathlist via add_partial_path().
    1338             :  *    The outer side is partial.  If parallel_hash is true, then the inner path
    1339             :  *    must be partial and will be run in parallel to create one or more shared
    1340             :  *    hash tables; otherwise the inner path must be complete and a copy of it
    1341             :  *    is run in every process to create separate identical private hash tables.
    1342             :  */
    1343             : static void
    1344      147860 : try_partial_hashjoin_path(PlannerInfo *root,
    1345             :                           RelOptInfo *joinrel,
    1346             :                           Path *outer_path,
    1347             :                           Path *inner_path,
    1348             :                           List *hashclauses,
    1349             :                           JoinType jointype,
    1350             :                           JoinPathExtraData *extra,
    1351             :                           bool parallel_hash)
    1352             : {
    1353             :     JoinCostWorkspace workspace;
    1354             : 
    1355             :     /*
    1356             :      * If the inner path is parameterized, we can't use a partial hashjoin.
    1357             :      * Parameterized partial paths are not supported.  The caller should
    1358             :      * already have verified that no lateral rels are required here.
    1359             :      */
    1360             :     Assert(bms_is_empty(joinrel->lateral_relids));
    1361             :     Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
    1362      147860 :     if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
    1363       40700 :         return;
    1364             : 
    1365             :     /*
    1366             :      * Before creating a path, get a quick lower bound on what it is likely to
    1367             :      * cost.  Bail out right away if it looks terrible.
    1368             :      */
    1369      147860 :     initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
    1370             :                           outer_path, inner_path, extra, parallel_hash);
    1371      147860 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1372             :                                    workspace.total_cost, NIL))
    1373       40700 :         return;
    1374             : 
    1375             :     /* Might be good enough to be worth trying, so let's try it. */
    1376      107160 :     add_partial_path(joinrel, (Path *)
    1377      107160 :                      create_hashjoin_path(root,
    1378             :                                           joinrel,
    1379             :                                           jointype,
    1380             :                                           &workspace,
    1381             :                                           extra,
    1382             :                                           outer_path,
    1383             :                                           inner_path,
    1384             :                                           parallel_hash,
    1385             :                                           extra->restrictlist,
    1386             :                                           NULL,
    1387             :                                           hashclauses));
    1388             : }
    1389             : 
    1390             : /*
    1391             :  * sort_inner_and_outer
    1392             :  *    Create mergejoin join paths by explicitly sorting both the outer and
    1393             :  *    inner join relations on each available merge ordering.
    1394             :  *
    1395             :  * 'joinrel' is the join relation
    1396             :  * 'outerrel' is the outer join relation
    1397             :  * 'innerrel' is the inner join relation
    1398             :  * 'jointype' is the type of join to do
    1399             :  * 'extra' contains additional input values
    1400             :  */
    1401             : static void
    1402      763798 : sort_inner_and_outer(PlannerInfo *root,
    1403             :                      RelOptInfo *joinrel,
    1404             :                      RelOptInfo *outerrel,
    1405             :                      RelOptInfo *innerrel,
    1406             :                      JoinType jointype,
    1407             :                      JoinPathExtraData *extra)
    1408             : {
    1409             :     Path       *outer_path;
    1410             :     Path       *inner_path;
    1411      763798 :     Path       *cheapest_partial_outer = NULL;
    1412      763798 :     Path       *cheapest_safe_inner = NULL;
    1413             :     List       *all_pathkeys;
    1414             :     ListCell   *l;
    1415             : 
    1416             :     /* Nothing to do if there are no available mergejoin clauses */
    1417      763798 :     if (extra->mergeclause_list == NIL)
    1418      122190 :         return;
    1419             : 
    1420             :     /*
    1421             :      * We only consider the cheapest-total-cost input paths, since we are
    1422             :      * assuming here that a sort is required.  We will consider
    1423             :      * cheapest-startup-cost input paths later, and only if they don't need a
    1424             :      * sort.
    1425             :      *
    1426             :      * This function intentionally does not consider parameterized input
    1427             :      * paths, except when the cheapest-total is parameterized.  If we did so,
    1428             :      * we'd have a combinatorial explosion of mergejoin paths of dubious
    1429             :      * value.  This interacts with decisions elsewhere that also discriminate
    1430             :      * against mergejoins with parameterized inputs; see comments in
    1431             :      * src/backend/optimizer/README.
    1432             :      */
    1433      641608 :     outer_path = outerrel->cheapest_total_path;
    1434      641608 :     inner_path = innerrel->cheapest_total_path;
    1435             : 
    1436             :     /*
    1437             :      * If either cheapest-total path is parameterized by the other rel, we
    1438             :      * can't use a mergejoin.  (There's no use looking for alternative input
    1439             :      * paths, since these should already be the least-parameterized available
    1440             :      * paths.)
    1441             :      */
    1442      641608 :     if (PATH_PARAM_BY_REL(outer_path, innerrel) ||
    1443      640716 :         PATH_PARAM_BY_REL(inner_path, outerrel))
    1444        1820 :         return;
    1445             : 
    1446             :     /*
    1447             :      * If the joinrel is parallel-safe, we may be able to consider a partial
    1448             :      * merge join.  However, we can't handle JOIN_FULL, JOIN_RIGHT and
    1449             :      * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
    1450             :      * Also, the resulting path must not be parameterized.
    1451             :      */
    1452      639788 :     if (joinrel->consider_parallel &&
    1453      576576 :         jointype != JOIN_FULL &&
    1454      493738 :         jointype != JOIN_RIGHT &&
    1455      492254 :         jointype != JOIN_RIGHT_ANTI &&
    1456      492254 :         outerrel->partial_pathlist != NIL &&
    1457       72902 :         bms_is_empty(joinrel->lateral_relids))
    1458             :     {
    1459       72902 :         cheapest_partial_outer = (Path *) linitial(outerrel->partial_pathlist);
    1460             : 
    1461       72902 :         if (inner_path->parallel_safe)
    1462       72722 :             cheapest_safe_inner = inner_path;
    1463             :         else
    1464             :             cheapest_safe_inner =
    1465         180 :                 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    1466             :     }
    1467             : 
    1468             :     /*
    1469             :      * Each possible ordering of the available mergejoin clauses will generate
    1470             :      * a differently-sorted result path at essentially the same cost.  We have
    1471             :      * no basis for choosing one over another at this level of joining, but
    1472             :      * some sort orders may be more useful than others for higher-level
    1473             :      * mergejoins, so it's worth considering multiple orderings.
    1474             :      *
    1475             :      * Actually, it's not quite true that every mergeclause ordering will
    1476             :      * generate a different path order, because some of the clauses may be
    1477             :      * partially redundant (refer to the same EquivalenceClasses).  Therefore,
    1478             :      * what we do is convert the mergeclause list to a list of canonical
    1479             :      * pathkeys, and then consider different orderings of the pathkeys.
    1480             :      *
    1481             :      * Generating a path for *every* permutation of the pathkeys doesn't seem
    1482             :      * like a winning strategy; the cost in planning time is too high. For
    1483             :      * now, we generate one path for each pathkey, listing that pathkey first
    1484             :      * and the rest in random order.  This should allow at least a one-clause
    1485             :      * mergejoin without re-sorting against any other possible mergejoin
    1486             :      * partner path.  But if we've not guessed the right ordering of secondary
    1487             :      * keys, we may end up evaluating clauses as qpquals when they could have
    1488             :      * been done as mergeclauses.  (In practice, it's rare that there's more
    1489             :      * than two or three mergeclauses, so expending a huge amount of thought
    1490             :      * on that is probably not worth it.)
    1491             :      *
    1492             :      * The pathkey order returned by select_outer_pathkeys_for_merge() has
    1493             :      * some heuristics behind it (see that function), so be sure to try it
    1494             :      * exactly as-is as well as making variants.
    1495             :      */
    1496      639788 :     all_pathkeys = select_outer_pathkeys_for_merge(root,
    1497             :                                                    extra->mergeclause_list,
    1498             :                                                    joinrel);
    1499             : 
    1500     1358230 :     foreach(l, all_pathkeys)
    1501             :     {
    1502      718442 :         PathKey    *front_pathkey = (PathKey *) lfirst(l);
    1503             :         List       *cur_mergeclauses;
    1504             :         List       *outerkeys;
    1505             :         List       *innerkeys;
    1506             :         List       *merge_pathkeys;
    1507             : 
    1508             :         /* Make a pathkey list with this guy first */
    1509      718442 :         if (l != list_head(all_pathkeys))
    1510       78654 :             outerkeys = lcons(front_pathkey,
    1511             :                               list_delete_nth_cell(list_copy(all_pathkeys),
    1512             :                                                    foreach_current_index(l)));
    1513             :         else
    1514      639788 :             outerkeys = all_pathkeys;   /* no work at first one... */
    1515             : 
    1516             :         /* Sort the mergeclauses into the corresponding ordering */
    1517             :         cur_mergeclauses =
    1518      718442 :             find_mergeclauses_for_outer_pathkeys(root,
    1519             :                                                  outerkeys,
    1520             :                                                  extra->mergeclause_list);
    1521             : 
    1522             :         /* Should have used them all... */
    1523             :         Assert(list_length(cur_mergeclauses) == list_length(extra->mergeclause_list));
    1524             : 
    1525             :         /* Build sort pathkeys for the inner side */
    1526      718442 :         innerkeys = make_inner_pathkeys_for_merge(root,
    1527             :                                                   cur_mergeclauses,
    1528             :                                                   outerkeys);
    1529             : 
    1530             :         /* Build pathkeys representing output sort order */
    1531      718442 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    1532             :                                              outerkeys);
    1533             : 
    1534             :         /*
    1535             :          * And now we can make the path.
    1536             :          *
    1537             :          * Note: it's possible that the cheapest paths will already be sorted
    1538             :          * properly.  try_mergejoin_path will detect that case and suppress an
    1539             :          * explicit sort step, so we needn't do so here.
    1540             :          */
    1541      718442 :         try_mergejoin_path(root,
    1542             :                            joinrel,
    1543             :                            outer_path,
    1544             :                            inner_path,
    1545             :                            merge_pathkeys,
    1546             :                            cur_mergeclauses,
    1547             :                            outerkeys,
    1548             :                            innerkeys,
    1549             :                            jointype,
    1550             :                            extra,
    1551             :                            false);
    1552             : 
    1553             :         /*
    1554             :          * If we have partial outer and parallel safe inner path then try
    1555             :          * partial mergejoin path.
    1556             :          */
    1557      718442 :         if (cheapest_partial_outer && cheapest_safe_inner)
    1558       76564 :             try_partial_mergejoin_path(root,
    1559             :                                        joinrel,
    1560             :                                        cheapest_partial_outer,
    1561             :                                        cheapest_safe_inner,
    1562             :                                        merge_pathkeys,
    1563             :                                        cur_mergeclauses,
    1564             :                                        outerkeys,
    1565             :                                        innerkeys,
    1566             :                                        jointype,
    1567             :                                        extra);
    1568             :     }
    1569             : }
    1570             : 
    1571             : /*
    1572             :  * generate_mergejoin_paths
    1573             :  *  Creates possible mergejoin paths for input outerpath.
    1574             :  *
    1575             :  * We generate mergejoins if mergejoin clauses are available.  We have
    1576             :  * two ways to generate the inner path for a mergejoin: sort the cheapest
    1577             :  * inner path, or use an inner path that is already suitably ordered for the
    1578             :  * merge.  If we have several mergeclauses, it could be that there is no inner
    1579             :  * path (or only a very expensive one) for the full list of mergeclauses, but
    1580             :  * better paths exist if we truncate the mergeclause list (thereby discarding
    1581             :  * some sort key requirements).  So, we consider truncations of the
    1582             :  * mergeclause list as well as the full list.  (Ideally we'd consider all
    1583             :  * subsets of the mergeclause list, but that seems way too expensive.)
    1584             :  */
    1585             : static void
    1586     1532094 : generate_mergejoin_paths(PlannerInfo *root,
    1587             :                          RelOptInfo *joinrel,
    1588             :                          RelOptInfo *innerrel,
    1589             :                          Path *outerpath,
    1590             :                          JoinType jointype,
    1591             :                          JoinPathExtraData *extra,
    1592             :                          bool useallclauses,
    1593             :                          Path *inner_cheapest_total,
    1594             :                          List *merge_pathkeys,
    1595             :                          bool is_partial)
    1596             : {
    1597             :     List       *mergeclauses;
    1598             :     List       *innersortkeys;
    1599             :     List       *trialsortkeys;
    1600             :     Path       *cheapest_startup_inner;
    1601             :     Path       *cheapest_total_inner;
    1602             :     int         num_sortkeys;
    1603             :     int         sortkeycnt;
    1604             : 
    1605             :     /* Look for useful mergeclauses (if any) */
    1606             :     mergeclauses =
    1607     1532094 :         find_mergeclauses_for_outer_pathkeys(root,
    1608             :                                              outerpath->pathkeys,
    1609             :                                              extra->mergeclause_list);
    1610             : 
    1611             :     /*
    1612             :      * Done with this outer path if no chance for a mergejoin.
    1613             :      *
    1614             :      * Special corner case: for "x FULL JOIN y ON true", there will be no join
    1615             :      * clauses at all.  Ordinarily we'd generate a clauseless nestloop path,
    1616             :      * but since mergejoin is our only join type that supports FULL JOIN
    1617             :      * without any join clauses, it's necessary to generate a clauseless
    1618             :      * mergejoin path instead.
    1619             :      */
    1620     1532094 :     if (mergeclauses == NIL)
    1621             :     {
    1622     1031482 :         if (jointype == JOIN_FULL)
    1623             :              /* okay to try for mergejoin */ ;
    1624             :         else
    1625     1028086 :             return;
    1626             :     }
    1627      593054 :     if (useallclauses &&
    1628       89046 :         list_length(mergeclauses) != list_length(extra->mergeclause_list))
    1629       13736 :         return;
    1630             : 
    1631             :     /* Compute the required ordering of the inner path */
    1632      490272 :     innersortkeys = make_inner_pathkeys_for_merge(root,
    1633             :                                                   mergeclauses,
    1634             :                                                   outerpath->pathkeys);
    1635             : 
    1636             :     /*
    1637             :      * Generate a mergejoin on the basis of sorting the cheapest inner. Since
    1638             :      * a sort will be needed, only cheapest total cost matters. (But
    1639             :      * try_mergejoin_path will do the right thing if inner_cheapest_total is
    1640             :      * already correctly sorted.)
    1641             :      */
    1642      490272 :     try_mergejoin_path(root,
    1643             :                        joinrel,
    1644             :                        outerpath,
    1645             :                        inner_cheapest_total,
    1646             :                        merge_pathkeys,
    1647             :                        mergeclauses,
    1648             :                        NIL,
    1649             :                        innersortkeys,
    1650             :                        jointype,
    1651             :                        extra,
    1652             :                        is_partial);
    1653             : 
    1654             :     /*
    1655             :      * Look for presorted inner paths that satisfy the innersortkey list ---
    1656             :      * or any truncation thereof, if we are allowed to build a mergejoin using
    1657             :      * a subset of the merge clauses.  Here, we consider both cheap startup
    1658             :      * cost and cheap total cost.
    1659             :      *
    1660             :      * Currently we do not consider parameterized inner paths here. This
    1661             :      * interacts with decisions elsewhere that also discriminate against
    1662             :      * mergejoins with parameterized inputs; see comments in
    1663             :      * src/backend/optimizer/README.
    1664             :      *
    1665             :      * As we shorten the sortkey list, we should consider only paths that are
    1666             :      * strictly cheaper than (in particular, not the same as) any path found
    1667             :      * in an earlier iteration.  Otherwise we'd be intentionally using fewer
    1668             :      * merge keys than a given path allows (treating the rest as plain
    1669             :      * joinquals), which is unlikely to be a good idea.  Also, eliminating
    1670             :      * paths here on the basis of compare_path_costs is a lot cheaper than
    1671             :      * building the mergejoin path only to throw it away.
    1672             :      *
    1673             :      * If inner_cheapest_total is well enough sorted to have not required a
    1674             :      * sort in the path made above, we shouldn't make a duplicate path with
    1675             :      * it, either.  We handle that case with the same logic that handles the
    1676             :      * previous consideration, by initializing the variables that track
    1677             :      * cheapest-so-far properly.  Note that we do NOT reject
    1678             :      * inner_cheapest_total if we find it matches some shorter set of
    1679             :      * pathkeys.  That case corresponds to using fewer mergekeys to avoid
    1680             :      * sorting inner_cheapest_total, whereas we did sort it above, so the
    1681             :      * plans being considered are different.
    1682             :      */
    1683      490272 :     if (pathkeys_contained_in(innersortkeys,
    1684             :                               inner_cheapest_total->pathkeys))
    1685             :     {
    1686             :         /* inner_cheapest_total didn't require a sort */
    1687       15282 :         cheapest_startup_inner = inner_cheapest_total;
    1688       15282 :         cheapest_total_inner = inner_cheapest_total;
    1689             :     }
    1690             :     else
    1691             :     {
    1692             :         /* it did require a sort, at least for the full set of keys */
    1693      474990 :         cheapest_startup_inner = NULL;
    1694      474990 :         cheapest_total_inner = NULL;
    1695             :     }
    1696      490272 :     num_sortkeys = list_length(innersortkeys);
    1697      490272 :     if (num_sortkeys > 1 && !useallclauses)
    1698       25542 :         trialsortkeys = list_copy(innersortkeys);   /* need modifiable copy */
    1699             :     else
    1700      464730 :         trialsortkeys = innersortkeys;  /* won't really truncate */
    1701             : 
    1702      931660 :     for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
    1703             :     {
    1704             :         Path       *innerpath;
    1705      516554 :         List       *newclauses = NIL;
    1706             : 
    1707             :         /*
    1708             :          * Look for an inner path ordered well enough for the first
    1709             :          * 'sortkeycnt' innersortkeys.  NB: trialsortkeys list is modified
    1710             :          * destructively, which is why we made a copy...
    1711             :          */
    1712      516554 :         trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
    1713      516554 :         innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
    1714             :                                                    trialsortkeys,
    1715             :                                                    NULL,
    1716             :                                                    TOTAL_COST,
    1717             :                                                    is_partial);
    1718      516554 :         if (innerpath != NULL &&
    1719       25936 :             (cheapest_total_inner == NULL ||
    1720       25936 :              compare_path_costs(innerpath, cheapest_total_inner,
    1721             :                                 TOTAL_COST) < 0))
    1722             :         {
    1723             :             /* Found a cheap (or even-cheaper) sorted path */
    1724             :             /* Select the right mergeclauses, if we didn't already */
    1725      289814 :             if (sortkeycnt < num_sortkeys)
    1726             :             {
    1727             :                 newclauses =
    1728       15404 :                     trim_mergeclauses_for_inner_pathkeys(root,
    1729             :                                                          mergeclauses,
    1730             :                                                          trialsortkeys);
    1731             :                 Assert(newclauses != NIL);
    1732             :             }
    1733             :             else
    1734      274410 :                 newclauses = mergeclauses;
    1735      289814 :             try_mergejoin_path(root,
    1736             :                                joinrel,
    1737             :                                outerpath,
    1738             :                                innerpath,
    1739             :                                merge_pathkeys,
    1740             :                                newclauses,
    1741             :                                NIL,
    1742             :                                NIL,
    1743             :                                jointype,
    1744             :                                extra,
    1745             :                                is_partial);
    1746      289814 :             cheapest_total_inner = innerpath;
    1747             :         }
    1748             :         /* Same on the basis of cheapest startup cost ... */
    1749      516554 :         innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
    1750             :                                                    trialsortkeys,
    1751             :                                                    NULL,
    1752             :                                                    STARTUP_COST,
    1753             :                                                    is_partial);
    1754      516554 :         if (innerpath != NULL &&
    1755       25936 :             (cheapest_startup_inner == NULL ||
    1756       25936 :              compare_path_costs(innerpath, cheapest_startup_inner,
    1757             :                                 STARTUP_COST) < 0))
    1758             :         {
    1759             :             /* Found a cheap (or even-cheaper) sorted path */
    1760      287208 :             if (innerpath != cheapest_total_inner)
    1761             :             {
    1762             :                 /*
    1763             :                  * Avoid rebuilding clause list if we already made one; saves
    1764             :                  * memory in big join trees...
    1765             :                  */
    1766        2876 :                 if (newclauses == NIL)
    1767             :                 {
    1768         102 :                     if (sortkeycnt < num_sortkeys)
    1769             :                     {
    1770             :                         newclauses =
    1771           0 :                             trim_mergeclauses_for_inner_pathkeys(root,
    1772             :                                                                  mergeclauses,
    1773             :                                                                  trialsortkeys);
    1774             :                         Assert(newclauses != NIL);
    1775             :                     }
    1776             :                     else
    1777         102 :                         newclauses = mergeclauses;
    1778             :                 }
    1779        2876 :                 try_mergejoin_path(root,
    1780             :                                    joinrel,
    1781             :                                    outerpath,
    1782             :                                    innerpath,
    1783             :                                    merge_pathkeys,
    1784             :                                    newclauses,
    1785             :                                    NIL,
    1786             :                                    NIL,
    1787             :                                    jointype,
    1788             :                                    extra,
    1789             :                                    is_partial);
    1790             :             }
    1791      287208 :             cheapest_startup_inner = innerpath;
    1792             :         }
    1793             : 
    1794             :         /*
    1795             :          * Don't consider truncated sortkeys if we need all clauses.
    1796             :          */
    1797      516554 :         if (useallclauses)
    1798       75166 :             break;
    1799             :     }
    1800             : }
    1801             : 
    1802             : /*
    1803             :  * match_unsorted_outer
    1804             :  *    Creates possible join paths for processing a single join relation
    1805             :  *    'joinrel' by employing either iterative substitution or
    1806             :  *    mergejoining on each of its possible outer paths (considering
    1807             :  *    only outer paths that are already ordered well enough for merging).
    1808             :  *
    1809             :  * We always generate a nestloop path for each available outer path.
    1810             :  * In fact we may generate as many as five: one on the cheapest-total-cost
    1811             :  * inner path, one on the same with materialization, one on the
    1812             :  * cheapest-startup-cost inner path (if different), one on the
    1813             :  * cheapest-total inner-indexscan path (if any), and one on the
    1814             :  * cheapest-startup inner-indexscan path (if different).
    1815             :  *
    1816             :  * We also consider mergejoins if mergejoin clauses are available.  See
    1817             :  * detailed comments in generate_mergejoin_paths.
    1818             :  *
    1819             :  * 'joinrel' is the join relation
    1820             :  * 'outerrel' is the outer join relation
    1821             :  * 'innerrel' is the inner join relation
    1822             :  * 'jointype' is the type of join to do
    1823             :  * 'extra' contains additional input values
    1824             :  */
    1825             : static void
    1826      763798 : match_unsorted_outer(PlannerInfo *root,
    1827             :                      RelOptInfo *joinrel,
    1828             :                      RelOptInfo *outerrel,
    1829             :                      RelOptInfo *innerrel,
    1830             :                      JoinType jointype,
    1831             :                      JoinPathExtraData *extra)
    1832             : {
    1833             :     bool        nestjoinOK;
    1834             :     bool        useallclauses;
    1835      763798 :     Path       *inner_cheapest_total = innerrel->cheapest_total_path;
    1836      763798 :     Path       *matpath = NULL;
    1837             :     ListCell   *lc1;
    1838             : 
    1839             :     /*
    1840             :      * For now we do not support RIGHT_SEMI join in mergejoin or nestloop
    1841             :      * join.
    1842             :      */
    1843      763798 :     if (jointype == JOIN_RIGHT_SEMI)
    1844         102 :         return;
    1845             : 
    1846             :     /*
    1847             :      * Nestloop only supports inner, left, semi, and anti joins.  Also, if we
    1848             :      * are doing a right, right-anti or full mergejoin, we must use *all* the
    1849             :      * mergeclauses as join clauses, else we will not have a valid plan.
    1850             :      * (Although these two flags are currently inverses, keep them separate
    1851             :      * for clarity and possible future changes.)
    1852             :      */
    1853      763696 :     switch (jointype)
    1854             :     {
    1855      666688 :         case JOIN_INNER:
    1856             :         case JOIN_LEFT:
    1857             :         case JOIN_SEMI:
    1858             :         case JOIN_ANTI:
    1859      666688 :             nestjoinOK = true;
    1860      666688 :             useallclauses = false;
    1861      666688 :             break;
    1862       97008 :         case JOIN_RIGHT:
    1863             :         case JOIN_RIGHT_ANTI:
    1864             :         case JOIN_FULL:
    1865       97008 :             nestjoinOK = false;
    1866       97008 :             useallclauses = true;
    1867       97008 :             break;
    1868           0 :         default:
    1869           0 :             elog(ERROR, "unrecognized join type: %d",
    1870             :                  (int) jointype);
    1871             :             nestjoinOK = false; /* keep compiler quiet */
    1872             :             useallclauses = false;
    1873             :             break;
    1874             :     }
    1875             : 
    1876             :     /*
    1877             :      * If inner_cheapest_total is parameterized by the outer rel, ignore it;
    1878             :      * we will consider it below as a member of cheapest_parameterized_paths,
    1879             :      * but the other possibilities considered in this routine aren't usable.
    1880             :      *
    1881             :      * Furthermore, if the inner side is a unique-ified relation, we cannot
    1882             :      * generate any valid paths here, because the inner rel's dependency on
    1883             :      * the outer rel makes unique-ification meaningless.
    1884             :      */
    1885      763696 :     if (PATH_PARAM_BY_REL(inner_cheapest_total, outerrel))
    1886             :     {
    1887       15000 :         inner_cheapest_total = NULL;
    1888             : 
    1889       15000 :         if (RELATION_WAS_MADE_UNIQUE(innerrel, extra->sjinfo, jointype))
    1890          36 :             return;
    1891             :     }
    1892             : 
    1893      763660 :     if (nestjoinOK)
    1894             :     {
    1895             :         /*
    1896             :          * Consider materializing the cheapest inner path, unless that is
    1897             :          * disabled or the path in question materializes its output anyway.
    1898             :          */
    1899      666652 :         if ((extra->pgs_mask & PGS_NESTLOOP_MATERIALIZE) != 0 &&
    1900      649672 :             inner_cheapest_total != NULL &&
    1901      649672 :             !ExecMaterializesOutput(inner_cheapest_total->pathtype))
    1902             :             matpath = (Path *)
    1903      621452 :                 create_material_path(innerrel, inner_cheapest_total, true);
    1904             :     }
    1905             : 
    1906     2488838 :     foreach(lc1, outerrel->pathlist)
    1907             :     {
    1908     1725178 :         Path       *outerpath = (Path *) lfirst(lc1);
    1909             :         List       *merge_pathkeys;
    1910             : 
    1911             :         /*
    1912             :          * We cannot use an outer path that is parameterized by the inner rel.
    1913             :          */
    1914     1725178 :         if (PATH_PARAM_BY_REL(outerpath, innerrel))
    1915      269266 :             continue;
    1916             : 
    1917             :         /*
    1918             :          * The result will have this sort order (even if it is implemented as
    1919             :          * a nestloop, and even if some of the mergeclauses are implemented by
    1920             :          * qpquals rather than as true mergeclauses):
    1921             :          */
    1922     1455912 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    1923             :                                              outerpath->pathkeys);
    1924             : 
    1925     1455912 :         if (nestjoinOK)
    1926             :         {
    1927             :             /*
    1928             :              * Consider nestloop joins using this outer path and various
    1929             :              * available paths for the inner relation.  We consider the
    1930             :              * cheapest-total paths for each available parameterization of the
    1931             :              * inner relation, including the unparameterized case.
    1932             :              */
    1933             :             ListCell   *lc2;
    1934             : 
    1935     3271520 :             foreach(lc2, innerrel->cheapest_parameterized_paths)
    1936             :             {
    1937     1999636 :                 Path       *innerpath = (Path *) lfirst(lc2);
    1938             :                 Path       *mpath;
    1939             : 
    1940     1999636 :                 try_nestloop_path(root,
    1941             :                                   joinrel,
    1942             :                                   outerpath,
    1943             :                                   innerpath,
    1944             :                                   merge_pathkeys,
    1945             :                                   jointype,
    1946             :                                   PGS_NESTLOOP_PLAIN,
    1947             :                                   extra);
    1948             : 
    1949             :                 /*
    1950             :                  * Try generating a memoize path and see if that makes the
    1951             :                  * nested loop any cheaper.
    1952             :                  */
    1953     1999636 :                 mpath = get_memoize_path(root, innerrel, outerrel,
    1954             :                                          innerpath, outerpath, jointype,
    1955             :                                          extra);
    1956     1999636 :                 if (mpath != NULL)
    1957      314628 :                     try_nestloop_path(root,
    1958             :                                       joinrel,
    1959             :                                       outerpath,
    1960             :                                       mpath,
    1961             :                                       merge_pathkeys,
    1962             :                                       jointype,
    1963             :                                       PGS_NESTLOOP_MEMOIZE,
    1964             :                                       extra);
    1965             :             }
    1966             : 
    1967             :             /* Also consider materialized form of the cheapest inner path */
    1968     1271884 :             if (matpath != NULL)
    1969     1195020 :                 try_nestloop_path(root,
    1970             :                                   joinrel,
    1971             :                                   outerpath,
    1972             :                                   matpath,
    1973             :                                   merge_pathkeys,
    1974             :                                   jointype,
    1975             :                                   PGS_NESTLOOP_MATERIALIZE,
    1976             :                                   extra);
    1977             :         }
    1978             : 
    1979             :         /* Can't do anything else if inner rel is parameterized by outer */
    1980     1455912 :         if (inner_cheapest_total == NULL)
    1981       17890 :             continue;
    1982             : 
    1983             :         /* Generate merge join paths */
    1984     1438022 :         generate_mergejoin_paths(root, joinrel, innerrel, outerpath,
    1985             :                                  jointype, extra, useallclauses,
    1986             :                                  inner_cheapest_total, merge_pathkeys,
    1987             :                                  false);
    1988             :     }
    1989             : 
    1990             :     /*
    1991             :      * Consider partial nestloop and mergejoin plan if outerrel has any
    1992             :      * partial path and the joinrel is parallel-safe.  However, we can't
    1993             :      * handle joins needing lateral rels, since partial paths must not be
    1994             :      * parameterized.  Similarly, we can't handle JOIN_FULL, JOIN_RIGHT and
    1995             :      * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
    1996             :      */
    1997      763660 :     if (joinrel->consider_parallel &&
    1998      656546 :         jointype != JOIN_FULL &&
    1999      572036 :         jointype != JOIN_RIGHT &&
    2000      570534 :         jointype != JOIN_RIGHT_ANTI &&
    2001      570534 :         outerrel->partial_pathlist != NIL &&
    2002       74644 :         bms_is_empty(joinrel->lateral_relids))
    2003             :     {
    2004       74644 :         if (nestjoinOK)
    2005       74644 :             consider_parallel_nestloop(root, joinrel, outerrel, innerrel,
    2006             :                                        jointype, extra);
    2007             : 
    2008             :         /*
    2009             :          * If inner_cheapest_total is NULL or non parallel-safe then find the
    2010             :          * cheapest total parallel safe path.
    2011             :          */
    2012       74644 :         if (inner_cheapest_total == NULL ||
    2013       74224 :             !inner_cheapest_total->parallel_safe)
    2014             :         {
    2015             :             inner_cheapest_total =
    2016         876 :                 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    2017             :         }
    2018             : 
    2019       74644 :         if (inner_cheapest_total)
    2020       74182 :             consider_parallel_mergejoin(root, joinrel, outerrel, innerrel,
    2021             :                                         jointype, extra,
    2022             :                                         inner_cheapest_total);
    2023             :     }
    2024             : }
    2025             : 
    2026             : /*
    2027             :  * consider_parallel_mergejoin
    2028             :  *    Try to build partial paths for a joinrel by joining a partial path
    2029             :  *    for the outer relation to a complete path for the inner relation.
    2030             :  *
    2031             :  * 'joinrel' is the join relation
    2032             :  * 'outerrel' is the outer join relation
    2033             :  * 'innerrel' is the inner join relation
    2034             :  * 'jointype' is the type of join to do
    2035             :  * 'extra' contains additional input values
    2036             :  * 'inner_cheapest_total' cheapest total path for innerrel
    2037             :  */
    2038             : static void
    2039       74182 : consider_parallel_mergejoin(PlannerInfo *root,
    2040             :                             RelOptInfo *joinrel,
    2041             :                             RelOptInfo *outerrel,
    2042             :                             RelOptInfo *innerrel,
    2043             :                             JoinType jointype,
    2044             :                             JoinPathExtraData *extra,
    2045             :                             Path *inner_cheapest_total)
    2046             : {
    2047             :     ListCell   *lc1;
    2048             : 
    2049             :     /* generate merge join path for each partial outer path */
    2050      168254 :     foreach(lc1, outerrel->partial_pathlist)
    2051             :     {
    2052       94072 :         Path       *outerpath = (Path *) lfirst(lc1);
    2053             :         List       *merge_pathkeys;
    2054             : 
    2055             :         /*
    2056             :          * Figure out what useful ordering any paths we create will have.
    2057             :          */
    2058       94072 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    2059             :                                              outerpath->pathkeys);
    2060             : 
    2061       94072 :         generate_mergejoin_paths(root, joinrel, innerrel, outerpath, jointype,
    2062             :                                  extra, false, inner_cheapest_total,
    2063             :                                  merge_pathkeys, true);
    2064             :     }
    2065       74182 : }
    2066             : 
    2067             : /*
    2068             :  * consider_parallel_nestloop
    2069             :  *    Try to build partial paths for a joinrel by joining a partial path for the
    2070             :  *    outer relation to a complete path for the inner relation.
    2071             :  *
    2072             :  * 'joinrel' is the join relation
    2073             :  * 'outerrel' is the outer join relation
    2074             :  * 'innerrel' is the inner join relation
    2075             :  * 'jointype' is the type of join to do
    2076             :  * 'extra' contains additional input values
    2077             :  */
    2078             : static void
    2079       74644 : consider_parallel_nestloop(PlannerInfo *root,
    2080             :                            RelOptInfo *joinrel,
    2081             :                            RelOptInfo *outerrel,
    2082             :                            RelOptInfo *innerrel,
    2083             :                            JoinType jointype,
    2084             :                            JoinPathExtraData *extra)
    2085             : {
    2086       74644 :     Path       *inner_cheapest_total = innerrel->cheapest_total_path;
    2087       74644 :     Path       *matpath = NULL;
    2088             :     ListCell   *lc1;
    2089             : 
    2090             :     /*
    2091             :      * Consider materializing the cheapest inner path, unless: 1)
    2092             :      * materialization is disabled here, 2) the cheapest inner path is not
    2093             :      * parallel-safe, 3) the cheapest inner path is parameterized by the outer
    2094             :      * rel, or 4) the cheapest inner path materializes its output anyway.
    2095             :      */
    2096       74644 :     if ((extra->pgs_mask & PGS_NESTLOOP_MATERIALIZE) != 0 &&
    2097       73980 :         inner_cheapest_total->parallel_safe &&
    2098       73698 :         !PATH_PARAM_BY_REL(inner_cheapest_total, outerrel) &&
    2099       73308 :         !ExecMaterializesOutput(inner_cheapest_total->pathtype))
    2100             :     {
    2101             :         matpath = (Path *)
    2102       73212 :             create_material_path(innerrel, inner_cheapest_total, true);
    2103             :         Assert(matpath->parallel_safe);
    2104             :     }
    2105             : 
    2106      169316 :     foreach(lc1, outerrel->partial_pathlist)
    2107             :     {
    2108       94672 :         Path       *outerpath = (Path *) lfirst(lc1);
    2109             :         List       *pathkeys;
    2110             :         ListCell   *lc2;
    2111             : 
    2112             :         /* Figure out what useful ordering any paths we create will have. */
    2113       94672 :         pathkeys = build_join_pathkeys(root, joinrel, jointype,
    2114             :                                        outerpath->pathkeys);
    2115             : 
    2116             :         /*
    2117             :          * Try the cheapest parameterized paths; only those which will produce
    2118             :          * an unparameterized path when joined to this outerrel will survive
    2119             :          * try_partial_nestloop_path.  The cheapest unparameterized path is
    2120             :          * also in this list.
    2121             :          */
    2122      198448 :         foreach(lc2, innerrel->cheapest_parameterized_paths)
    2123             :         {
    2124      103776 :             Path       *innerpath = (Path *) lfirst(lc2);
    2125             :             Path       *mpath;
    2126             : 
    2127             :             /* Can't join to an inner path that is not parallel-safe */
    2128      103776 :             if (!innerpath->parallel_safe)
    2129         534 :                 continue;
    2130             : 
    2131      103242 :             try_partial_nestloop_path(root, joinrel, outerpath, innerpath,
    2132             :                                       pathkeys, jointype,
    2133             :                                       PGS_NESTLOOP_PLAIN, extra);
    2134             : 
    2135             :             /*
    2136             :              * Try generating a memoize path and see if that makes the nested
    2137             :              * loop any cheaper.
    2138             :              */
    2139      103242 :             mpath = get_memoize_path(root, innerrel, outerrel,
    2140             :                                      innerpath, outerpath, jointype,
    2141             :                                      extra);
    2142      103242 :             if (mpath != NULL)
    2143        5858 :                 try_partial_nestloop_path(root, joinrel, outerpath, mpath,
    2144             :                                           pathkeys, jointype,
    2145             :                                           PGS_NESTLOOP_MEMOIZE, extra);
    2146             :         }
    2147             : 
    2148             :         /* Also consider materialized form of the cheapest inner path */
    2149       94672 :         if (matpath != NULL)
    2150       92814 :             try_partial_nestloop_path(root, joinrel, outerpath, matpath,
    2151             :                                       pathkeys, jointype,
    2152             :                                       PGS_NESTLOOP_MATERIALIZE, extra);
    2153             :     }
    2154       74644 : }
    2155             : 
    2156             : /*
    2157             :  * hash_inner_and_outer
    2158             :  *    Create hashjoin join paths by explicitly hashing both the outer and
    2159             :  *    inner keys of each available hash clause.
    2160             :  *
    2161             :  * 'joinrel' is the join relation
    2162             :  * 'outerrel' is the outer join relation
    2163             :  * 'innerrel' is the inner join relation
    2164             :  * 'jointype' is the type of join to do
    2165             :  * 'extra' contains additional input values
    2166             :  */
    2167             : static void
    2168      776096 : hash_inner_and_outer(PlannerInfo *root,
    2169             :                      RelOptInfo *joinrel,
    2170             :                      RelOptInfo *outerrel,
    2171             :                      RelOptInfo *innerrel,
    2172             :                      JoinType jointype,
    2173             :                      JoinPathExtraData *extra)
    2174             : {
    2175      776096 :     bool        isouterjoin = IS_OUTER_JOIN(jointype);
    2176             :     List       *hashclauses;
    2177             :     ListCell   *l;
    2178             : 
    2179             :     /*
    2180             :      * We need to build only one hashclauses list for any given pair of outer
    2181             :      * and inner relations; all of the hashable clauses will be used as keys.
    2182             :      *
    2183             :      * Scan the join's restrictinfo list to find hashjoinable clauses that are
    2184             :      * usable with this pair of sub-relations.
    2185             :      */
    2186      776096 :     hashclauses = NIL;
    2187     1618464 :     foreach(l, extra->restrictlist)
    2188             :     {
    2189      842368 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
    2190             : 
    2191             :         /*
    2192             :          * If processing an outer join, only use its own join clauses for
    2193             :          * hashing.  For inner joins we need not be so picky.
    2194             :          */
    2195      842368 :         if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
    2196       10368 :             continue;
    2197             : 
    2198      832000 :         if (!restrictinfo->can_join ||
    2199      751576 :             restrictinfo->hashjoinoperator == InvalidOid)
    2200       98720 :             continue;           /* not hashjoinable */
    2201             : 
    2202             :         /*
    2203             :          * Check if clause has the form "outer op inner" or "inner op outer".
    2204             :          */
    2205      733280 :         if (!clause_sides_match_join(restrictinfo, outerrel->relids,
    2206             :                                      innerrel->relids))
    2207         216 :             continue;           /* no good for these input relations */
    2208             : 
    2209             :         /*
    2210             :          * If clause has the form "inner op outer", check if its operator has
    2211             :          * valid commutator.  This is necessary because hashclauses in this
    2212             :          * form will get commuted in createplan.c to put the outer var on the
    2213             :          * left (see get_switched_clauses).  This probably shouldn't ever
    2214             :          * fail, since hashable operators ought to have commutators, but be
    2215             :          * paranoid.
    2216             :          *
    2217             :          * The clause being hashjoinable indicates that it's an OpExpr.
    2218             :          */
    2219     1099596 :         if (!restrictinfo->outer_is_left &&
    2220      366532 :             !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
    2221           6 :             continue;
    2222             : 
    2223      733058 :         hashclauses = lappend(hashclauses, restrictinfo);
    2224             :     }
    2225             : 
    2226             :     /* If we found any usable hashclauses, make paths */
    2227      776096 :     if (hashclauses)
    2228             :     {
    2229             :         /*
    2230             :          * We consider both the cheapest-total-cost and cheapest-startup-cost
    2231             :          * outer paths.  There's no need to consider any but the
    2232             :          * cheapest-total-cost inner path, however.
    2233             :          */
    2234      653586 :         Path       *cheapest_startup_outer = outerrel->cheapest_startup_path;
    2235      653586 :         Path       *cheapest_total_outer = outerrel->cheapest_total_path;
    2236      653586 :         Path       *cheapest_total_inner = innerrel->cheapest_total_path;
    2237             :         ListCell   *lc1;
    2238             :         ListCell   *lc2;
    2239             : 
    2240             :         /*
    2241             :          * If either cheapest-total path is parameterized by the other rel, we
    2242             :          * can't use a hashjoin.  (There's no use looking for alternative
    2243             :          * input paths, since these should already be the least-parameterized
    2244             :          * available paths.)
    2245             :          */
    2246      653586 :         if (PATH_PARAM_BY_REL(cheapest_total_outer, innerrel) ||
    2247      652682 :             PATH_PARAM_BY_REL(cheapest_total_inner, outerrel))
    2248        1808 :             return;
    2249             : 
    2250             :         /*
    2251             :          * Consider the cheapest startup outer together with the cheapest
    2252             :          * total inner, and then consider pairings of cheapest-total paths
    2253             :          * including parameterized ones.  There is no use in generating
    2254             :          * parameterized paths on the basis of possibly cheap startup cost, so
    2255             :          * this is sufficient.
    2256             :          */
    2257      651778 :         if (cheapest_startup_outer != NULL)
    2258      649890 :             try_hashjoin_path(root,
    2259             :                               joinrel,
    2260             :                               cheapest_startup_outer,
    2261             :                               cheapest_total_inner,
    2262             :                               hashclauses,
    2263             :                               jointype,
    2264             :                               extra);
    2265             : 
    2266     1627742 :         foreach(lc1, outerrel->cheapest_parameterized_paths)
    2267             :         {
    2268      975964 :             Path       *outerpath = (Path *) lfirst(lc1);
    2269             : 
    2270             :             /*
    2271             :              * We cannot use an outer path that is parameterized by the inner
    2272             :              * rel.
    2273             :              */
    2274      975964 :             if (PATH_PARAM_BY_REL(outerpath, innerrel))
    2275      260704 :                 continue;
    2276             : 
    2277     1806914 :             foreach(lc2, innerrel->cheapest_parameterized_paths)
    2278             :             {
    2279     1091654 :                 Path       *innerpath = (Path *) lfirst(lc2);
    2280             : 
    2281             :                 /*
    2282             :                  * We cannot use an inner path that is parameterized by the
    2283             :                  * outer rel, either.
    2284             :                  */
    2285     1091654 :                 if (PATH_PARAM_BY_REL(innerpath, outerrel))
    2286      296808 :                     continue;
    2287             : 
    2288      794846 :                 if (outerpath == cheapest_startup_outer &&
    2289             :                     innerpath == cheapest_total_inner)
    2290      563742 :                     continue;   /* already tried it */
    2291             : 
    2292      231104 :                 try_hashjoin_path(root,
    2293             :                                   joinrel,
    2294             :                                   outerpath,
    2295             :                                   innerpath,
    2296             :                                   hashclauses,
    2297             :                                   jointype,
    2298             :                                   extra);
    2299             :             }
    2300             :         }
    2301             : 
    2302             :         /*
    2303             :          * If the joinrel is parallel-safe, we may be able to consider a
    2304             :          * partial hash join.
    2305             :          *
    2306             :          * However, we can't handle JOIN_RIGHT_SEMI, because the hash table is
    2307             :          * either a shared hash table or a private hash table per backend.  In
    2308             :          * the shared case, there is no concurrency protection for the match
    2309             :          * flags, so multiple workers could inspect and set the flags
    2310             :          * concurrently, potentially producing incorrect results.  In the
    2311             :          * private case, each worker has its own copy of the hash table, so no
    2312             :          * single process has all the match flags.
    2313             :          *
    2314             :          * Also, the resulting path must not be parameterized.
    2315             :          */
    2316      651778 :         if (joinrel->consider_parallel &&
    2317      585730 :             jointype != JOIN_RIGHT_SEMI &&
    2318      585730 :             outerrel->partial_pathlist != NIL &&
    2319       76862 :             bms_is_empty(joinrel->lateral_relids))
    2320             :         {
    2321             :             Path       *cheapest_partial_outer;
    2322       76862 :             Path       *cheapest_partial_inner = NULL;
    2323       76862 :             Path       *cheapest_safe_inner = NULL;
    2324             : 
    2325       76862 :             cheapest_partial_outer =
    2326       76862 :                 (Path *) linitial(outerrel->partial_pathlist);
    2327             : 
    2328             :             /*
    2329             :              * Can we use a partial inner plan too, so that we can build a
    2330             :              * shared hash table in parallel?
    2331             :              */
    2332       76862 :             if (innerrel->partial_pathlist != NIL &&
    2333             :                 enable_parallel_hash)
    2334             :             {
    2335       75186 :                 cheapest_partial_inner =
    2336       75186 :                     (Path *) linitial(innerrel->partial_pathlist);
    2337       75186 :                 try_partial_hashjoin_path(root, joinrel,
    2338             :                                           cheapest_partial_outer,
    2339             :                                           cheapest_partial_inner,
    2340             :                                           hashclauses, jointype, extra,
    2341             :                                           true /* parallel_hash */ );
    2342             :             }
    2343             : 
    2344             :             /*
    2345             :              * Normally, given that the joinrel is parallel-safe, the cheapest
    2346             :              * total inner path will also be parallel-safe, but if not, we'll
    2347             :              * have to search for the cheapest safe, unparameterized inner
    2348             :              * path.  If full, right, or right-anti join, we can't use
    2349             :              * parallelism (building the hash table in each backend) because
    2350             :              * no one process has all the match bits.
    2351             :              */
    2352       76862 :             if (jointype == JOIN_FULL ||
    2353       73046 :                 jointype == JOIN_RIGHT ||
    2354             :                 jointype == JOIN_RIGHT_ANTI)
    2355        4146 :                 cheapest_safe_inner = NULL;
    2356       72716 :             else if (cheapest_total_inner->parallel_safe)
    2357       72404 :                 cheapest_safe_inner = cheapest_total_inner;
    2358             :             else
    2359             :                 cheapest_safe_inner =
    2360         312 :                     get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    2361             : 
    2362       76862 :             if (cheapest_safe_inner != NULL)
    2363       72674 :                 try_partial_hashjoin_path(root, joinrel,
    2364             :                                           cheapest_partial_outer,
    2365             :                                           cheapest_safe_inner,
    2366             :                                           hashclauses, jointype, extra,
    2367             :                                           false /* parallel_hash */ );
    2368             :         }
    2369             :     }
    2370             : }
    2371             : 
    2372             : /*
    2373             :  * select_mergejoin_clauses
    2374             :  *    Select mergejoin clauses that are usable for a particular join.
    2375             :  *    Returns a list of RestrictInfo nodes for those clauses.
    2376             :  *
    2377             :  * *mergejoin_allowed is normally set to true, but it is set to false if
    2378             :  * this is a right-semi join, or this is a right/right-anti/full join and
    2379             :  * there are nonmergejoinable join clauses.  The executor's mergejoin
    2380             :  * machinery cannot handle such cases, so we have to avoid generating a
    2381             :  * mergejoin plan.  (Note that this flag does NOT consider whether there are
    2382             :  * actually any mergejoinable clauses.  This is correct because in some
    2383             :  * cases we need to build a clauseless mergejoin.  Simply returning NIL is
    2384             :  * therefore not enough to distinguish safe from unsafe cases.)
    2385             :  *
    2386             :  * We also mark each selected RestrictInfo to show which side is currently
    2387             :  * being considered as outer.  These are transient markings that are only
    2388             :  * good for the duration of the current add_paths_to_joinrel() call!
    2389             :  *
    2390             :  * We examine each restrictinfo clause known for the join to see
    2391             :  * if it is mergejoinable and involves vars from the two sub-relations
    2392             :  * currently of interest.
    2393             :  */
    2394             : static List *
    2395      777496 : select_mergejoin_clauses(PlannerInfo *root,
    2396             :                          RelOptInfo *joinrel,
    2397             :                          RelOptInfo *outerrel,
    2398             :                          RelOptInfo *innerrel,
    2399             :                          List *restrictlist,
    2400             :                          JoinType jointype,
    2401             :                          bool *mergejoin_allowed)
    2402             : {
    2403      777496 :     List       *result_list = NIL;
    2404      777496 :     bool        isouterjoin = IS_OUTER_JOIN(jointype);
    2405      777496 :     bool        have_nonmergeable_joinclause = false;
    2406             :     ListCell   *l;
    2407             : 
    2408             :     /*
    2409             :      * For now we do not support RIGHT_SEMI join in mergejoin: the benefit of
    2410             :      * swapping inputs tends to be small here.
    2411             :      */
    2412      777496 :     if (jointype == JOIN_RIGHT_SEMI)
    2413             :     {
    2414        7550 :         *mergejoin_allowed = false;
    2415        7550 :         return NIL;
    2416             :     }
    2417             : 
    2418     1607444 :     foreach(l, restrictlist)
    2419             :     {
    2420      837498 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
    2421             : 
    2422             :         /*
    2423             :          * If processing an outer join, only use its own join clauses in the
    2424             :          * merge.  For inner joins we can use pushed-down clauses too. (Note:
    2425             :          * we don't set have_nonmergeable_joinclause here because pushed-down
    2426             :          * clauses will become otherquals not joinquals.)
    2427             :          */
    2428      837498 :         if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
    2429       10392 :             continue;
    2430             : 
    2431             :         /* Check that clause is a mergeable operator clause */
    2432      827106 :         if (!restrictinfo->can_join ||
    2433      746700 :             restrictinfo->mergeopfamilies == NIL)
    2434             :         {
    2435             :             /*
    2436             :              * The executor can handle extra joinquals that are constants, but
    2437             :              * not anything else, when doing right/right-anti/full merge join.
    2438             :              * (The reason to support constants is so we can do FULL JOIN ON
    2439             :              * FALSE.)
    2440             :              */
    2441       97236 :             if (!restrictinfo->clause || !IsA(restrictinfo->clause, Const))
    2442       86908 :                 have_nonmergeable_joinclause = true;
    2443       97236 :             continue;           /* not mergejoinable */
    2444             :         }
    2445             : 
    2446             :         /*
    2447             :          * Check if clause has the form "outer op inner" or "inner op outer".
    2448             :          */
    2449      729870 :         if (!clause_sides_match_join(restrictinfo, outerrel->relids,
    2450             :                                      innerrel->relids))
    2451             :         {
    2452        1008 :             have_nonmergeable_joinclause = true;
    2453        1008 :             continue;           /* no good for these input relations */
    2454             :         }
    2455             : 
    2456             :         /*
    2457             :          * If clause has the form "inner op outer", check if its operator has
    2458             :          * valid commutator.  This is necessary because mergejoin clauses in
    2459             :          * this form will get commuted in createplan.c to put the outer var on
    2460             :          * the left (see get_switched_clauses).  This probably shouldn't ever
    2461             :          * fail, since mergejoinable operators ought to have commutators, but
    2462             :          * be paranoid.
    2463             :          *
    2464             :          * The clause being mergejoinable indicates that it's an OpExpr.
    2465             :          */
    2466     1090346 :         if (!restrictinfo->outer_is_left &&
    2467      361484 :             !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
    2468             :         {
    2469          36 :             have_nonmergeable_joinclause = true;
    2470          36 :             continue;
    2471             :         }
    2472             : 
    2473             :         /*
    2474             :          * Insist that each side have a non-redundant eclass.  This
    2475             :          * restriction is needed because various bits of the planner expect
    2476             :          * that each clause in a merge be associable with some pathkey in a
    2477             :          * canonical pathkey list, but redundant eclasses can't appear in
    2478             :          * canonical sort orderings.  (XXX it might be worth relaxing this,
    2479             :          * but not enough time to address it for 8.3.)
    2480             :          */
    2481      728826 :         update_mergeclause_eclasses(root, restrictinfo);
    2482             : 
    2483      728826 :         if (EC_MUST_BE_REDUNDANT(restrictinfo->left_ec) ||
    2484      728778 :             EC_MUST_BE_REDUNDANT(restrictinfo->right_ec))
    2485             :         {
    2486         128 :             have_nonmergeable_joinclause = true;
    2487         128 :             continue;           /* can't handle redundant eclasses */
    2488             :         }
    2489             : 
    2490      728698 :         result_list = lappend(result_list, restrictinfo);
    2491             :     }
    2492             : 
    2493             :     /*
    2494             :      * Report whether mergejoin is allowed (see comment at top of function).
    2495             :      */
    2496      769946 :     switch (jointype)
    2497             :     {
    2498      106830 :         case JOIN_RIGHT:
    2499             :         case JOIN_RIGHT_ANTI:
    2500             :         case JOIN_FULL:
    2501      106830 :             *mergejoin_allowed = !have_nonmergeable_joinclause;
    2502      106830 :             break;
    2503      663116 :         default:
    2504      663116 :             *mergejoin_allowed = true;
    2505      663116 :             break;
    2506             :     }
    2507             : 
    2508      769946 :     return result_list;
    2509             : }

Generated by: LCOV version 1.16