LCOV - code coverage report
Current view: top level - src/backend/optimizer/path - joinpath.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 97.9 % 536 525
Test Date: 2026-03-21 22:15:55 Functions: 100.0 % 18 18
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       627972 : 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       627972 :     JoinType    save_jointype = jointype;
     132              :     JoinPathExtraData extra;
     133       627972 :     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       627972 :     if (joinrel->reloptkind == RELOPT_OTHER_JOINREL)
     145        54278 :         joinrelids = joinrel->top_parent_relids;
     146              :     else
     147       573694 :         joinrelids = joinrel->relids;
     148              : 
     149       627972 :     extra.restrictlist = restrictlist;
     150       627972 :     extra.mergeclause_list = NIL;
     151       627972 :     extra.sjinfo = sjinfo;
     152       627972 :     extra.param_source_rels = NULL;
     153       627972 :     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       627972 :     if (join_path_setup_hook)
     178       154676 :         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       627972 :     switch (jointype)
     201              :     {
     202         5934 :         case JOIN_SEMI:
     203         5934 :             extra.inner_unique = false; /* well, unproven */
     204         5934 :             break;
     205         4794 :         case JOIN_UNIQUE_INNER:
     206         9588 :             extra.inner_unique = bms_is_subset(sjinfo->min_lefthand,
     207         4794 :                                                outerrel->relids);
     208         4794 :             break;
     209         4794 :         case JOIN_UNIQUE_OUTER:
     210         4794 :             extra.inner_unique = innerrel_is_unique(root,
     211              :                                                     joinrel->relids,
     212              :                                                     outerrel->relids,
     213              :                                                     innerrel,
     214              :                                                     JOIN_INNER,
     215              :                                                     restrictlist,
     216              :                                                     false);
     217         4794 :             break;
     218       612450 :         default:
     219       612450 :             extra.inner_unique = innerrel_is_unique(root,
     220              :                                                     joinrel->relids,
     221              :                                                     outerrel->relids,
     222              :                                                     innerrel,
     223              :                                                     jointype,
     224              :                                                     restrictlist,
     225              :                                                     false);
     226       612450 :             break;
     227              :     }
     228              : 
     229              :     /*
     230              :      * If the outer or inner relation has been unique-ified, handle as a plain
     231              :      * inner join.
     232              :      */
     233       627972 :     if (jointype == JOIN_UNIQUE_OUTER || jointype == JOIN_UNIQUE_INNER)
     234         9588 :         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       627972 :     if ((extra.pgs_mask & PGS_MERGEJOIN_ANY) != 0 || jointype == JOIN_FULL)
     243       553686 :         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       627972 :     if (jointype == JOIN_SEMI || jointype == JOIN_ANTI || extra.inner_unique)
     256       183397 :         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      1150274 :     foreach(lc, root->join_info_list)
     275              :     {
     276       522302 :         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       522302 :         if (bms_overlap(joinrelids, sjinfo2->min_righthand) &&
     286       345824 :             !bms_overlap(joinrelids, sjinfo2->min_lefthand))
     287        15260 :             extra.param_source_rels = bms_join(extra.param_source_rels,
     288        15260 :                                                bms_difference(root->all_baserels,
     289        15260 :                                                               sjinfo2->min_righthand));
     290              : 
     291              :         /* full joins constrain both sides symmetrically */
     292       526236 :         if (sjinfo2->jointype == JOIN_FULL &&
     293         3934 :             bms_overlap(joinrelids, sjinfo2->min_lefthand) &&
     294         3898 :             !bms_overlap(joinrelids, sjinfo2->min_righthand))
     295          536 :             extra.param_source_rels = bms_join(extra.param_source_rels,
     296          536 :                                                bms_difference(root->all_baserels,
     297          536 :                                                               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      1255944 :     extra.param_source_rels = bms_add_members(extra.param_source_rels,
     308       627972 :                                               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       627972 :     if (mergejoin_allowed)
     315       616428 :         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       627972 :     if (mergejoin_allowed)
     327       616428 :         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       627972 :     if ((extra.pgs_mask & PGS_HASHJOIN) != 0 || jointype == JOIN_FULL)
     354       560369 :         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       627972 :     if ((extra.pgs_mask & PGS_FOREIGNJOIN) != 0 && joinrel->fdwroutine &&
     363         1362 :         joinrel->fdwroutine->GetForeignJoinPaths)
     364         1360 :         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       627972 :     if (set_join_pathlist_hook)
     380            0 :         set_join_pathlist_hook(root, joinrel, outerrel, innerrel,
     381              :                                save_jointype, &extra);
     382       627972 : }
     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       248131 : 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       291216 :     return (bms_overlap(inner_paramrels, outerrelids) &&
     409        43085 :             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       277551 : 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       277551 :     *param_exprs = NIL;
     486       277551 :     *operators = NIL;
     487       277551 :     *binary_mode = false;
     488              : 
     489              :     /* Add join clauses from param_info to the hash key */
     490       277551 :     if (param_info != NULL)
     491              :     {
     492       277551 :         List       *clauses = param_info->ppi_clauses;
     493              : 
     494       521124 :         foreach(lc, clauses)
     495              :         {
     496       301292 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     497              :             OpExpr     *opexpr;
     498              :             Node       *expr;
     499              :             Oid         hasheqoperator;
     500              : 
     501       301292 :             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       301292 :             if (!IsA(opexpr, OpExpr) || list_length(opexpr->args) != 2 ||
     508       289244 :                 !clause_sides_match_join(rinfo, outerrel->relids,
     509              :                                          innerrel->relids))
     510              :             {
     511        57659 :                 list_free(*operators);
     512        57659 :                 list_free(*param_exprs);
     513        57719 :                 return false;
     514              :             }
     515              : 
     516       243633 :             if (rinfo->outer_is_left)
     517              :             {
     518       138043 :                 expr = (Node *) linitial(opexpr->args);
     519       138043 :                 hasheqoperator = rinfo->left_hasheqoperator;
     520              :             }
     521              :             else
     522              :             {
     523       105590 :                 expr = (Node *) lsecond(opexpr->args);
     524       105590 :                 hasheqoperator = rinfo->right_hasheqoperator;
     525              :             }
     526              : 
     527              :             /* can't do memoize if we can't hash the outer type */
     528       243633 :             if (!OidIsValid(hasheqoperator))
     529              :             {
     530           60 :                 list_free(*operators);
     531           60 :                 list_free(*param_exprs);
     532           60 :                 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       243573 :             if (!list_member(*param_exprs, expr))
     541              :             {
     542       243569 :                 *operators = lappend_oid(*operators, hasheqoperator);
     543       243569 :                 *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       243573 :             if (!OidIsValid(rinfo->hashjoinoperator))
     558          747 :                 *binary_mode = true;
     559              :         }
     560              :     }
     561              : 
     562              :     /* Now add any lateral vars to the cache key too */
     563       219832 :     lateral_vars = list_concat(ph_lateral_vars, innerrel->lateral_vars);
     564       225420 :     foreach(lc, lateral_vars)
     565              :     {
     566         6352 :         Node       *expr = (Node *) lfirst(lc);
     567              :         TypeCacheEntry *typentry;
     568              : 
     569              :         /* Reject if there are any volatile functions in lateral vars */
     570         6352 :         if (contain_volatile_functions(expr))
     571              :         {
     572            0 :             list_free(*operators);
     573            0 :             list_free(*param_exprs);
     574          764 :             return false;
     575              :         }
     576              : 
     577         6352 :         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         6352 :         if (!OidIsValid(typentry->hash_proc) || !OidIsValid(typentry->eq_opr))
     582              :         {
     583          764 :             list_free(*operators);
     584          764 :             list_free(*param_exprs);
     585          764 :             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         5588 :         if (!list_member(*param_exprs, expr))
     594              :         {
     595         5262 :             *operators = lappend_oid(*operators, typentry->eq_opr);
     596         5262 :             *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         5588 :         *binary_mode = true;
     609              :     }
     610              : 
     611              :     /* We're okay to use memoize */
     612       219068 :     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      1069732 : extract_lateral_vars_from_PHVs(PlannerInfo *root, Relids innerrelids)
     622              : {
     623      1069732 :     List       *ph_lateral_vars = NIL;
     624              :     ListCell   *lc;
     625              : 
     626              :     /* Nothing would be found if the query contains no LATERAL RTEs */
     627      1069732 :     if (!root->hasLateralRTEs)
     628      1024343 :         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        45389 :     if (bms_membership(innerrelids) == BMS_MULTIPLE)
     635        18515 :         return NIL;
     636              : 
     637        28796 :     foreach(lc, root->placeholder_list)
     638              :     {
     639         1922 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
     640              :         List       *vars;
     641              :         ListCell   *cell;
     642              : 
     643              :         /* PHV is uninteresting if no lateral refs */
     644         1922 :         if (phinfo->ph_lateral == NULL)
     645         1102 :             continue;
     646              : 
     647              :         /* PHV is uninteresting if not due to be evaluated at innerrelids */
     648          820 :         if (!bms_equal(phinfo->ph_eval_at, innerrelids))
     649          654 :             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          166 :         if (!bms_overlap(pull_varnos(root, (Node *) phinfo->ph_var->phexpr),
     659              :                          innerrelids))
     660              :         {
     661          158 :             ph_lateral_vars = lappend(ph_lateral_vars, phinfo->ph_var->phexpr);
     662          158 :             continue;
     663              :         }
     664              : 
     665              :         /* Fetch Vars and PHVs of lateral references within PlaceHolderVars */
     666            8 :         vars = pull_vars_of_level((Node *) phinfo->ph_var->phexpr, 0);
     667           24 :         foreach(cell, vars)
     668              :         {
     669           16 :             Node       *node = (Node *) lfirst(cell);
     670              : 
     671           16 :             if (IsA(node, Var))
     672              :             {
     673            8 :                 Var        *var = (Var *) node;
     674              : 
     675              :                 Assert(var->varlevelsup == 0);
     676              : 
     677            8 :                 if (bms_is_member(var->varno, phinfo->ph_lateral))
     678            0 :                     ph_lateral_vars = lappend(ph_lateral_vars, node);
     679              :             }
     680            8 :             else if (IsA(node, PlaceHolderVar))
     681              :             {
     682            8 :                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
     683              : 
     684              :                 Assert(phv->phlevelsup == 0);
     685              : 
     686            8 :                 if (bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
     687            8 :                                   phinfo->ph_lateral))
     688            8 :                     ph_lateral_vars = lappend(ph_lateral_vars, node);
     689              :             }
     690              :             else
     691              :                 Assert(false);
     692              :         }
     693              : 
     694            8 :         list_free(vars);
     695              :     }
     696              : 
     697        26874 :     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      1668719 : 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      1668719 :     if ((extra->pgs_mask & PGS_NESTLOOP_MEMOIZE) == 0)
     725       163984 :         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      1504735 :     if (outer_path->parent->rows < 2)
     734       435003 :         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      1069732 :     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      1069732 :     if ((inner_path->param_info == NULL ||
     749       382897 :          inner_path->param_info->ppi_clauses == NIL) &&
     750       712564 :         innerrel->lateral_vars == NIL &&
     751              :         ph_lateral_vars == NIL)
     752       707752 :         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       361980 :     if ((jointype == JOIN_SEMI || jointype == JOIN_ANTI) &&
     769        10362 :         !extra->inner_unique)
     770         4531 :         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       357449 :     if (extra->inner_unique)
     795              :     {
     796              :         Bitmapset  *ppi_serials;
     797              : 
     798       215655 :         if (inner_path->param_info == NULL)
     799            0 :             return NULL;
     800              : 
     801       215655 :         ppi_serials = inner_path->param_info->ppi_serials;
     802              : 
     803       513825 :         foreach_node(RestrictInfo, rinfo, extra->restrictlist)
     804              :         {
     805       242101 :             if (!bms_is_member(rinfo->rinfo_serial, ppi_serials))
     806        79793 :                 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       277656 :     if (contain_volatile_functions((Node *) innerrel->reltarget))
     816            0 :         return NULL;
     817              : 
     818       458071 :     foreach(lc, innerrel->baserestrictinfo)
     819              :     {
     820       180519 :         RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     821              : 
     822       180519 :         if (contain_volatile_functions((Node *) rinfo))
     823          104 :             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       277552 :     if (inner_path->param_info != NULL)
     833              :     {
     834       599967 :         foreach(lc, inner_path->param_info->ppi_clauses)
     835              :         {
     836       322416 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
     837              : 
     838       322416 :             if (contain_volatile_functions((Node *) rinfo))
     839            1 :                 return NULL;
     840              :         }
     841              :     }
     842              : 
     843              :     /* Check if we have hash ops for each parameter to the path */
     844       277551 :     if (paraminfo_get_equal_hashops(root,
     845              :                                     inner_path->param_info,
     846       277551 :                                     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       219068 :         return (Path *) create_memoize_path(root,
     855              :                                             innerrel,
     856              :                                             inner_path,
     857              :                                             param_exprs,
     858              :                                             hash_operators,
     859       219068 :                                             extra->inner_unique,
     860              :                                             binary_mode,
     861              :                                             outer_path->rows);
     862              :     }
     863              : 
     864        58483 :     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      2661282 : 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      2661282 :     RelOptInfo *innerrel = inner_path->parent;
     885      2661282 :     RelOptInfo *outerrel = outer_path->parent;
     886              :     Relids      innerrelids;
     887              :     Relids      outerrelids;
     888      2661282 :     Relids      inner_paramrels = PATH_REQ_OUTER(inner_path);
     889      2661282 :     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      3114747 :     if (extra->sjinfo->ojrelid != 0 &&
     898       906930 :         (bms_is_member(extra->sjinfo->ojrelid, inner_paramrels) ||
     899       453465 :          bms_is_member(extra->sjinfo->ojrelid, outer_paramrels)))
     900       244281 :         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      2661182 :     if (innerrel->top_parent_relids)
     910       134037 :         innerrelids = innerrel->top_parent_relids;
     911              :     else
     912      2527145 :         innerrelids = innerrel->relids;
     913              : 
     914      2661182 :     if (outerrel->top_parent_relids)
     915       134037 :         outerrelids = outerrel->top_parent_relids;
     916              :     else
     917      2527145 :         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      2661182 :     required_outer = calc_nestloop_required_outer(outerrelids, outer_paramrels,
     925              :                                                   innerrelids, inner_paramrels);
     926      2661182 :     if (required_outer &&
     927       287101 :         !bms_overlap(required_outer, extra->param_source_rels) &&
     928       248131 :         !allow_star_schema_join(root, outerrelids, inner_paramrels))
     929              :     {
     930              :         /* Waste no memory when we reject a path here */
     931       244181 :         bms_free(required_outer);
     932       244181 :         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      2417001 :     if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
     946        10645 :         !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      2417001 :     initial_cost_nestloop(root, &workspace, jointype,
     962              :                           nestloop_subtype | PGS_CONSIDER_NONPARTIAL,
     963              :                           outer_path, inner_path, extra);
     964              : 
     965      2417001 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
     966              :                           workspace.startup_cost, workspace.total_cost,
     967              :                           pathkeys, required_outer))
     968              :     {
     969      1111258 :         add_path(joinrel, (Path *)
     970      1111258 :                  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      1305743 :         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       157787 : 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       157787 :     if (inner_path->param_info != NULL)
    1014              :     {
    1015        12346 :         Relids      inner_paramrels = inner_path->param_info->ppi_req_outer;
    1016        12346 :         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        12346 :         if (outerrel->top_parent_relids)
    1025         8708 :             outerrelids = outerrel->top_parent_relids;
    1026              :         else
    1027         3638 :             outerrelids = outerrel->relids;
    1028              : 
    1029        12346 :         if (!bms_is_subset(inner_paramrels, outerrelids))
    1030       119493 :             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       156610 :     if (PATH_PARAM_BY_PARENT(inner_path, outer_path->parent) &&
    1041         7920 :         !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       156610 :     initial_cost_nestloop(root, &workspace, jointype, nestloop_subtype,
    1049              :                           outer_path, inner_path, extra);
    1050       156610 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1051              :                                    workspace.startup_cost,
    1052              :                                    workspace.total_cost, pathkeys))
    1053       118316 :         return;
    1054              : 
    1055              :     /* Might be good enough to be worth trying, so let's try it. */
    1056        38294 :     add_partial_path(joinrel, (Path *)
    1057        38294 :                      create_nestloop_path(root,
    1058              :                                           joinrel,
    1059              :                                           jointype,
    1060              :                                           &workspace,
    1061              :                                           extra,
    1062              :                                           outer_path,
    1063              :                                           inner_path,
    1064              :                                           extra->restrictlist,
    1065              :                                           pathkeys,
    1066              :                                           NULL));
    1067              : }
    1068              : 
    1069              : /*
    1070              :  * try_mergejoin_path
    1071              :  *    Consider a merge join path; if it appears useful, push it into
    1072              :  *    the joinrel's pathlist via add_path().
    1073              :  */
    1074              : static void
    1075      1093223 : try_mergejoin_path(PlannerInfo *root,
    1076              :                    RelOptInfo *joinrel,
    1077              :                    Path *outer_path,
    1078              :                    Path *inner_path,
    1079              :                    List *pathkeys,
    1080              :                    List *mergeclauses,
    1081              :                    List *outersortkeys,
    1082              :                    List *innersortkeys,
    1083              :                    JoinType jointype,
    1084              :                    JoinPathExtraData *extra,
    1085              :                    bool is_partial)
    1086              : {
    1087              :     Relids      required_outer;
    1088      1093223 :     int         outer_presorted_keys = 0;
    1089              :     JoinCostWorkspace workspace;
    1090              : 
    1091      1093223 :     if (is_partial)
    1092              :     {
    1093        16441 :         try_partial_mergejoin_path(root,
    1094              :                                    joinrel,
    1095              :                                    outer_path,
    1096              :                                    inner_path,
    1097              :                                    pathkeys,
    1098              :                                    mergeclauses,
    1099              :                                    outersortkeys,
    1100              :                                    innersortkeys,
    1101              :                                    jointype,
    1102              :                                    extra);
    1103        45695 :         return;
    1104              :     }
    1105              : 
    1106              :     /*
    1107              :      * If we are forming an outer join at this join, it's nonsensical to use
    1108              :      * an input path that uses the outer join as part of its parameterization.
    1109              :      * (This can happen despite our join order restrictions, since those apply
    1110              :      * to what is in an input relation not what its parameters are.)
    1111              :      */
    1112      1326746 :     if (extra->sjinfo->ojrelid != 0 &&
    1113       499928 :         (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
    1114       249964 :          bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
    1115           10 :         return;
    1116              : 
    1117              :     /*
    1118              :      * Check to see if proposed path is still parameterized, and reject if the
    1119              :      * parameterization wouldn't be sensible.
    1120              :      */
    1121      1076772 :     required_outer = calc_non_nestloop_required_outer(outer_path,
    1122              :                                                       inner_path);
    1123      1076772 :     if (required_outer &&
    1124        34859 :         !bms_overlap(required_outer, extra->param_source_rels))
    1125              :     {
    1126              :         /* Waste no memory when we reject a path here */
    1127        29244 :         bms_free(required_outer);
    1128        29244 :         return;
    1129              :     }
    1130              : 
    1131              :     /*
    1132              :      * If the given paths are already well enough ordered, we can skip doing
    1133              :      * an explicit sort.
    1134              :      *
    1135              :      * We need to determine the number of presorted keys of the outer path to
    1136              :      * decide whether explicit incremental sort can be applied when
    1137              :      * outersortkeys is not NIL.  We do not need to do the same for the inner
    1138              :      * path though, as incremental sort currently does not support
    1139              :      * mark/restore.
    1140              :      */
    1141      1577839 :     if (outersortkeys &&
    1142       530311 :         pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
    1143              :                                     &outer_presorted_keys))
    1144        13376 :         outersortkeys = NIL;
    1145      1898863 :     if (innersortkeys &&
    1146       851335 :         pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
    1147        23001 :         innersortkeys = NIL;
    1148              : 
    1149              :     /*
    1150              :      * See comments in try_nestloop_path().
    1151              :      */
    1152      1047528 :     initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
    1153              :                            outer_path, inner_path,
    1154              :                            outersortkeys, innersortkeys,
    1155              :                            outer_presorted_keys,
    1156              :                            extra);
    1157              : 
    1158      1047528 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
    1159              :                           workspace.startup_cost, workspace.total_cost,
    1160              :                           pathkeys, required_outer))
    1161              :     {
    1162       298327 :         add_path(joinrel, (Path *)
    1163       298327 :                  create_mergejoin_path(root,
    1164              :                                        joinrel,
    1165              :                                        jointype,
    1166              :                                        &workspace,
    1167              :                                        extra,
    1168              :                                        outer_path,
    1169              :                                        inner_path,
    1170              :                                        extra->restrictlist,
    1171              :                                        pathkeys,
    1172              :                                        required_outer,
    1173              :                                        mergeclauses,
    1174              :                                        outersortkeys,
    1175              :                                        innersortkeys,
    1176              :                                        outer_presorted_keys));
    1177              :     }
    1178              :     else
    1179              :     {
    1180              :         /* Waste no memory when we reject a path here */
    1181       749201 :         bms_free(required_outer);
    1182              :     }
    1183              : }
    1184              : 
    1185              : /*
    1186              :  * try_partial_mergejoin_path
    1187              :  *    Consider a partial merge join path; if it appears useful, push it into
    1188              :  *    the joinrel's pathlist via add_partial_path().
    1189              :  */
    1190              : static void
    1191        71677 : try_partial_mergejoin_path(PlannerInfo *root,
    1192              :                            RelOptInfo *joinrel,
    1193              :                            Path *outer_path,
    1194              :                            Path *inner_path,
    1195              :                            List *pathkeys,
    1196              :                            List *mergeclauses,
    1197              :                            List *outersortkeys,
    1198              :                            List *innersortkeys,
    1199              :                            JoinType jointype,
    1200              :                            JoinPathExtraData *extra)
    1201              : {
    1202        71677 :     int         outer_presorted_keys = 0;
    1203              :     JoinCostWorkspace workspace;
    1204              : 
    1205              :     /*
    1206              :      * See comments in try_partial_hashjoin_path().
    1207              :      */
    1208              :     Assert(bms_is_empty(joinrel->lateral_relids));
    1209              :     Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
    1210        71677 :     if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
    1211        24475 :         return;
    1212              : 
    1213              :     /*
    1214              :      * If the given paths are already well enough ordered, we can skip doing
    1215              :      * an explicit sort.
    1216              :      *
    1217              :      * We need to determine the number of presorted keys of the outer path to
    1218              :      * decide whether explicit incremental sort can be applied when
    1219              :      * outersortkeys is not NIL.  We do not need to do the same for the inner
    1220              :      * path though, as incremental sort currently does not support
    1221              :      * mark/restore.
    1222              :      */
    1223       126913 :     if (outersortkeys &&
    1224        55236 :         pathkeys_count_contained_in(outersortkeys, outer_path->pathkeys,
    1225              :                                     &outer_presorted_keys))
    1226          135 :         outersortkeys = NIL;
    1227       141210 :     if (innersortkeys &&
    1228        69533 :         pathkeys_contained_in(innersortkeys, inner_path->pathkeys))
    1229          450 :         innersortkeys = NIL;
    1230              : 
    1231              :     /*
    1232              :      * See comments in try_partial_nestloop_path().
    1233              :      */
    1234        71677 :     initial_cost_mergejoin(root, &workspace, jointype, mergeclauses,
    1235              :                            outer_path, inner_path,
    1236              :                            outersortkeys, innersortkeys,
    1237              :                            outer_presorted_keys,
    1238              :                            extra);
    1239              : 
    1240        71677 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1241              :                                    workspace.startup_cost,
    1242              :                                    workspace.total_cost, pathkeys))
    1243        24475 :         return;
    1244              : 
    1245              :     /* Might be good enough to be worth trying, so let's try it. */
    1246        47202 :     add_partial_path(joinrel, (Path *)
    1247        47202 :                      create_mergejoin_path(root,
    1248              :                                            joinrel,
    1249              :                                            jointype,
    1250              :                                            &workspace,
    1251              :                                            extra,
    1252              :                                            outer_path,
    1253              :                                            inner_path,
    1254              :                                            extra->restrictlist,
    1255              :                                            pathkeys,
    1256              :                                            NULL,
    1257              :                                            mergeclauses,
    1258              :                                            outersortkeys,
    1259              :                                            innersortkeys,
    1260              :                                            outer_presorted_keys));
    1261              : }
    1262              : 
    1263              : /*
    1264              :  * try_hashjoin_path
    1265              :  *    Consider a hash join path; if it appears useful, push it into
    1266              :  *    the joinrel's pathlist via add_path().
    1267              :  */
    1268              : static void
    1269       636644 : try_hashjoin_path(PlannerInfo *root,
    1270              :                   RelOptInfo *joinrel,
    1271              :                   Path *outer_path,
    1272              :                   Path *inner_path,
    1273              :                   List *hashclauses,
    1274              :                   JoinType jointype,
    1275              :                   JoinPathExtraData *extra)
    1276              : {
    1277              :     Relids      required_outer;
    1278              :     JoinCostWorkspace workspace;
    1279              : 
    1280              :     /*
    1281              :      * If we are forming an outer join at this join, it's nonsensical to use
    1282              :      * an input path that uses the outer join as part of its parameterization.
    1283              :      * (This can happen despite our join order restrictions, since those apply
    1284              :      * to what is in an input relation not what its parameters are.)
    1285              :      */
    1286       797661 :     if (extra->sjinfo->ojrelid != 0 &&
    1287       322009 :         (bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(inner_path)) ||
    1288       160992 :          bms_is_member(extra->sjinfo->ojrelid, PATH_REQ_OUTER(outer_path))))
    1289        93797 :         return;
    1290              : 
    1291              :     /*
    1292              :      * Check to see if proposed path is still parameterized, and reject if the
    1293              :      * parameterization wouldn't be sensible.
    1294              :      */
    1295       636594 :     required_outer = calc_non_nestloop_required_outer(outer_path,
    1296              :                                                       inner_path);
    1297       636594 :     if (required_outer &&
    1298       105457 :         !bms_overlap(required_outer, extra->param_source_rels))
    1299              :     {
    1300              :         /* Waste no memory when we reject a path here */
    1301        93747 :         bms_free(required_outer);
    1302        93747 :         return;
    1303              :     }
    1304              : 
    1305              :     /*
    1306              :      * See comments in try_nestloop_path().  Also note that hashjoin paths
    1307              :      * never have any output pathkeys, per comments in create_hashjoin_path.
    1308              :      */
    1309       542847 :     initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
    1310              :                           outer_path, inner_path, extra, false);
    1311              : 
    1312       542847 :     if (add_path_precheck(joinrel, workspace.disabled_nodes,
    1313              :                           workspace.startup_cost, workspace.total_cost,
    1314              :                           NIL, required_outer))
    1315              :     {
    1316       265232 :         add_path(joinrel, (Path *)
    1317       265232 :                  create_hashjoin_path(root,
    1318              :                                       joinrel,
    1319              :                                       jointype,
    1320              :                                       &workspace,
    1321              :                                       extra,
    1322              :                                       outer_path,
    1323              :                                       inner_path,
    1324              :                                       false,    /* parallel_hash */
    1325              :                                       extra->restrictlist,
    1326              :                                       required_outer,
    1327              :                                       hashclauses));
    1328              :     }
    1329              :     else
    1330              :     {
    1331              :         /* Waste no memory when we reject a path here */
    1332       277615 :         bms_free(required_outer);
    1333              :     }
    1334              : }
    1335              : 
    1336              : /*
    1337              :  * try_partial_hashjoin_path
    1338              :  *    Consider a partial hashjoin join path; if it appears useful, push it into
    1339              :  *    the joinrel's partial_pathlist via add_partial_path().
    1340              :  *    The outer side is partial.  If parallel_hash is true, then the inner path
    1341              :  *    must be partial and will be run in parallel to create one or more shared
    1342              :  *    hash tables; otherwise the inner path must be complete and a copy of it
    1343              :  *    is run in every process to create separate identical private hash tables.
    1344              :  */
    1345              : static void
    1346       114016 : try_partial_hashjoin_path(PlannerInfo *root,
    1347              :                           RelOptInfo *joinrel,
    1348              :                           Path *outer_path,
    1349              :                           Path *inner_path,
    1350              :                           List *hashclauses,
    1351              :                           JoinType jointype,
    1352              :                           JoinPathExtraData *extra,
    1353              :                           bool parallel_hash)
    1354              : {
    1355              :     JoinCostWorkspace workspace;
    1356              : 
    1357              :     /*
    1358              :      * If the inner path is parameterized, we can't use a partial hashjoin.
    1359              :      * Parameterized partial paths are not supported.  The caller should
    1360              :      * already have verified that no lateral rels are required here.
    1361              :      */
    1362              :     Assert(bms_is_empty(joinrel->lateral_relids));
    1363              :     Assert(bms_is_empty(PATH_REQ_OUTER(outer_path)));
    1364       114016 :     if (!bms_is_empty(PATH_REQ_OUTER(inner_path)))
    1365        32158 :         return;
    1366              : 
    1367              :     /*
    1368              :      * Before creating a path, get a quick lower bound on what it is likely to
    1369              :      * cost.  Bail out right away if it looks terrible.
    1370              :      */
    1371       114016 :     initial_cost_hashjoin(root, &workspace, jointype, hashclauses,
    1372              :                           outer_path, inner_path, extra, parallel_hash);
    1373       114016 :     if (!add_partial_path_precheck(joinrel, workspace.disabled_nodes,
    1374              :                                    workspace.startup_cost,
    1375              :                                    workspace.total_cost, NIL))
    1376        32158 :         return;
    1377              : 
    1378              :     /* Might be good enough to be worth trying, so let's try it. */
    1379        81858 :     add_partial_path(joinrel, (Path *)
    1380        81858 :                      create_hashjoin_path(root,
    1381              :                                           joinrel,
    1382              :                                           jointype,
    1383              :                                           &workspace,
    1384              :                                           extra,
    1385              :                                           outer_path,
    1386              :                                           inner_path,
    1387              :                                           parallel_hash,
    1388              :                                           extra->restrictlist,
    1389              :                                           NULL,
    1390              :                                           hashclauses));
    1391              : }
    1392              : 
    1393              : /*
    1394              :  * sort_inner_and_outer
    1395              :  *    Create mergejoin join paths by explicitly sorting both the outer and
    1396              :  *    inner join relations on each available merge ordering.
    1397              :  *
    1398              :  * 'joinrel' is the join relation
    1399              :  * 'outerrel' is the outer join relation
    1400              :  * 'innerrel' is the inner join relation
    1401              :  * 'jointype' is the type of join to do
    1402              :  * 'extra' contains additional input values
    1403              :  */
    1404              : static void
    1405       616428 : sort_inner_and_outer(PlannerInfo *root,
    1406              :                      RelOptInfo *joinrel,
    1407              :                      RelOptInfo *outerrel,
    1408              :                      RelOptInfo *innerrel,
    1409              :                      JoinType jointype,
    1410              :                      JoinPathExtraData *extra)
    1411              : {
    1412              :     Path       *outer_path;
    1413              :     Path       *inner_path;
    1414       616428 :     Path       *cheapest_partial_outer = NULL;
    1415       616428 :     Path       *cheapest_safe_inner = NULL;
    1416              :     List       *all_pathkeys;
    1417              :     ListCell   *l;
    1418              : 
    1419              :     /* Nothing to do if there are no available mergejoin clauses */
    1420       616428 :     if (extra->mergeclause_list == NIL)
    1421       152383 :         return;
    1422              : 
    1423              :     /*
    1424              :      * We only consider the cheapest-total-cost input paths, since we are
    1425              :      * assuming here that a sort is required.  We will consider
    1426              :      * cheapest-startup-cost input paths later, and only if they don't need a
    1427              :      * sort.
    1428              :      *
    1429              :      * This function intentionally does not consider parameterized input
    1430              :      * paths, except when the cheapest-total is parameterized.  If we did so,
    1431              :      * we'd have a combinatorial explosion of mergejoin paths of dubious
    1432              :      * value.  This interacts with decisions elsewhere that also discriminate
    1433              :      * against mergejoins with parameterized inputs; see comments in
    1434              :      * src/backend/optimizer/README.
    1435              :      */
    1436       464045 :     outer_path = outerrel->cheapest_total_path;
    1437       464045 :     inner_path = innerrel->cheapest_total_path;
    1438              : 
    1439              :     /*
    1440              :      * If either cheapest-total path is parameterized by the other rel, we
    1441              :      * can't use a mergejoin.  (There's no use looking for alternative input
    1442              :      * paths, since these should already be the least-parameterized available
    1443              :      * paths.)
    1444              :      */
    1445       464045 :     if (PATH_PARAM_BY_REL(outer_path, innerrel) ||
    1446       462115 :         PATH_PARAM_BY_REL(inner_path, outerrel))
    1447         3884 :         return;
    1448              : 
    1449              :     /*
    1450              :      * If the joinrel is parallel-safe, we may be able to consider a partial
    1451              :      * merge join.  However, we can't handle JOIN_FULL, JOIN_RIGHT and
    1452              :      * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
    1453              :      * Also, the resulting path must not be parameterized.
    1454              :      */
    1455       460161 :     if (joinrel->consider_parallel &&
    1456       415728 :         jointype != JOIN_FULL &&
    1457       363643 :         jointype != JOIN_RIGHT &&
    1458       360526 :         jointype != JOIN_RIGHT_ANTI &&
    1459       360526 :         outerrel->partial_pathlist != NIL &&
    1460        52653 :         bms_is_empty(joinrel->lateral_relids))
    1461              :     {
    1462        52653 :         cheapest_partial_outer = (Path *) linitial(outerrel->partial_pathlist);
    1463              : 
    1464        52653 :         if (inner_path->parallel_safe)
    1465        52522 :             cheapest_safe_inner = inner_path;
    1466              :         else
    1467              :             cheapest_safe_inner =
    1468          131 :                 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    1469              :     }
    1470              : 
    1471              :     /*
    1472              :      * Each possible ordering of the available mergejoin clauses will generate
    1473              :      * a differently-sorted result path at essentially the same cost.  We have
    1474              :      * no basis for choosing one over another at this level of joining, but
    1475              :      * some sort orders may be more useful than others for higher-level
    1476              :      * mergejoins, so it's worth considering multiple orderings.
    1477              :      *
    1478              :      * Actually, it's not quite true that every mergeclause ordering will
    1479              :      * generate a different path order, because some of the clauses may be
    1480              :      * partially redundant (refer to the same EquivalenceClasses).  Therefore,
    1481              :      * what we do is convert the mergeclause list to a list of canonical
    1482              :      * pathkeys, and then consider different orderings of the pathkeys.
    1483              :      *
    1484              :      * Generating a path for *every* permutation of the pathkeys doesn't seem
    1485              :      * like a winning strategy; the cost in planning time is too high. For
    1486              :      * now, we generate one path for each pathkey, listing that pathkey first
    1487              :      * and the rest in random order.  This should allow at least a one-clause
    1488              :      * mergejoin without re-sorting against any other possible mergejoin
    1489              :      * partner path.  But if we've not guessed the right ordering of secondary
    1490              :      * keys, we may end up evaluating clauses as qpquals when they could have
    1491              :      * been done as mergeclauses.  (In practice, it's rare that there's more
    1492              :      * than two or three mergeclauses, so expending a huge amount of thought
    1493              :      * on that is probably not worth it.)
    1494              :      *
    1495              :      * The pathkey order returned by select_outer_pathkeys_for_merge() has
    1496              :      * some heuristics behind it (see that function), so be sure to try it
    1497              :      * exactly as-is as well as making variants.
    1498              :      */
    1499       460161 :     all_pathkeys = select_outer_pathkeys_for_merge(root,
    1500              :                                                    extra->mergeclause_list,
    1501              :                                                    joinrel);
    1502              : 
    1503       990472 :     foreach(l, all_pathkeys)
    1504              :     {
    1505       530311 :         PathKey    *front_pathkey = (PathKey *) lfirst(l);
    1506              :         List       *cur_mergeclauses;
    1507              :         List       *outerkeys;
    1508              :         List       *innerkeys;
    1509              :         List       *merge_pathkeys;
    1510              : 
    1511              :         /* Make a pathkey list with this guy first */
    1512       530311 :         if (l != list_head(all_pathkeys))
    1513        70150 :             outerkeys = lcons(front_pathkey,
    1514              :                               list_delete_nth_cell(list_copy(all_pathkeys),
    1515              :                                                    foreach_current_index(l)));
    1516              :         else
    1517       460161 :             outerkeys = all_pathkeys;   /* no work at first one... */
    1518              : 
    1519              :         /* Sort the mergeclauses into the corresponding ordering */
    1520              :         cur_mergeclauses =
    1521       530311 :             find_mergeclauses_for_outer_pathkeys(root,
    1522              :                                                  outerkeys,
    1523              :                                                  extra->mergeclause_list);
    1524              : 
    1525              :         /* Should have used them all... */
    1526              :         Assert(list_length(cur_mergeclauses) == list_length(extra->mergeclause_list));
    1527              : 
    1528              :         /* Build sort pathkeys for the inner side */
    1529       530311 :         innerkeys = make_inner_pathkeys_for_merge(root,
    1530              :                                                   cur_mergeclauses,
    1531              :                                                   outerkeys);
    1532              : 
    1533              :         /* Build pathkeys representing output sort order */
    1534       530311 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    1535              :                                              outerkeys);
    1536              : 
    1537              :         /*
    1538              :          * And now we can make the path.
    1539              :          *
    1540              :          * Note: it's possible that the cheapest paths will already be sorted
    1541              :          * properly.  try_mergejoin_path will detect that case and suppress an
    1542              :          * explicit sort step, so we needn't do so here.
    1543              :          */
    1544       530311 :         try_mergejoin_path(root,
    1545              :                            joinrel,
    1546              :                            outer_path,
    1547              :                            inner_path,
    1548              :                            merge_pathkeys,
    1549              :                            cur_mergeclauses,
    1550              :                            outerkeys,
    1551              :                            innerkeys,
    1552              :                            jointype,
    1553              :                            extra,
    1554              :                            false);
    1555              : 
    1556              :         /*
    1557              :          * If we have partial outer and parallel safe inner path then try
    1558              :          * partial mergejoin path.
    1559              :          */
    1560       530311 :         if (cheapest_partial_outer && cheapest_safe_inner)
    1561        55236 :             try_partial_mergejoin_path(root,
    1562              :                                        joinrel,
    1563              :                                        cheapest_partial_outer,
    1564              :                                        cheapest_safe_inner,
    1565              :                                        merge_pathkeys,
    1566              :                                        cur_mergeclauses,
    1567              :                                        outerkeys,
    1568              :                                        innerkeys,
    1569              :                                        jointype,
    1570              :                                        extra);
    1571              :     }
    1572              : }
    1573              : 
    1574              : /*
    1575              :  * generate_mergejoin_paths
    1576              :  *  Creates possible mergejoin paths for input outerpath.
    1577              :  *
    1578              :  * We generate mergejoins if mergejoin clauses are available.  We have
    1579              :  * two ways to generate the inner path for a mergejoin: sort the cheapest
    1580              :  * inner path, or use an inner path that is already suitably ordered for the
    1581              :  * merge.  If we have several mergeclauses, it could be that there is no inner
    1582              :  * path (or only a very expensive one) for the full list of mergeclauses, but
    1583              :  * better paths exist if we truncate the mergeclause list (thereby discarding
    1584              :  * some sort key requirements).  So, we consider truncations of the
    1585              :  * mergeclause list as well as the full list.  (Ideally we'd consider all
    1586              :  * subsets of the mergeclause list, but that seems way too expensive.)
    1587              :  */
    1588              : static void
    1589      1214285 : generate_mergejoin_paths(PlannerInfo *root,
    1590              :                          RelOptInfo *joinrel,
    1591              :                          RelOptInfo *innerrel,
    1592              :                          Path *outerpath,
    1593              :                          JoinType jointype,
    1594              :                          JoinPathExtraData *extra,
    1595              :                          bool useallclauses,
    1596              :                          Path *inner_cheapest_total,
    1597              :                          List *merge_pathkeys,
    1598              :                          bool is_partial)
    1599              : {
    1600              :     List       *mergeclauses;
    1601              :     List       *innersortkeys;
    1602              :     List       *trialsortkeys;
    1603              :     Path       *cheapest_startup_inner;
    1604              :     Path       *cheapest_total_inner;
    1605              :     int         num_sortkeys;
    1606              :     int         sortkeycnt;
    1607              : 
    1608              :     /* Look for useful mergeclauses (if any) */
    1609              :     mergeclauses =
    1610      1214285 :         find_mergeclauses_for_outer_pathkeys(root,
    1611              :                                              outerpath->pathkeys,
    1612              :                                              extra->mergeclause_list);
    1613              : 
    1614              :     /*
    1615              :      * Done with this outer path if no chance for a mergejoin.
    1616              :      *
    1617              :      * Special corner case: for "x FULL JOIN y ON true", there will be no join
    1618              :      * clauses at all.  Ordinarily we'd generate a clauseless nestloop path,
    1619              :      * but since mergejoin is our only join type that supports FULL JOIN
    1620              :      * without any join clauses, it's necessary to generate a clauseless
    1621              :      * mergejoin path instead.
    1622              :      */
    1623      1214285 :     if (mergeclauses == NIL)
    1624              :     {
    1625       854636 :         if (jointype == JOIN_FULL)
    1626              :              /* okay to try for mergejoin */ ;
    1627              :         else
    1628       851930 :             return;
    1629              :     }
    1630       421154 :     if (useallclauses &&
    1631        58799 :         list_length(mergeclauses) != list_length(extra->mergeclause_list))
    1632         9878 :         return;
    1633              : 
    1634              :     /* Compute the required ordering of the inner path */
    1635       352477 :     innersortkeys = make_inner_pathkeys_for_merge(root,
    1636              :                                                   mergeclauses,
    1637              :                                                   outerpath->pathkeys);
    1638              : 
    1639              :     /*
    1640              :      * Generate a mergejoin on the basis of sorting the cheapest inner. Since
    1641              :      * a sort will be needed, only cheapest total cost matters. (But
    1642              :      * try_mergejoin_path will do the right thing if inner_cheapest_total is
    1643              :      * already correctly sorted.)
    1644              :      */
    1645       352477 :     try_mergejoin_path(root,
    1646              :                        joinrel,
    1647              :                        outerpath,
    1648              :                        inner_cheapest_total,
    1649              :                        merge_pathkeys,
    1650              :                        mergeclauses,
    1651              :                        NIL,
    1652              :                        innersortkeys,
    1653              :                        jointype,
    1654              :                        extra,
    1655              :                        is_partial);
    1656              : 
    1657              :     /*
    1658              :      * Look for presorted inner paths that satisfy the innersortkey list ---
    1659              :      * or any truncation thereof, if we are allowed to build a mergejoin using
    1660              :      * a subset of the merge clauses.  Here, we consider both cheap startup
    1661              :      * cost and cheap total cost.
    1662              :      *
    1663              :      * Currently we do not consider parameterized inner paths here. This
    1664              :      * interacts with decisions elsewhere that also discriminate against
    1665              :      * mergejoins with parameterized inputs; see comments in
    1666              :      * src/backend/optimizer/README.
    1667              :      *
    1668              :      * As we shorten the sortkey list, we should consider only paths that are
    1669              :      * strictly cheaper than (in particular, not the same as) any path found
    1670              :      * in an earlier iteration.  Otherwise we'd be intentionally using fewer
    1671              :      * merge keys than a given path allows (treating the rest as plain
    1672              :      * joinquals), which is unlikely to be a good idea.  Also, eliminating
    1673              :      * paths here on the basis of compare_path_costs is a lot cheaper than
    1674              :      * building the mergejoin path only to throw it away.
    1675              :      *
    1676              :      * If inner_cheapest_total is well enough sorted to have not required a
    1677              :      * sort in the path made above, we shouldn't make a duplicate path with
    1678              :      * it, either.  We handle that case with the same logic that handles the
    1679              :      * previous consideration, by initializing the variables that track
    1680              :      * cheapest-so-far properly.  Note that we do NOT reject
    1681              :      * inner_cheapest_total if we find it matches some shorter set of
    1682              :      * pathkeys.  That case corresponds to using fewer mergekeys to avoid
    1683              :      * sorting inner_cheapest_total, whereas we did sort it above, so the
    1684              :      * plans being considered are different.
    1685              :      */
    1686       352477 :     if (pathkeys_contained_in(innersortkeys,
    1687              :                               inner_cheapest_total->pathkeys))
    1688              :     {
    1689              :         /* inner_cheapest_total didn't require a sort */
    1690        11226 :         cheapest_startup_inner = inner_cheapest_total;
    1691        11226 :         cheapest_total_inner = inner_cheapest_total;
    1692              :     }
    1693              :     else
    1694              :     {
    1695              :         /* it did require a sort, at least for the full set of keys */
    1696       341251 :         cheapest_startup_inner = NULL;
    1697       341251 :         cheapest_total_inner = NULL;
    1698              :     }
    1699       352477 :     num_sortkeys = list_length(innersortkeys);
    1700       352477 :     if (num_sortkeys > 1 && !useallclauses)
    1701        20716 :         trialsortkeys = list_copy(innersortkeys);   /* need modifiable copy */
    1702              :     else
    1703       331761 :         trialsortkeys = innersortkeys;  /* won't really truncate */
    1704              : 
    1705       677356 :     for (sortkeycnt = num_sortkeys; sortkeycnt > 0; sortkeycnt--)
    1706              :     {
    1707              :         Path       *innerpath;
    1708       373688 :         List       *newclauses = NIL;
    1709              : 
    1710              :         /*
    1711              :          * Look for an inner path ordered well enough for the first
    1712              :          * 'sortkeycnt' innersortkeys.  NB: trialsortkeys list is modified
    1713              :          * destructively, which is why we made a copy...
    1714              :          */
    1715       373688 :         trialsortkeys = list_truncate(trialsortkeys, sortkeycnt);
    1716       373688 :         innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
    1717              :                                                    trialsortkeys,
    1718              :                                                    NULL,
    1719              :                                                    TOTAL_COST,
    1720              :                                                    is_partial);
    1721       373688 :         if (innerpath != NULL &&
    1722        18070 :             (cheapest_total_inner == NULL ||
    1723        18070 :              compare_path_costs(innerpath, cheapest_total_inner,
    1724              :                                 TOTAL_COST) < 0))
    1725              :         {
    1726              :             /* Found a cheap (or even-cheaper) sorted path */
    1727              :             /* Select the right mergeclauses, if we didn't already */
    1728       208674 :             if (sortkeycnt < num_sortkeys)
    1729              :             {
    1730              :                 newclauses =
    1731        10290 :                     trim_mergeclauses_for_inner_pathkeys(root,
    1732              :                                                          mergeclauses,
    1733              :                                                          trialsortkeys);
    1734              :                 Assert(newclauses != NIL);
    1735              :             }
    1736              :             else
    1737       198384 :                 newclauses = mergeclauses;
    1738       208674 :             try_mergejoin_path(root,
    1739              :                                joinrel,
    1740              :                                outerpath,
    1741              :                                innerpath,
    1742              :                                merge_pathkeys,
    1743              :                                newclauses,
    1744              :                                NIL,
    1745              :                                NIL,
    1746              :                                jointype,
    1747              :                                extra,
    1748              :                                is_partial);
    1749       208674 :             cheapest_total_inner = innerpath;
    1750              :         }
    1751              :         /* Same on the basis of cheapest startup cost ... */
    1752       373688 :         innerpath = get_cheapest_path_for_pathkeys(innerrel->pathlist,
    1753              :                                                    trialsortkeys,
    1754              :                                                    NULL,
    1755              :                                                    STARTUP_COST,
    1756              :                                                    is_partial);
    1757       373688 :         if (innerpath != NULL &&
    1758        18070 :             (cheapest_startup_inner == NULL ||
    1759        18070 :              compare_path_costs(innerpath, cheapest_startup_inner,
    1760              :                                 STARTUP_COST) < 0))
    1761              :         {
    1762              :             /* Found a cheap (or even-cheaper) sorted path */
    1763       207021 :             if (innerpath != cheapest_total_inner)
    1764              :             {
    1765              :                 /*
    1766              :                  * Avoid rebuilding clause list if we already made one; saves
    1767              :                  * memory in big join trees...
    1768              :                  */
    1769         1761 :                 if (newclauses == NIL)
    1770              :                 {
    1771          104 :                     if (sortkeycnt < num_sortkeys)
    1772              :                     {
    1773              :                         newclauses =
    1774           63 :                             trim_mergeclauses_for_inner_pathkeys(root,
    1775              :                                                                  mergeclauses,
    1776              :                                                                  trialsortkeys);
    1777              :                         Assert(newclauses != NIL);
    1778              :                     }
    1779              :                     else
    1780           41 :                         newclauses = mergeclauses;
    1781              :                 }
    1782         1761 :                 try_mergejoin_path(root,
    1783              :                                    joinrel,
    1784              :                                    outerpath,
    1785              :                                    innerpath,
    1786              :                                    merge_pathkeys,
    1787              :                                    newclauses,
    1788              :                                    NIL,
    1789              :                                    NIL,
    1790              :                                    jointype,
    1791              :                                    extra,
    1792              :                                    is_partial);
    1793              :             }
    1794       207021 :             cheapest_startup_inner = innerpath;
    1795              :         }
    1796              : 
    1797              :         /*
    1798              :          * Don't consider truncated sortkeys if we need all clauses.
    1799              :          */
    1800       373688 :         if (useallclauses)
    1801        48809 :             break;
    1802              :     }
    1803              : }
    1804              : 
    1805              : /*
    1806              :  * match_unsorted_outer
    1807              :  *    Creates possible join paths for processing a single join relation
    1808              :  *    'joinrel' by employing either iterative substitution or
    1809              :  *    mergejoining on each of its possible outer paths (considering
    1810              :  *    only outer paths that are already ordered well enough for merging).
    1811              :  *
    1812              :  * We always generate a nestloop path for each available outer path.
    1813              :  * In fact we may generate as many as five: one on the cheapest-total-cost
    1814              :  * inner path, one on the same with materialization, one on the
    1815              :  * cheapest-startup-cost inner path (if different), one on the
    1816              :  * cheapest-total inner-indexscan path (if any), and one on the
    1817              :  * cheapest-startup inner-indexscan path (if different).
    1818              :  *
    1819              :  * We also consider mergejoins if mergejoin clauses are available.  See
    1820              :  * detailed comments in generate_mergejoin_paths.
    1821              :  *
    1822              :  * 'joinrel' is the join relation
    1823              :  * 'outerrel' is the outer join relation
    1824              :  * 'innerrel' is the inner join relation
    1825              :  * 'jointype' is the type of join to do
    1826              :  * 'extra' contains additional input values
    1827              :  */
    1828              : static void
    1829       616428 : match_unsorted_outer(PlannerInfo *root,
    1830              :                      RelOptInfo *joinrel,
    1831              :                      RelOptInfo *outerrel,
    1832              :                      RelOptInfo *innerrel,
    1833              :                      JoinType jointype,
    1834              :                      JoinPathExtraData *extra)
    1835              : {
    1836              :     bool        nestjoinOK;
    1837              :     bool        useallclauses;
    1838       616428 :     Path       *inner_cheapest_total = innerrel->cheapest_total_path;
    1839       616428 :     Path       *matpath = NULL;
    1840              :     ListCell   *lc1;
    1841              : 
    1842              :     /*
    1843              :      * For now we do not support RIGHT_SEMI join in mergejoin or nestloop
    1844              :      * join.
    1845              :      */
    1846       616428 :     if (jointype == JOIN_RIGHT_SEMI)
    1847         1104 :         return;
    1848              : 
    1849              :     /*
    1850              :      * Nestloop only supports inner, left, semi, and anti joins.  Also, if we
    1851              :      * are doing a right, right-anti or full mergejoin, we must use *all* the
    1852              :      * mergeclauses as join clauses, else we will not have a valid plan.
    1853              :      * (Although these two flags are currently inverses, keep them separate
    1854              :      * for clarity and possible future changes.)
    1855              :      */
    1856       615324 :     switch (jointype)
    1857              :     {
    1858       544584 :         case JOIN_INNER:
    1859              :         case JOIN_LEFT:
    1860              :         case JOIN_SEMI:
    1861              :         case JOIN_ANTI:
    1862       544584 :             nestjoinOK = true;
    1863       544584 :             useallclauses = false;
    1864       544584 :             break;
    1865        70740 :         case JOIN_RIGHT:
    1866              :         case JOIN_RIGHT_ANTI:
    1867              :         case JOIN_FULL:
    1868        70740 :             nestjoinOK = false;
    1869        70740 :             useallclauses = true;
    1870        70740 :             break;
    1871            0 :         default:
    1872            0 :             elog(ERROR, "unrecognized join type: %d",
    1873              :                  (int) jointype);
    1874              :             nestjoinOK = false; /* keep compiler quiet */
    1875              :             useallclauses = false;
    1876              :             break;
    1877              :     }
    1878              : 
    1879              :     /*
    1880              :      * If inner_cheapest_total is parameterized by the outer rel, ignore it;
    1881              :      * we will consider it below as a member of cheapest_parameterized_paths,
    1882              :      * but the other possibilities considered in this routine aren't usable.
    1883              :      *
    1884              :      * Furthermore, if the inner side is a unique-ified relation, we cannot
    1885              :      * generate any valid paths here, because the inner rel's dependency on
    1886              :      * the outer rel makes unique-ification meaningless.
    1887              :      */
    1888       615324 :     if (PATH_PARAM_BY_REL(inner_cheapest_total, outerrel))
    1889              :     {
    1890        12647 :         inner_cheapest_total = NULL;
    1891              : 
    1892        12647 :         if (RELATION_WAS_MADE_UNIQUE(innerrel, extra->sjinfo, jointype))
    1893           30 :             return;
    1894              :     }
    1895              : 
    1896       615294 :     if (nestjoinOK)
    1897              :     {
    1898              :         /*
    1899              :          * Consider materializing the cheapest inner path, unless that is
    1900              :          * disabled or the path in question materializes its output anyway.
    1901              :          *
    1902              :          * At present, we only consider materialization for non-partial outer
    1903              :          * paths, so it's correct to test PGS_CONSIDER_NONPARTIAL here. If we
    1904              :          * ever want to consider materialization for partial paths, we'll need
    1905              :          * to create matpath whenever PGS_NESTLOOP_MATERIALIZE is set, use it
    1906              :          * for partial paths either way, and use it for non-partial paths only
    1907              :          * when PGS_CONSIDER_NONPARTIAL is also set.
    1908              :          */
    1909       544554 :         if ((extra->pgs_mask &
    1910              :              (PGS_NESTLOOP_MATERIALIZE | PGS_CONSIDER_NONPARTIAL)) ==
    1911       479462 :             (PGS_NESTLOOP_MATERIALIZE | PGS_CONSIDER_NONPARTIAL) &&
    1912       467723 :             inner_cheapest_total != NULL &&
    1913       467723 :             !ExecMaterializesOutput(inner_cheapest_total->pathtype))
    1914              :             matpath = (Path *)
    1915       450072 :                 create_material_path(innerrel, inner_cheapest_total, true);
    1916              :     }
    1917              : 
    1918      1981080 :     foreach(lc1, outerrel->pathlist)
    1919              :     {
    1920      1365786 :         Path       *outerpath = (Path *) lfirst(lc1);
    1921              :         List       *merge_pathkeys;
    1922              : 
    1923              :         /*
    1924              :          * We cannot use an outer path that is parameterized by the inner rel.
    1925              :          */
    1926      1365786 :         if (PATH_PARAM_BY_REL(outerpath, innerrel))
    1927       210582 :             continue;
    1928              : 
    1929              :         /*
    1930              :          * The result will have this sort order (even if it is implemented as
    1931              :          * a nestloop, and even if some of the mergeclauses are implemented by
    1932              :          * qpquals rather than as true mergeclauses):
    1933              :          */
    1934      1155204 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    1935              :                                              outerpath->pathkeys);
    1936              : 
    1937      1155204 :         if (nestjoinOK)
    1938              :         {
    1939              :             /*
    1940              :              * Consider nestloop joins using this outer path and various
    1941              :              * available paths for the inner relation.  We consider the
    1942              :              * cheapest-total paths for each available parameterization of the
    1943              :              * inner relation, including the unparameterized case.
    1944              :              */
    1945              :             ListCell   *lc2;
    1946              : 
    1947      2606546 :             foreach(lc2, innerrel->cheapest_parameterized_paths)
    1948              :             {
    1949      1581918 :                 Path       *innerpath = (Path *) lfirst(lc2);
    1950              :                 Path       *mpath;
    1951              : 
    1952      1581918 :                 try_nestloop_path(root,
    1953              :                                   joinrel,
    1954              :                                   outerpath,
    1955              :                                   innerpath,
    1956              :                                   merge_pathkeys,
    1957              :                                   jointype,
    1958              :                                   PGS_NESTLOOP_PLAIN,
    1959              :                                   extra);
    1960              : 
    1961              :                 /*
    1962              :                  * Try generating a memoize path and see if that makes the
    1963              :                  * nested loop any cheaper.
    1964              :                  */
    1965      1581918 :                 mpath = get_memoize_path(root, innerrel, outerrel,
    1966              :                                          innerpath, outerpath, jointype,
    1967              :                                          extra);
    1968      1581918 :                 if (mpath != NULL)
    1969       215058 :                     try_nestloop_path(root,
    1970              :                                       joinrel,
    1971              :                                       outerpath,
    1972              :                                       mpath,
    1973              :                                       merge_pathkeys,
    1974              :                                       jointype,
    1975              :                                       PGS_NESTLOOP_MEMOIZE,
    1976              :                                       extra);
    1977              :             }
    1978              : 
    1979              :             /* Also consider materialized form of the cheapest inner path */
    1980      1024628 :             if (matpath != NULL)
    1981       864306 :                 try_nestloop_path(root,
    1982              :                                   joinrel,
    1983              :                                   outerpath,
    1984              :                                   matpath,
    1985              :                                   merge_pathkeys,
    1986              :                                   jointype,
    1987              :                                   PGS_NESTLOOP_MATERIALIZE,
    1988              :                                   extra);
    1989              :         }
    1990              : 
    1991              :         /* Can't do anything else if inner rel is parameterized by outer */
    1992      1155204 :         if (inner_cheapest_total == NULL)
    1993        19714 :             continue;
    1994              : 
    1995              :         /* Generate merge join paths */
    1996      1135490 :         generate_mergejoin_paths(root, joinrel, innerrel, outerpath,
    1997              :                                  jointype, extra, useallclauses,
    1998              :                                  inner_cheapest_total, merge_pathkeys,
    1999              :                                  false);
    2000              :     }
    2001              : 
    2002              :     /*
    2003              :      * Consider partial nestloop and mergejoin plan if outerrel has any
    2004              :      * partial path and the joinrel is parallel-safe.  However, we can't
    2005              :      * handle joins needing lateral rels, since partial paths must not be
    2006              :      * parameterized.  Similarly, we can't handle JOIN_FULL, JOIN_RIGHT and
    2007              :      * JOIN_RIGHT_ANTI, because they can produce false null extended rows.
    2008              :      */
    2009       615294 :     if (joinrel->consider_parallel &&
    2010       530568 :         jointype != JOIN_FULL &&
    2011       472088 :         jointype != JOIN_RIGHT &&
    2012       468324 :         jointype != JOIN_RIGHT_ANTI &&
    2013       468324 :         outerrel->partial_pathlist != NIL &&
    2014        62881 :         bms_is_empty(joinrel->lateral_relids))
    2015              :     {
    2016        62881 :         if (nestjoinOK)
    2017        62881 :             consider_parallel_nestloop(root, joinrel, outerrel, innerrel,
    2018              :                                        jointype, extra);
    2019              : 
    2020              :         /*
    2021              :          * If inner_cheapest_total is NULL or non parallel-safe then find the
    2022              :          * cheapest total parallel safe path.
    2023              :          */
    2024        62881 :         if (inner_cheapest_total == NULL ||
    2025        62531 :             !inner_cheapest_total->parallel_safe)
    2026              :         {
    2027              :             inner_cheapest_total =
    2028          688 :                 get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    2029              :         }
    2030              : 
    2031        62881 :         if (inner_cheapest_total)
    2032        62499 :             consider_parallel_mergejoin(root, joinrel, outerrel, innerrel,
    2033              :                                         jointype, extra,
    2034              :                                         inner_cheapest_total);
    2035              :     }
    2036              : }
    2037              : 
    2038              : /*
    2039              :  * consider_parallel_mergejoin
    2040              :  *    Try to build partial paths for a joinrel by joining a partial path
    2041              :  *    for the outer relation to a complete path for the inner relation.
    2042              :  *
    2043              :  * 'joinrel' is the join relation
    2044              :  * 'outerrel' is the outer join relation
    2045              :  * 'innerrel' is the inner join relation
    2046              :  * 'jointype' is the type of join to do
    2047              :  * 'extra' contains additional input values
    2048              :  * 'inner_cheapest_total' cheapest total path for innerrel
    2049              :  */
    2050              : static void
    2051        62499 : consider_parallel_mergejoin(PlannerInfo *root,
    2052              :                             RelOptInfo *joinrel,
    2053              :                             RelOptInfo *outerrel,
    2054              :                             RelOptInfo *innerrel,
    2055              :                             JoinType jointype,
    2056              :                             JoinPathExtraData *extra,
    2057              :                             Path *inner_cheapest_total)
    2058              : {
    2059              :     ListCell   *lc1;
    2060              : 
    2061              :     /* generate merge join path for each partial outer path */
    2062       141294 :     foreach(lc1, outerrel->partial_pathlist)
    2063              :     {
    2064        78795 :         Path       *outerpath = (Path *) lfirst(lc1);
    2065              :         List       *merge_pathkeys;
    2066              : 
    2067              :         /*
    2068              :          * Figure out what useful ordering any paths we create will have.
    2069              :          */
    2070        78795 :         merge_pathkeys = build_join_pathkeys(root, joinrel, jointype,
    2071              :                                              outerpath->pathkeys);
    2072              : 
    2073        78795 :         generate_mergejoin_paths(root, joinrel, innerrel, outerpath, jointype,
    2074              :                                  extra, false, inner_cheapest_total,
    2075              :                                  merge_pathkeys, true);
    2076              :     }
    2077        62499 : }
    2078              : 
    2079              : /*
    2080              :  * consider_parallel_nestloop
    2081              :  *    Try to build partial paths for a joinrel by joining a partial path for the
    2082              :  *    outer relation to a complete path for the inner relation.
    2083              :  *
    2084              :  * 'joinrel' is the join relation
    2085              :  * 'outerrel' is the outer join relation
    2086              :  * 'innerrel' is the inner join relation
    2087              :  * 'jointype' is the type of join to do
    2088              :  * 'extra' contains additional input values
    2089              :  */
    2090              : static void
    2091        62881 : consider_parallel_nestloop(PlannerInfo *root,
    2092              :                            RelOptInfo *joinrel,
    2093              :                            RelOptInfo *outerrel,
    2094              :                            RelOptInfo *innerrel,
    2095              :                            JoinType jointype,
    2096              :                            JoinPathExtraData *extra)
    2097              : {
    2098        62881 :     Path       *inner_cheapest_total = innerrel->cheapest_total_path;
    2099        62881 :     Path       *matpath = NULL;
    2100              :     ListCell   *lc1;
    2101              : 
    2102              :     /*
    2103              :      * Consider materializing the cheapest inner path, unless: 1)
    2104              :      * materialization is disabled here, 2) the cheapest inner path is not
    2105              :      * parallel-safe, 3) the cheapest inner path is parameterized by the outer
    2106              :      * rel, or 4) the cheapest inner path materializes its output anyway.
    2107              :      */
    2108        62881 :     if ((extra->pgs_mask & PGS_NESTLOOP_MATERIALIZE) != 0 &&
    2109        53523 :         inner_cheapest_total->parallel_safe &&
    2110        53322 :         !PATH_PARAM_BY_REL(inner_cheapest_total, outerrel) &&
    2111        53062 :         !ExecMaterializesOutput(inner_cheapest_total->pathtype))
    2112              :     {
    2113              :         matpath = (Path *)
    2114        52998 :             create_material_path(innerrel, inner_cheapest_total, true);
    2115              :         Assert(matpath->parallel_safe);
    2116              :     }
    2117              : 
    2118       142173 :     foreach(lc1, outerrel->partial_pathlist)
    2119              :     {
    2120        79292 :         Path       *outerpath = (Path *) lfirst(lc1);
    2121              :         List       *pathkeys;
    2122              :         ListCell   *lc2;
    2123              : 
    2124              :         /* Figure out what useful ordering any paths we create will have. */
    2125        79292 :         pathkeys = build_join_pathkeys(root, joinrel, jointype,
    2126              :                                        outerpath->pathkeys);
    2127              : 
    2128              :         /*
    2129              :          * Try the cheapest parameterized paths; only those which will produce
    2130              :          * an unparameterized path when joined to this outerrel will survive
    2131              :          * try_partial_nestloop_path.  The cheapest unparameterized path is
    2132              :          * also in this list.
    2133              :          */
    2134       166490 :         foreach(lc2, innerrel->cheapest_parameterized_paths)
    2135              :         {
    2136        87198 :             Path       *innerpath = (Path *) lfirst(lc2);
    2137              :             Path       *mpath;
    2138              : 
    2139              :             /* Can't join to an inner path that is not parallel-safe */
    2140        87198 :             if (!innerpath->parallel_safe)
    2141          397 :                 continue;
    2142              : 
    2143        86801 :             try_partial_nestloop_path(root, joinrel, outerpath, innerpath,
    2144              :                                       pathkeys, jointype,
    2145              :                                       PGS_NESTLOOP_PLAIN, extra);
    2146              : 
    2147              :             /*
    2148              :              * Try generating a memoize path and see if that makes the nested
    2149              :              * loop any cheaper.
    2150              :              */
    2151        86801 :             mpath = get_memoize_path(root, innerrel, outerrel,
    2152              :                                      innerpath, outerpath, jointype,
    2153              :                                      extra);
    2154        86801 :             if (mpath != NULL)
    2155         4010 :                 try_partial_nestloop_path(root, joinrel, outerpath, mpath,
    2156              :                                           pathkeys, jointype,
    2157              :                                           PGS_NESTLOOP_MEMOIZE, extra);
    2158              :         }
    2159              : 
    2160              :         /* Also consider materialized form of the cheapest inner path */
    2161        79292 :         if (matpath != NULL)
    2162        66976 :             try_partial_nestloop_path(root, joinrel, outerpath, matpath,
    2163              :                                       pathkeys, jointype,
    2164              :                                       PGS_NESTLOOP_MATERIALIZE, extra);
    2165              :     }
    2166        62881 : }
    2167              : 
    2168              : /*
    2169              :  * hash_inner_and_outer
    2170              :  *    Create hashjoin join paths by explicitly hashing both the outer and
    2171              :  *    inner keys of each available hash clause.
    2172              :  *
    2173              :  * 'joinrel' is the join relation
    2174              :  * 'outerrel' is the outer join relation
    2175              :  * 'innerrel' is the inner join relation
    2176              :  * 'jointype' is the type of join to do
    2177              :  * 'extra' contains additional input values
    2178              :  */
    2179              : static void
    2180       560369 : hash_inner_and_outer(PlannerInfo *root,
    2181              :                      RelOptInfo *joinrel,
    2182              :                      RelOptInfo *outerrel,
    2183              :                      RelOptInfo *innerrel,
    2184              :                      JoinType jointype,
    2185              :                      JoinPathExtraData *extra)
    2186              : {
    2187       560369 :     bool        isouterjoin = IS_OUTER_JOIN(jointype);
    2188              :     List       *hashclauses;
    2189              :     ListCell   *l;
    2190              : 
    2191              :     /*
    2192              :      * We need to build only one hashclauses list for any given pair of outer
    2193              :      * and inner relations; all of the hashable clauses will be used as keys.
    2194              :      *
    2195              :      * Scan the join's restrictinfo list to find hashjoinable clauses that are
    2196              :      * usable with this pair of sub-relations.
    2197              :      */
    2198       560369 :     hashclauses = NIL;
    2199      1189190 :     foreach(l, extra->restrictlist)
    2200              :     {
    2201       628821 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
    2202              : 
    2203              :         /*
    2204              :          * If processing an outer join, only use its own join clauses for
    2205              :          * hashing.  For inner joins we need not be so picky.
    2206              :          */
    2207       628821 :         if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
    2208        11602 :             continue;
    2209              : 
    2210       617219 :         if (!restrictinfo->can_join ||
    2211       563678 :             restrictinfo->hashjoinoperator == InvalidOid)
    2212        66454 :             continue;           /* not hashjoinable */
    2213              : 
    2214              :         /*
    2215              :          * Check if clause has the form "outer op inner" or "inner op outer".
    2216              :          */
    2217       550765 :         if (!clause_sides_match_join(restrictinfo, outerrel->relids,
    2218              :                                      innerrel->relids))
    2219          144 :             continue;           /* no good for these input relations */
    2220              : 
    2221              :         /*
    2222              :          * If clause has the form "inner op outer", check if its operator has
    2223              :          * valid commutator.  This is necessary because hashclauses in this
    2224              :          * form will get commuted in createplan.c to put the outer var on the
    2225              :          * left (see get_switched_clauses).  This probably shouldn't ever
    2226              :          * fail, since hashable operators ought to have commutators, but be
    2227              :          * paranoid.
    2228              :          *
    2229              :          * The clause being hashjoinable indicates that it's an OpExpr.
    2230              :          */
    2231       825340 :         if (!restrictinfo->outer_is_left &&
    2232       274719 :             !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
    2233            5 :             continue;
    2234              : 
    2235       550616 :         hashclauses = lappend(hashclauses, restrictinfo);
    2236              :     }
    2237              : 
    2238              :     /* If we found any usable hashclauses, make paths */
    2239       560369 :     if (hashclauses)
    2240              :     {
    2241              :         /*
    2242              :          * We consider both the cheapest-total-cost and cheapest-startup-cost
    2243              :          * outer paths.  There's no need to consider any but the
    2244              :          * cheapest-total-cost inner path, however.
    2245              :          */
    2246       479629 :         Path       *cheapest_startup_outer = outerrel->cheapest_startup_path;
    2247       479629 :         Path       *cheapest_total_outer = outerrel->cheapest_total_path;
    2248       479629 :         Path       *cheapest_total_inner = innerrel->cheapest_total_path;
    2249              :         ListCell   *lc1;
    2250              :         ListCell   *lc2;
    2251              : 
    2252              :         /*
    2253              :          * If either cheapest-total path is parameterized by the other rel, we
    2254              :          * can't use a hashjoin.  (There's no use looking for alternative
    2255              :          * input paths, since these should already be the least-parameterized
    2256              :          * available paths.)
    2257              :          */
    2258       479629 :         if (PATH_PARAM_BY_REL(cheapest_total_outer, innerrel) ||
    2259       477691 :             PATH_PARAM_BY_REL(cheapest_total_inner, outerrel))
    2260         3876 :             return;
    2261              : 
    2262              :         /*
    2263              :          * Consider the cheapest startup outer together with the cheapest
    2264              :          * total inner, and then consider pairings of cheapest-total paths
    2265              :          * including parameterized ones.  There is no use in generating
    2266              :          * parameterized paths on the basis of possibly cheap startup cost, so
    2267              :          * this is sufficient.
    2268              :          */
    2269       475753 :         if (cheapest_startup_outer != NULL)
    2270       474000 :             try_hashjoin_path(root,
    2271              :                               joinrel,
    2272              :                               cheapest_startup_outer,
    2273              :                               cheapest_total_inner,
    2274              :                               hashclauses,
    2275              :                               jointype,
    2276              :                               extra);
    2277              : 
    2278      1180384 :         foreach(lc1, outerrel->cheapest_parameterized_paths)
    2279              :         {
    2280       704631 :             Path       *outerpath = (Path *) lfirst(lc1);
    2281              : 
    2282              :             /*
    2283              :              * We cannot use an outer path that is parameterized by the inner
    2284              :              * rel.
    2285              :              */
    2286       704631 :             if (PATH_PARAM_BY_REL(outerpath, innerrel))
    2287       183593 :                 continue;
    2288              : 
    2289      1306180 :             foreach(lc2, innerrel->cheapest_parameterized_paths)
    2290              :             {
    2291       785142 :                 Path       *innerpath = (Path *) lfirst(lc2);
    2292              : 
    2293              :                 /*
    2294              :                  * We cannot use an inner path that is parameterized by the
    2295              :                  * outer rel, either.
    2296              :                  */
    2297       785142 :                 if (PATH_PARAM_BY_REL(innerpath, outerrel))
    2298       207430 :                     continue;
    2299              : 
    2300       577712 :                 if (outerpath == cheapest_startup_outer &&
    2301              :                     innerpath == cheapest_total_inner)
    2302       415068 :                     continue;   /* already tried it */
    2303              : 
    2304       162644 :                 try_hashjoin_path(root,
    2305              :                                   joinrel,
    2306              :                                   outerpath,
    2307              :                                   innerpath,
    2308              :                                   hashclauses,
    2309              :                                   jointype,
    2310              :                                   extra);
    2311              :             }
    2312              :         }
    2313              : 
    2314              :         /*
    2315              :          * If the joinrel is parallel-safe, we may be able to consider a
    2316              :          * partial hash join.
    2317              :          *
    2318              :          * However, we can't handle JOIN_RIGHT_SEMI, because the hash table is
    2319              :          * either a shared hash table or a private hash table per backend.  In
    2320              :          * the shared case, there is no concurrency protection for the match
    2321              :          * flags, so multiple workers could inspect and set the flags
    2322              :          * concurrently, potentially producing incorrect results.  In the
    2323              :          * private case, each worker has its own copy of the hash table, so no
    2324              :          * single process has all the match flags.
    2325              :          *
    2326              :          * Also, the resulting path must not be parameterized.
    2327              :          */
    2328       475753 :         if (joinrel->consider_parallel &&
    2329       428955 :             jointype != JOIN_RIGHT_SEMI &&
    2330       428955 :             outerrel->partial_pathlist != NIL &&
    2331        59410 :             bms_is_empty(joinrel->lateral_relids))
    2332              :         {
    2333              :             Path       *cheapest_partial_outer;
    2334        59410 :             Path       *cheapest_partial_inner = NULL;
    2335        59410 :             Path       *cheapest_safe_inner = NULL;
    2336              : 
    2337        59410 :             cheapest_partial_outer =
    2338        59410 :                 (Path *) linitial(outerrel->partial_pathlist);
    2339              : 
    2340              :             /*
    2341              :              * Can we use a partial inner plan too, so that we can build a
    2342              :              * shared hash table in parallel?
    2343              :              */
    2344        59410 :             if (innerrel->partial_pathlist != NIL &&
    2345              :                 enable_parallel_hash)
    2346              :             {
    2347        57878 :                 cheapest_partial_inner =
    2348        57878 :                     (Path *) linitial(innerrel->partial_pathlist);
    2349        57878 :                 try_partial_hashjoin_path(root, joinrel,
    2350              :                                           cheapest_partial_outer,
    2351              :                                           cheapest_partial_inner,
    2352              :                                           hashclauses, jointype, extra,
    2353              :                                           true /* parallel_hash */ );
    2354              :             }
    2355              : 
    2356              :             /*
    2357              :              * Normally, given that the joinrel is parallel-safe, the cheapest
    2358              :              * total inner path will also be parallel-safe, but if not, we'll
    2359              :              * have to search for the cheapest safe, unparameterized inner
    2360              :              * path.  If full, right, or right-anti join, we can't use
    2361              :              * parallelism (building the hash table in each backend) because
    2362              :              * no one process has all the match bits.
    2363              :              */
    2364        59410 :             if (jointype == JOIN_FULL ||
    2365        56423 :                 jointype == JOIN_RIGHT ||
    2366              :                 jointype == JOIN_RIGHT_ANTI)
    2367         3244 :                 cheapest_safe_inner = NULL;
    2368        56166 :             else if (cheapest_total_inner->parallel_safe)
    2369        55947 :                 cheapest_safe_inner = cheapest_total_inner;
    2370              :             else
    2371              :                 cheapest_safe_inner =
    2372          219 :                     get_cheapest_parallel_safe_total_inner(innerrel->pathlist);
    2373              : 
    2374        59410 :             if (cheapest_safe_inner != NULL)
    2375        56138 :                 try_partial_hashjoin_path(root, joinrel,
    2376              :                                           cheapest_partial_outer,
    2377              :                                           cheapest_safe_inner,
    2378              :                                           hashclauses, jointype, extra,
    2379              :                                           false /* parallel_hash */ );
    2380              :         }
    2381              :     }
    2382              : }
    2383              : 
    2384              : /*
    2385              :  * select_mergejoin_clauses
    2386              :  *    Select mergejoin clauses that are usable for a particular join.
    2387              :  *    Returns a list of RestrictInfo nodes for those clauses.
    2388              :  *
    2389              :  * *mergejoin_allowed is normally set to true, but it is set to false if
    2390              :  * this is a right-semi join, or this is a right/right-anti/full join and
    2391              :  * there are nonmergejoinable join clauses.  The executor's mergejoin
    2392              :  * machinery cannot handle such cases, so we have to avoid generating a
    2393              :  * mergejoin plan.  (Note that this flag does NOT consider whether there are
    2394              :  * actually any mergejoinable clauses.  This is correct because in some
    2395              :  * cases we need to build a clauseless mergejoin.  Simply returning NIL is
    2396              :  * therefore not enough to distinguish safe from unsafe cases.)
    2397              :  *
    2398              :  * We also mark each selected RestrictInfo to show which side is currently
    2399              :  * being considered as outer.  These are transient markings that are only
    2400              :  * good for the duration of the current add_paths_to_joinrel() call!
    2401              :  *
    2402              :  * We examine each restrictinfo clause known for the join to see
    2403              :  * if it is mergejoinable and involves vars from the two sub-relations
    2404              :  * currently of interest.
    2405              :  */
    2406              : static List *
    2407       553686 : select_mergejoin_clauses(PlannerInfo *root,
    2408              :                          RelOptInfo *joinrel,
    2409              :                          RelOptInfo *outerrel,
    2410              :                          RelOptInfo *innerrel,
    2411              :                          List *restrictlist,
    2412              :                          JoinType jointype,
    2413              :                          bool *mergejoin_allowed)
    2414              : {
    2415       553686 :     List       *result_list = NIL;
    2416       553686 :     bool        isouterjoin = IS_OUTER_JOIN(jointype);
    2417       553686 :     bool        have_nonmergeable_joinclause = false;
    2418              :     ListCell   *l;
    2419              : 
    2420              :     /*
    2421              :      * For now we do not support RIGHT_SEMI join in mergejoin: the benefit of
    2422              :      * swapping inputs tends to be small here.
    2423              :      */
    2424       553686 :     if (jointype == JOIN_RIGHT_SEMI)
    2425              :     {
    2426         4830 :         *mergejoin_allowed = false;
    2427         4830 :         return NIL;
    2428              :     }
    2429              : 
    2430      1166391 :     foreach(l, restrictlist)
    2431              :     {
    2432       617535 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
    2433              : 
    2434              :         /*
    2435              :          * If processing an outer join, only use its own join clauses in the
    2436              :          * merge.  For inner joins we can use pushed-down clauses too. (Note:
    2437              :          * we don't set have_nonmergeable_joinclause here because pushed-down
    2438              :          * clauses will become otherquals not joinquals.)
    2439              :          */
    2440       617535 :         if (isouterjoin && RINFO_IS_PUSHED_DOWN(restrictinfo, joinrel->relids))
    2441        11305 :             continue;
    2442              : 
    2443              :         /* Check that clause is a mergeable operator clause */
    2444       606230 :         if (!restrictinfo->can_join ||
    2445       552723 :             restrictinfo->mergeopfamilies == NIL)
    2446              :         {
    2447              :             /*
    2448              :              * The executor can handle extra joinquals that are constants, but
    2449              :              * not anything else, when doing right/right-anti/full merge join.
    2450              :              * (The reason to support constants is so we can do FULL JOIN ON
    2451              :              * FALSE.)
    2452              :              */
    2453        65435 :             if (!restrictinfo->clause || !IsA(restrictinfo->clause, Const))
    2454        58577 :                 have_nonmergeable_joinclause = true;
    2455        65435 :             continue;           /* not mergejoinable */
    2456              :         }
    2457              : 
    2458              :         /*
    2459              :          * Check if clause has the form "outer op inner" or "inner op outer".
    2460              :          */
    2461       540795 :         if (!clause_sides_match_join(restrictinfo, outerrel->relids,
    2462              :                                      innerrel->relids))
    2463              :         {
    2464          672 :             have_nonmergeable_joinclause = true;
    2465          672 :             continue;           /* no good for these input relations */
    2466              :         }
    2467              : 
    2468              :         /*
    2469              :          * If clause has the form "inner op outer", check if its operator has
    2470              :          * valid commutator.  This is necessary because mergejoin clauses in
    2471              :          * this form will get commuted in createplan.c to put the outer var on
    2472              :          * the left (see get_switched_clauses).  This probably shouldn't ever
    2473              :          * fail, since mergejoinable operators ought to have commutators, but
    2474              :          * be paranoid.
    2475              :          *
    2476              :          * The clause being mergejoinable indicates that it's an OpExpr.
    2477              :          */
    2478       808125 :         if (!restrictinfo->outer_is_left &&
    2479       268002 :             !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
    2480              :         {
    2481           26 :             have_nonmergeable_joinclause = true;
    2482           26 :             continue;
    2483              :         }
    2484              : 
    2485              :         /*
    2486              :          * Insist that each side have a non-redundant eclass.  This
    2487              :          * restriction is needed because various bits of the planner expect
    2488              :          * that each clause in a merge be associable with some pathkey in a
    2489              :          * canonical pathkey list, but redundant eclasses can't appear in
    2490              :          * canonical sort orderings.  (XXX it might be worth relaxing this,
    2491              :          * but not enough time to address it for 8.3.)
    2492              :          */
    2493       540097 :         update_mergeclause_eclasses(root, restrictinfo);
    2494              : 
    2495       540097 :         if (EC_MUST_BE_REDUNDANT(restrictinfo->left_ec) ||
    2496       540065 :             EC_MUST_BE_REDUNDANT(restrictinfo->right_ec))
    2497              :         {
    2498           84 :             have_nonmergeable_joinclause = true;
    2499           84 :             continue;           /* can't handle redundant eclasses */
    2500              :         }
    2501              : 
    2502       540013 :         result_list = lappend(result_list, restrictinfo);
    2503              :     }
    2504              : 
    2505              :     /*
    2506              :      * Report whether mergejoin is allowed (see comment at top of function).
    2507              :      */
    2508       548856 :     switch (jointype)
    2509              :     {
    2510        70633 :         case JOIN_RIGHT:
    2511              :         case JOIN_RIGHT_ANTI:
    2512              :         case JOIN_FULL:
    2513        70633 :             *mergejoin_allowed = !have_nonmergeable_joinclause;
    2514        70633 :             break;
    2515       478223 :         default:
    2516       478223 :             *mergejoin_allowed = true;
    2517       478223 :             break;
    2518              :     }
    2519              : 
    2520       548856 :     return result_list;
    2521              : }
        

Generated by: LCOV version 2.0-1