LCOV - code coverage report
Current view: top level - src/backend/optimizer/plan - createplan.c (source / functions) Hit Total Coverage
Test: PostgreSQL Lines: 1871 2137 87.6 %
Date: 2017-09-29 15:12:54 Functions: 101 107 94.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * createplan.c
       4             :  *    Routines to create the desired plan for processing a query.
       5             :  *    Planning is complete, we just need to convert the selected
       6             :  *    Path into a Plan.
       7             :  *
       8             :  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
       9             :  * Portions Copyright (c) 1994, Regents of the University of California
      10             :  *
      11             :  *
      12             :  * IDENTIFICATION
      13             :  *    src/backend/optimizer/plan/createplan.c
      14             :  *
      15             :  *-------------------------------------------------------------------------
      16             :  */
      17             : #include "postgres.h"
      18             : 
      19             : #include <limits.h>
      20             : #include <math.h>
      21             : 
      22             : #include "access/stratnum.h"
      23             : #include "access/sysattr.h"
      24             : #include "catalog/pg_class.h"
      25             : #include "foreign/fdwapi.h"
      26             : #include "miscadmin.h"
      27             : #include "nodes/extensible.h"
      28             : #include "nodes/makefuncs.h"
      29             : #include "nodes/nodeFuncs.h"
      30             : #include "optimizer/clauses.h"
      31             : #include "optimizer/cost.h"
      32             : #include "optimizer/paths.h"
      33             : #include "optimizer/placeholder.h"
      34             : #include "optimizer/plancat.h"
      35             : #include "optimizer/planmain.h"
      36             : #include "optimizer/planner.h"
      37             : #include "optimizer/predtest.h"
      38             : #include "optimizer/restrictinfo.h"
      39             : #include "optimizer/subselect.h"
      40             : #include "optimizer/tlist.h"
      41             : #include "optimizer/var.h"
      42             : #include "parser/parse_clause.h"
      43             : #include "parser/parsetree.h"
      44             : #include "utils/lsyscache.h"
      45             : 
      46             : 
      47             : /*
      48             :  * Flag bits that can appear in the flags argument of create_plan_recurse().
      49             :  * These can be OR-ed together.
      50             :  *
      51             :  * CP_EXACT_TLIST specifies that the generated plan node must return exactly
      52             :  * the tlist specified by the path's pathtarget (this overrides both
      53             :  * CP_SMALL_TLIST and CP_LABEL_TLIST, if those are set).  Otherwise, the
      54             :  * plan node is allowed to return just the Vars and PlaceHolderVars needed
      55             :  * to evaluate the pathtarget.
      56             :  *
      57             :  * CP_SMALL_TLIST specifies that a narrower tlist is preferred.  This is
      58             :  * passed down by parent nodes such as Sort and Hash, which will have to
      59             :  * store the returned tuples.
      60             :  *
      61             :  * CP_LABEL_TLIST specifies that the plan node must return columns matching
      62             :  * any sortgrouprefs specified in its pathtarget, with appropriate
      63             :  * ressortgroupref labels.  This is passed down by parent nodes such as Sort
      64             :  * and Group, which need these values to be available in their inputs.
      65             :  */
      66             : #define CP_EXACT_TLIST      0x0001  /* Plan must return specified tlist */
      67             : #define CP_SMALL_TLIST      0x0002  /* Prefer narrower tlists */
      68             : #define CP_LABEL_TLIST      0x0004  /* tlist must contain sortgrouprefs */
      69             : 
      70             : 
      71             : static Plan *create_plan_recurse(PlannerInfo *root, Path *best_path,
      72             :                     int flags);
      73             : static Plan *create_scan_plan(PlannerInfo *root, Path *best_path,
      74             :                  int flags);
      75             : static List *build_path_tlist(PlannerInfo *root, Path *path);
      76             : static bool use_physical_tlist(PlannerInfo *root, Path *path, int flags);
      77             : static List *get_gating_quals(PlannerInfo *root, List *quals);
      78             : static Plan *create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
      79             :                    List *gating_quals);
      80             : static Plan *create_join_plan(PlannerInfo *root, JoinPath *best_path);
      81             : static Plan *create_append_plan(PlannerInfo *root, AppendPath *best_path);
      82             : static Plan *create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path);
      83             : static Result *create_result_plan(PlannerInfo *root, ResultPath *best_path);
      84             : static ProjectSet *create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path);
      85             : static Material *create_material_plan(PlannerInfo *root, MaterialPath *best_path,
      86             :                      int flags);
      87             : static Plan *create_unique_plan(PlannerInfo *root, UniquePath *best_path,
      88             :                    int flags);
      89             : static Gather *create_gather_plan(PlannerInfo *root, GatherPath *best_path);
      90             : static Plan *create_projection_plan(PlannerInfo *root, ProjectionPath *best_path);
      91             : static Plan *inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe);
      92             : static Sort *create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags);
      93             : static Group *create_group_plan(PlannerInfo *root, GroupPath *best_path);
      94             : static Unique *create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path,
      95             :                          int flags);
      96             : static Agg *create_agg_plan(PlannerInfo *root, AggPath *best_path);
      97             : static Plan *create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path);
      98             : static Result *create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path);
      99             : static WindowAgg *create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path);
     100             : static SetOp *create_setop_plan(PlannerInfo *root, SetOpPath *best_path,
     101             :                   int flags);
     102             : static RecursiveUnion *create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path);
     103             : static void get_column_info_for_window(PlannerInfo *root, WindowClause *wc,
     104             :                            List *tlist,
     105             :                            int numSortCols, AttrNumber *sortColIdx,
     106             :                            int *partNumCols,
     107             :                            AttrNumber **partColIdx,
     108             :                            Oid **partOperators,
     109             :                            int *ordNumCols,
     110             :                            AttrNumber **ordColIdx,
     111             :                            Oid **ordOperators);
     112             : static LockRows *create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path,
     113             :                      int flags);
     114             : static ModifyTable *create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path);
     115             : static Limit *create_limit_plan(PlannerInfo *root, LimitPath *best_path,
     116             :                   int flags);
     117             : static SeqScan *create_seqscan_plan(PlannerInfo *root, Path *best_path,
     118             :                     List *tlist, List *scan_clauses);
     119             : static SampleScan *create_samplescan_plan(PlannerInfo *root, Path *best_path,
     120             :                        List *tlist, List *scan_clauses);
     121             : static Scan *create_indexscan_plan(PlannerInfo *root, IndexPath *best_path,
     122             :                       List *tlist, List *scan_clauses, bool indexonly);
     123             : static BitmapHeapScan *create_bitmap_scan_plan(PlannerInfo *root,
     124             :                         BitmapHeapPath *best_path,
     125             :                         List *tlist, List *scan_clauses);
     126             : static Plan *create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
     127             :                       List **qual, List **indexqual, List **indexECs);
     128             : static void bitmap_subplan_mark_shared(Plan *plan);
     129             : static TidScan *create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
     130             :                     List *tlist, List *scan_clauses);
     131             : static SubqueryScan *create_subqueryscan_plan(PlannerInfo *root,
     132             :                          SubqueryScanPath *best_path,
     133             :                          List *tlist, List *scan_clauses);
     134             : static FunctionScan *create_functionscan_plan(PlannerInfo *root, Path *best_path,
     135             :                          List *tlist, List *scan_clauses);
     136             : static ValuesScan *create_valuesscan_plan(PlannerInfo *root, Path *best_path,
     137             :                        List *tlist, List *scan_clauses);
     138             : static TableFuncScan *create_tablefuncscan_plan(PlannerInfo *root, Path *best_path,
     139             :                           List *tlist, List *scan_clauses);
     140             : static CteScan *create_ctescan_plan(PlannerInfo *root, Path *best_path,
     141             :                     List *tlist, List *scan_clauses);
     142             : static NamedTuplestoreScan *create_namedtuplestorescan_plan(PlannerInfo *root,
     143             :                                 Path *best_path, List *tlist, List *scan_clauses);
     144             : static WorkTableScan *create_worktablescan_plan(PlannerInfo *root, Path *best_path,
     145             :                           List *tlist, List *scan_clauses);
     146             : static ForeignScan *create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
     147             :                         List *tlist, List *scan_clauses);
     148             : static CustomScan *create_customscan_plan(PlannerInfo *root,
     149             :                        CustomPath *best_path,
     150             :                        List *tlist, List *scan_clauses);
     151             : static NestLoop *create_nestloop_plan(PlannerInfo *root, NestPath *best_path);
     152             : static MergeJoin *create_mergejoin_plan(PlannerInfo *root, MergePath *best_path);
     153             : static HashJoin *create_hashjoin_plan(PlannerInfo *root, HashPath *best_path);
     154             : static Node *replace_nestloop_params(PlannerInfo *root, Node *expr);
     155             : static Node *replace_nestloop_params_mutator(Node *node, PlannerInfo *root);
     156             : static void process_subquery_nestloop_params(PlannerInfo *root,
     157             :                                  List *subplan_params);
     158             : static List *fix_indexqual_references(PlannerInfo *root, IndexPath *index_path);
     159             : static List *fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path);
     160             : static Node *fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol);
     161             : static List *get_switched_clauses(List *clauses, Relids outerrelids);
     162             : static List *order_qual_clauses(PlannerInfo *root, List *clauses);
     163             : static void copy_generic_path_info(Plan *dest, Path *src);
     164             : static void copy_plan_costsize(Plan *dest, Plan *src);
     165             : static void label_sort_with_costsize(PlannerInfo *root, Sort *plan,
     166             :                          double limit_tuples);
     167             : static SeqScan *make_seqscan(List *qptlist, List *qpqual, Index scanrelid);
     168             : static SampleScan *make_samplescan(List *qptlist, List *qpqual, Index scanrelid,
     169             :                 TableSampleClause *tsc);
     170             : static IndexScan *make_indexscan(List *qptlist, List *qpqual, Index scanrelid,
     171             :                Oid indexid, List *indexqual, List *indexqualorig,
     172             :                List *indexorderby, List *indexorderbyorig,
     173             :                List *indexorderbyops,
     174             :                ScanDirection indexscandir);
     175             : static IndexOnlyScan *make_indexonlyscan(List *qptlist, List *qpqual,
     176             :                    Index scanrelid, Oid indexid,
     177             :                    List *indexqual, List *indexorderby,
     178             :                    List *indextlist,
     179             :                    ScanDirection indexscandir);
     180             : static BitmapIndexScan *make_bitmap_indexscan(Index scanrelid, Oid indexid,
     181             :                       List *indexqual,
     182             :                       List *indexqualorig);
     183             : static BitmapHeapScan *make_bitmap_heapscan(List *qptlist,
     184             :                      List *qpqual,
     185             :                      Plan *lefttree,
     186             :                      List *bitmapqualorig,
     187             :                      Index scanrelid);
     188             : static TidScan *make_tidscan(List *qptlist, List *qpqual, Index scanrelid,
     189             :              List *tidquals);
     190             : static SubqueryScan *make_subqueryscan(List *qptlist,
     191             :                   List *qpqual,
     192             :                   Index scanrelid,
     193             :                   Plan *subplan);
     194             : static FunctionScan *make_functionscan(List *qptlist, List *qpqual,
     195             :                   Index scanrelid, List *functions, bool funcordinality);
     196             : static ValuesScan *make_valuesscan(List *qptlist, List *qpqual,
     197             :                 Index scanrelid, List *values_lists);
     198             : static TableFuncScan *make_tablefuncscan(List *qptlist, List *qpqual,
     199             :                    Index scanrelid, TableFunc *tablefunc);
     200             : static CteScan *make_ctescan(List *qptlist, List *qpqual,
     201             :              Index scanrelid, int ctePlanId, int cteParam);
     202             : static NamedTuplestoreScan *make_namedtuplestorescan(List *qptlist, List *qpqual,
     203             :                          Index scanrelid, char *enrname);
     204             : static WorkTableScan *make_worktablescan(List *qptlist, List *qpqual,
     205             :                    Index scanrelid, int wtParam);
     206             : static Append *make_append(List *appendplans, List *tlist, List *partitioned_rels);
     207             : static RecursiveUnion *make_recursive_union(List *tlist,
     208             :                      Plan *lefttree,
     209             :                      Plan *righttree,
     210             :                      int wtParam,
     211             :                      List *distinctList,
     212             :                      long numGroups);
     213             : static BitmapAnd *make_bitmap_and(List *bitmapplans);
     214             : static BitmapOr *make_bitmap_or(List *bitmapplans);
     215             : static NestLoop *make_nestloop(List *tlist,
     216             :               List *joinclauses, List *otherclauses, List *nestParams,
     217             :               Plan *lefttree, Plan *righttree,
     218             :               JoinType jointype, bool inner_unique);
     219             : static HashJoin *make_hashjoin(List *tlist,
     220             :               List *joinclauses, List *otherclauses,
     221             :               List *hashclauses,
     222             :               Plan *lefttree, Plan *righttree,
     223             :               JoinType jointype, bool inner_unique);
     224             : static Hash *make_hash(Plan *lefttree,
     225             :           Oid skewTable,
     226             :           AttrNumber skewColumn,
     227             :           bool skewInherit);
     228             : static MergeJoin *make_mergejoin(List *tlist,
     229             :                List *joinclauses, List *otherclauses,
     230             :                List *mergeclauses,
     231             :                Oid *mergefamilies,
     232             :                Oid *mergecollations,
     233             :                int *mergestrategies,
     234             :                bool *mergenullsfirst,
     235             :                Plan *lefttree, Plan *righttree,
     236             :                JoinType jointype, bool inner_unique,
     237             :                bool skip_mark_restore);
     238             : static Sort *make_sort(Plan *lefttree, int numCols,
     239             :           AttrNumber *sortColIdx, Oid *sortOperators,
     240             :           Oid *collations, bool *nullsFirst);
     241             : static Plan *prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
     242             :                            Relids relids,
     243             :                            const AttrNumber *reqColIdx,
     244             :                            bool adjust_tlist_in_place,
     245             :                            int *p_numsortkeys,
     246             :                            AttrNumber **p_sortColIdx,
     247             :                            Oid **p_sortOperators,
     248             :                            Oid **p_collations,
     249             :                            bool **p_nullsFirst);
     250             : static EquivalenceMember *find_ec_member_for_tle(EquivalenceClass *ec,
     251             :                        TargetEntry *tle,
     252             :                        Relids relids);
     253             : static Sort *make_sort_from_pathkeys(Plan *lefttree, List *pathkeys);
     254             : static Sort *make_sort_from_groupcols(List *groupcls,
     255             :                          AttrNumber *grpColIdx,
     256             :                          Plan *lefttree);
     257             : static Material *make_material(Plan *lefttree);
     258             : static WindowAgg *make_windowagg(List *tlist, Index winref,
     259             :                int partNumCols, AttrNumber *partColIdx, Oid *partOperators,
     260             :                int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators,
     261             :                int frameOptions, Node *startOffset, Node *endOffset,
     262             :                Plan *lefttree);
     263             : static Group *make_group(List *tlist, List *qual, int numGroupCols,
     264             :            AttrNumber *grpColIdx, Oid *grpOperators,
     265             :            Plan *lefttree);
     266             : static Unique *make_unique_from_sortclauses(Plan *lefttree, List *distinctList);
     267             : static Unique *make_unique_from_pathkeys(Plan *lefttree,
     268             :                           List *pathkeys, int numCols);
     269             : static Gather *make_gather(List *qptlist, List *qpqual,
     270             :             int nworkers, int rescan_param, bool single_copy, Plan *subplan);
     271             : static SetOp *make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
     272             :            List *distinctList, AttrNumber flagColIdx, int firstFlag,
     273             :            long numGroups);
     274             : static LockRows *make_lockrows(Plan *lefttree, List *rowMarks, int epqParam);
     275             : static Result *make_result(List *tlist, Node *resconstantqual, Plan *subplan);
     276             : static ProjectSet *make_project_set(List *tlist, Plan *subplan);
     277             : static ModifyTable *make_modifytable(PlannerInfo *root,
     278             :                  CmdType operation, bool canSetTag,
     279             :                  Index nominalRelation, List *partitioned_rels,
     280             :                  List *resultRelations, List *subplans,
     281             :                  List *withCheckOptionLists, List *returningLists,
     282             :                  List *rowMarks, OnConflictExpr *onconflict, int epqParam);
     283             : static GatherMerge *create_gather_merge_plan(PlannerInfo *root,
     284             :                          GatherMergePath *best_path);
     285             : 
     286             : 
     287             : /*
     288             :  * create_plan
     289             :  *    Creates the access plan for a query by recursively processing the
     290             :  *    desired tree of pathnodes, starting at the node 'best_path'.  For
     291             :  *    every pathnode found, we create a corresponding plan node containing
     292             :  *    appropriate id, target list, and qualification information.
     293             :  *
     294             :  *    The tlists and quals in the plan tree are still in planner format,
     295             :  *    ie, Vars still correspond to the parser's numbering.  This will be
     296             :  *    fixed later by setrefs.c.
     297             :  *
     298             :  *    best_path is the best access path
     299             :  *
     300             :  *    Returns a Plan tree.
     301             :  */
     302             : Plan *
     303       25250 : create_plan(PlannerInfo *root, Path *best_path)
     304             : {
     305             :     Plan       *plan;
     306             : 
     307             :     /* plan_params should not be in use in current query level */
     308       25250 :     Assert(root->plan_params == NIL);
     309             : 
     310             :     /* Initialize this module's private workspace in PlannerInfo */
     311       25250 :     root->curOuterRels = NULL;
     312       25250 :     root->curOuterParams = NIL;
     313             : 
     314             :     /* Recursively process the path tree, demanding the correct tlist result */
     315       25250 :     plan = create_plan_recurse(root, best_path, CP_EXACT_TLIST);
     316             : 
     317             :     /*
     318             :      * Make sure the topmost plan node's targetlist exposes the original
     319             :      * column names and other decorative info.  Targetlists generated within
     320             :      * the planner don't bother with that stuff, but we must have it on the
     321             :      * top-level tlist seen at execution time.  However, ModifyTable plan
     322             :      * nodes don't have a tlist matching the querytree targetlist.
     323             :      */
     324       25224 :     if (!IsA(plan, ModifyTable))
     325       20910 :         apply_tlist_labeling(plan->targetlist, root->processed_tlist);
     326             : 
     327             :     /*
     328             :      * Attach any initPlans created in this query level to the topmost plan
     329             :      * node.  (In principle the initplans could go in any plan node at or
     330             :      * above where they're referenced, but there seems no reason to put them
     331             :      * any lower than the topmost node for the query level.  Also, see
     332             :      * comments for SS_finalize_plan before you try to change this.)
     333             :      */
     334       25224 :     SS_attach_initplans(root, plan);
     335             : 
     336             :     /* Check we successfully assigned all NestLoopParams to plan nodes */
     337       25224 :     if (root->curOuterParams != NIL)
     338           0 :         elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
     339             : 
     340             :     /*
     341             :      * Reset plan_params to ensure param IDs used for nestloop params are not
     342             :      * re-used later
     343             :      */
     344       25224 :     root->plan_params = NIL;
     345             : 
     346       25224 :     return plan;
     347             : }
     348             : 
     349             : /*
     350             :  * create_plan_recurse
     351             :  *    Recursive guts of create_plan().
     352             :  */
     353             : static Plan *
     354       45514 : create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
     355             : {
     356             :     Plan       *plan;
     357             : 
     358       45514 :     switch (best_path->pathtype)
     359             :     {
     360             :         case T_SeqScan:
     361             :         case T_SampleScan:
     362             :         case T_IndexScan:
     363             :         case T_IndexOnlyScan:
     364             :         case T_BitmapHeapScan:
     365             :         case T_TidScan:
     366             :         case T_SubqueryScan:
     367             :         case T_FunctionScan:
     368             :         case T_TableFuncScan:
     369             :         case T_ValuesScan:
     370             :         case T_CteScan:
     371             :         case T_WorkTableScan:
     372             :         case T_NamedTuplestoreScan:
     373             :         case T_ForeignScan:
     374             :         case T_CustomScan:
     375       18470 :             plan = create_scan_plan(root, best_path, flags);
     376       18470 :             break;
     377             :         case T_HashJoin:
     378             :         case T_MergeJoin:
     379             :         case T_NestLoop:
     380        3715 :             plan = create_join_plan(root,
     381             :                                     (JoinPath *) best_path);
     382        3715 :             break;
     383             :         case T_Append:
     384         630 :             plan = create_append_plan(root,
     385             :                                       (AppendPath *) best_path);
     386         630 :             break;
     387             :         case T_MergeAppend:
     388          34 :             plan = create_merge_append_plan(root,
     389             :                                             (MergeAppendPath *) best_path);
     390          34 :             break;
     391             :         case T_Result:
     392       12141 :             if (IsA(best_path, ProjectionPath))
     393             :             {
     394         559 :                 plan = create_projection_plan(root,
     395             :                                               (ProjectionPath *) best_path);
     396             :             }
     397       11582 :             else if (IsA(best_path, MinMaxAggPath))
     398             :             {
     399          73 :                 plan = (Plan *) create_minmaxagg_plan(root,
     400             :                                                       (MinMaxAggPath *) best_path);
     401             :             }
     402             :             else
     403             :             {
     404       11509 :                 Assert(IsA(best_path, ResultPath));
     405       11509 :                 plan = (Plan *) create_result_plan(root,
     406             :                                                    (ResultPath *) best_path);
     407             :             }
     408       12141 :             break;
     409             :         case T_ProjectSet:
     410         226 :             plan = (Plan *) create_project_set_plan(root,
     411             :                                                     (ProjectSetPath *) best_path);
     412         226 :             break;
     413             :         case T_Material:
     414         200 :             plan = (Plan *) create_material_plan(root,
     415             :                                                  (MaterialPath *) best_path,
     416             :                                                  flags);
     417         200 :             break;
     418             :         case T_Unique:
     419          81 :             if (IsA(best_path, UpperUniquePath))
     420             :             {
     421          53 :                 plan = (Plan *) create_upper_unique_plan(root,
     422             :                                                          (UpperUniquePath *) best_path,
     423             :                                                          flags);
     424             :             }
     425             :             else
     426             :             {
     427          28 :                 Assert(IsA(best_path, UniquePath));
     428          28 :                 plan = create_unique_plan(root,
     429             :                                           (UniquePath *) best_path,
     430             :                                           flags);
     431             :             }
     432          81 :             break;
     433             :         case T_Gather:
     434          23 :             plan = (Plan *) create_gather_plan(root,
     435             :                                                (GatherPath *) best_path);
     436          23 :             break;
     437             :         case T_Sort:
     438        2516 :             plan = (Plan *) create_sort_plan(root,
     439             :                                              (SortPath *) best_path,
     440             :                                              flags);
     441        2516 :             break;
     442             :         case T_Group:
     443          11 :             plan = (Plan *) create_group_plan(root,
     444             :                                               (GroupPath *) best_path);
     445          11 :             break;
     446             :         case T_Agg:
     447        2393 :             if (IsA(best_path, GroupingSetsPath))
     448          88 :                 plan = create_groupingsets_plan(root,
     449             :                                                 (GroupingSetsPath *) best_path);
     450             :             else
     451             :             {
     452        2305 :                 Assert(IsA(best_path, AggPath));
     453        2305 :                 plan = (Plan *) create_agg_plan(root,
     454             :                                                 (AggPath *) best_path);
     455             :             }
     456        2393 :             break;
     457             :         case T_WindowAgg:
     458         140 :             plan = (Plan *) create_windowagg_plan(root,
     459             :                                                   (WindowAggPath *) best_path);
     460         140 :             break;
     461             :         case T_SetOp:
     462          37 :             plan = (Plan *) create_setop_plan(root,
     463             :                                               (SetOpPath *) best_path,
     464             :                                               flags);
     465          37 :             break;
     466             :         case T_RecursiveUnion:
     467          40 :             plan = (Plan *) create_recursiveunion_plan(root,
     468             :                                                        (RecursiveUnionPath *) best_path);
     469          40 :             break;
     470             :         case T_LockRows:
     471         328 :             plan = (Plan *) create_lockrows_plan(root,
     472             :                                                  (LockRowsPath *) best_path,
     473             :                                                  flags);
     474         328 :             break;
     475             :         case T_ModifyTable:
     476        4340 :             plan = (Plan *) create_modifytable_plan(root,
     477             :                                                     (ModifyTablePath *) best_path);
     478        4314 :             break;
     479             :         case T_Limit:
     480         181 :             plan = (Plan *) create_limit_plan(root,
     481             :                                               (LimitPath *) best_path,
     482             :                                               flags);
     483         181 :             break;
     484             :         case T_GatherMerge:
     485           8 :             plan = (Plan *) create_gather_merge_plan(root,
     486             :                                                      (GatherMergePath *) best_path);
     487           8 :             break;
     488             :         default:
     489           0 :             elog(ERROR, "unrecognized node type: %d",
     490             :                  (int) best_path->pathtype);
     491             :             plan = NULL;        /* keep compiler quiet */
     492             :             break;
     493             :     }
     494             : 
     495       45488 :     return plan;
     496             : }
     497             : 
     498             : /*
     499             :  * create_scan_plan
     500             :  *   Create a scan plan for the parent relation of 'best_path'.
     501             :  */
     502             : static Plan *
     503       18470 : create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
     504             : {
     505       18470 :     RelOptInfo *rel = best_path->parent;
     506             :     List       *scan_clauses;
     507             :     List       *gating_clauses;
     508             :     List       *tlist;
     509             :     Plan       *plan;
     510             : 
     511             :     /*
     512             :      * Extract the relevant restriction clauses from the parent relation. The
     513             :      * executor must apply all these restrictions during the scan, except for
     514             :      * pseudoconstants which we'll take care of below.
     515             :      *
     516             :      * If this is a plain indexscan or index-only scan, we need not consider
     517             :      * restriction clauses that are implied by the index's predicate, so use
     518             :      * indrestrictinfo not baserestrictinfo.  Note that we can't do that for
     519             :      * bitmap indexscans, since there's not necessarily a single index
     520             :      * involved; but it doesn't matter since create_bitmap_scan_plan() will be
     521             :      * able to get rid of such clauses anyway via predicate proof.
     522             :      */
     523       18470 :     switch (best_path->pathtype)
     524             :     {
     525             :         case T_IndexScan:
     526             :         case T_IndexOnlyScan:
     527        4511 :             scan_clauses = castNode(IndexPath, best_path)->indexinfo->indrestrictinfo;
     528        4511 :             break;
     529             :         default:
     530       13959 :             scan_clauses = rel->baserestrictinfo;
     531       13959 :             break;
     532             :     }
     533             : 
     534             :     /*
     535             :      * If this is a parameterized scan, we also need to enforce all the join
     536             :      * clauses available from the outer relation(s).
     537             :      *
     538             :      * For paranoia's sake, don't modify the stored baserestrictinfo list.
     539             :      */
     540       18470 :     if (best_path->param_info)
     541        1049 :         scan_clauses = list_concat(list_copy(scan_clauses),
     542        1049 :                                    best_path->param_info->ppi_clauses);
     543             : 
     544             :     /*
     545             :      * Detect whether we have any pseudoconstant quals to deal with.  Then, if
     546             :      * we'll need a gating Result node, it will be able to project, so there
     547             :      * are no requirements on the child's tlist.
     548             :      */
     549       18470 :     gating_clauses = get_gating_quals(root, scan_clauses);
     550       18470 :     if (gating_clauses)
     551         426 :         flags = 0;
     552             : 
     553             :     /*
     554             :      * For table scans, rather than using the relation targetlist (which is
     555             :      * only those Vars actually needed by the query), we prefer to generate a
     556             :      * tlist containing all Vars in order.  This will allow the executor to
     557             :      * optimize away projection of the table tuples, if possible.
     558             :      */
     559       18470 :     if (use_physical_tlist(root, best_path, flags))
     560             :     {
     561        3911 :         if (best_path->pathtype == T_IndexOnlyScan)
     562             :         {
     563             :             /* For index-only scan, the preferred tlist is the index's */
     564         259 :             tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
     565             : 
     566             :             /*
     567             :              * Transfer any sortgroupref data to the replacement tlist, unless
     568             :              * we don't care because the gating Result will handle it.
     569             :              */
     570         259 :             if (!gating_clauses)
     571         258 :                 apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
     572             :         }
     573             :         else
     574             :         {
     575        3652 :             tlist = build_physical_tlist(root, rel);
     576        3652 :             if (tlist == NIL)
     577             :             {
     578             :                 /* Failed because of dropped cols, so use regular method */
     579           7 :                 tlist = build_path_tlist(root, best_path);
     580             :             }
     581             :             else
     582             :             {
     583             :                 /* As above, transfer sortgroupref data to replacement tlist */
     584        3645 :                 if (!gating_clauses)
     585        3226 :                     apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
     586             :             }
     587             :         }
     588             :     }
     589             :     else
     590             :     {
     591       14559 :         tlist = build_path_tlist(root, best_path);
     592             :     }
     593             : 
     594       18470 :     switch (best_path->pathtype)
     595             :     {
     596             :         case T_SeqScan:
     597        9154 :             plan = (Plan *) create_seqscan_plan(root,
     598             :                                                 best_path,
     599             :                                                 tlist,
     600             :                                                 scan_clauses);
     601        9154 :             break;
     602             : 
     603             :         case T_SampleScan:
     604          36 :             plan = (Plan *) create_samplescan_plan(root,
     605             :                                                    best_path,
     606             :                                                    tlist,
     607             :                                                    scan_clauses);
     608          36 :             break;
     609             : 
     610             :         case T_IndexScan:
     611        3852 :             plan = (Plan *) create_indexscan_plan(root,
     612             :                                                   (IndexPath *) best_path,
     613             :                                                   tlist,
     614             :                                                   scan_clauses,
     615             :                                                   false);
     616        3852 :             break;
     617             : 
     618             :         case T_IndexOnlyScan:
     619         659 :             plan = (Plan *) create_indexscan_plan(root,
     620             :                                                   (IndexPath *) best_path,
     621             :                                                   tlist,
     622             :                                                   scan_clauses,
     623             :                                                   true);
     624         659 :             break;
     625             : 
     626             :         case T_BitmapHeapScan:
     627        1587 :             plan = (Plan *) create_bitmap_scan_plan(root,
     628             :                                                     (BitmapHeapPath *) best_path,
     629             :                                                     tlist,
     630             :                                                     scan_clauses);
     631        1587 :             break;
     632             : 
     633             :         case T_TidScan:
     634          66 :             plan = (Plan *) create_tidscan_plan(root,
     635             :                                                 (TidPath *) best_path,
     636             :                                                 tlist,
     637             :                                                 scan_clauses);
     638          66 :             break;
     639             : 
     640             :         case T_SubqueryScan:
     641        1059 :             plan = (Plan *) create_subqueryscan_plan(root,
     642             :                                                      (SubqueryScanPath *) best_path,
     643             :                                                      tlist,
     644             :                                                      scan_clauses);
     645        1059 :             break;
     646             : 
     647             :         case T_FunctionScan:
     648        1327 :             plan = (Plan *) create_functionscan_plan(root,
     649             :                                                      best_path,
     650             :                                                      tlist,
     651             :                                                      scan_clauses);
     652        1327 :             break;
     653             : 
     654             :         case T_TableFuncScan:
     655          22 :             plan = (Plan *) create_tablefuncscan_plan(root,
     656             :                                                       best_path,
     657             :                                                       tlist,
     658             :                                                       scan_clauses);
     659          22 :             break;
     660             : 
     661             :         case T_ValuesScan:
     662         463 :             plan = (Plan *) create_valuesscan_plan(root,
     663             :                                                    best_path,
     664             :                                                    tlist,
     665             :                                                    scan_clauses);
     666         463 :             break;
     667             : 
     668             :         case T_CteScan:
     669         162 :             plan = (Plan *) create_ctescan_plan(root,
     670             :                                                 best_path,
     671             :                                                 tlist,
     672             :                                                 scan_clauses);
     673         162 :             break;
     674             : 
     675             :         case T_NamedTuplestoreScan:
     676          43 :             plan = (Plan *) create_namedtuplestorescan_plan(root,
     677             :                                                             best_path,
     678             :                                                             tlist,
     679             :                                                             scan_clauses);
     680          43 :             break;
     681             : 
     682             :         case T_WorkTableScan:
     683          40 :             plan = (Plan *) create_worktablescan_plan(root,
     684             :                                                       best_path,
     685             :                                                       tlist,
     686             :                                                       scan_clauses);
     687          40 :             break;
     688             : 
     689             :         case T_ForeignScan:
     690           0 :             plan = (Plan *) create_foreignscan_plan(root,
     691             :                                                     (ForeignPath *) best_path,
     692             :                                                     tlist,
     693             :                                                     scan_clauses);
     694           0 :             break;
     695             : 
     696             :         case T_CustomScan:
     697           0 :             plan = (Plan *) create_customscan_plan(root,
     698             :                                                    (CustomPath *) best_path,
     699             :                                                    tlist,
     700             :                                                    scan_clauses);
     701           0 :             break;
     702             : 
     703             :         default:
     704           0 :             elog(ERROR, "unrecognized node type: %d",
     705             :                  (int) best_path->pathtype);
     706             :             plan = NULL;        /* keep compiler quiet */
     707             :             break;
     708             :     }
     709             : 
     710             :     /*
     711             :      * If there are any pseudoconstant clauses attached to this node, insert a
     712             :      * gating Result node that evaluates the pseudoconstants as one-time
     713             :      * quals.
     714             :      */
     715       18470 :     if (gating_clauses)
     716         426 :         plan = create_gating_plan(root, best_path, plan, gating_clauses);
     717             : 
     718       18470 :     return plan;
     719             : }
     720             : 
     721             : /*
     722             :  * Build a target list (ie, a list of TargetEntry) for the Path's output.
     723             :  *
     724             :  * This is almost just make_tlist_from_pathtarget(), but we also have to
     725             :  * deal with replacing nestloop params.
     726             :  */
     727             : static List *
     728       34429 : build_path_tlist(PlannerInfo *root, Path *path)
     729             : {
     730       34429 :     List       *tlist = NIL;
     731       34429 :     Index      *sortgrouprefs = path->pathtarget->sortgrouprefs;
     732       34429 :     int         resno = 1;
     733             :     ListCell   *v;
     734             : 
     735      107523 :     foreach(v, path->pathtarget->exprs)
     736             :     {
     737       73094 :         Node       *node = (Node *) lfirst(v);
     738             :         TargetEntry *tle;
     739             : 
     740             :         /*
     741             :          * If it's a parameterized path, there might be lateral references in
     742             :          * the tlist, which need to be replaced with Params.  There's no need
     743             :          * to remake the TargetEntry nodes, so apply this to each list item
     744             :          * separately.
     745             :          */
     746       73094 :         if (path->param_info)
     747        1676 :             node = replace_nestloop_params(root, node);
     748             : 
     749       73094 :         tle = makeTargetEntry((Expr *) node,
     750             :                               resno,
     751             :                               NULL,
     752             :                               false);
     753       73094 :         if (sortgrouprefs)
     754       55700 :             tle->ressortgroupref = sortgrouprefs[resno - 1];
     755             : 
     756       73094 :         tlist = lappend(tlist, tle);
     757       73094 :         resno++;
     758             :     }
     759       34429 :     return tlist;
     760             : }
     761             : 
     762             : /*
     763             :  * use_physical_tlist
     764             :  *      Decide whether to use a tlist matching relation structure,
     765             :  *      rather than only those Vars actually referenced.
     766             :  */
     767             : static bool
     768       18470 : use_physical_tlist(PlannerInfo *root, Path *path, int flags)
     769             : {
     770       18470 :     RelOptInfo *rel = path->parent;
     771             :     int         i;
     772             :     ListCell   *lc;
     773             : 
     774             :     /*
     775             :      * Forget it if either exact tlist or small tlist is demanded.
     776             :      */
     777       18470 :     if (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST))
     778       11071 :         return false;
     779             : 
     780             :     /*
     781             :      * We can do this for real relation scans, subquery scans, function scans,
     782             :      * tablefunc scans, values scans, and CTE scans (but not for, eg, joins).
     783             :      */
     784        7990 :     if (rel->rtekind != RTE_RELATION &&
     785        1030 :         rel->rtekind != RTE_SUBQUERY &&
     786         670 :         rel->rtekind != RTE_FUNCTION &&
     787         440 :         rel->rtekind != RTE_TABLEFUNC &&
     788         281 :         rel->rtekind != RTE_VALUES &&
     789          72 :         rel->rtekind != RTE_CTE)
     790          37 :         return false;
     791             : 
     792             :     /*
     793             :      * Can't do it with inheritance cases either (mainly because Append
     794             :      * doesn't project; this test may be unnecessary now that
     795             :      * create_append_plan instructs its children to return an exact tlist).
     796             :      */
     797        7362 :     if (rel->reloptkind != RELOPT_BASEREL)
     798           0 :         return false;
     799             : 
     800             :     /*
     801             :      * Also, don't do it to a CustomPath; the premise that we're extracting
     802             :      * columns from a simple physical tuple is unlikely to hold for those.
     803             :      * (When it does make sense, the custom path creator can set up the path's
     804             :      * pathtarget that way.)
     805             :      */
     806        7362 :     if (IsA(path, CustomPath))
     807           0 :         return false;
     808             : 
     809             :     /*
     810             :      * Can't do it if any system columns or whole-row Vars are requested.
     811             :      * (This could possibly be fixed but would take some fragile assumptions
     812             :      * in setrefs.c, I think.)
     813             :      */
     814       53351 :     for (i = rel->min_attr; i <= 0; i++)
     815             :     {
     816       49407 :         if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
     817        3418 :             return false;
     818             :     }
     819             : 
     820             :     /*
     821             :      * Can't do it if the rel is required to emit any placeholder expressions,
     822             :      * either.
     823             :      */
     824        4053 :     foreach(lc, root->placeholder_list)
     825             :     {
     826         124 :         PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
     827             : 
     828         242 :         if (bms_nonempty_difference(phinfo->ph_needed, rel->relids) &&
     829         118 :             bms_is_subset(phinfo->ph_eval_at, rel->relids))
     830          15 :             return false;
     831             :     }
     832             : 
     833             :     /*
     834             :      * Also, can't do it if CP_LABEL_TLIST is specified and path is requested
     835             :      * to emit any sort/group columns that are not simple Vars.  (If they are
     836             :      * simple Vars, they should appear in the physical tlist, and
     837             :      * apply_pathtarget_labeling_to_tlist will take care of getting them
     838             :      * labeled again.)  We also have to check that no two sort/group columns
     839             :      * are the same Var, else that element of the physical tlist would need
     840             :      * conflicting ressortgroupref labels.
     841             :      */
     842        3929 :     if ((flags & CP_LABEL_TLIST) && path->pathtarget->sortgrouprefs)
     843             :     {
     844         156 :         Bitmapset  *sortgroupatts = NULL;
     845             : 
     846         156 :         i = 0;
     847         455 :         foreach(lc, path->pathtarget->exprs)
     848             :         {
     849         317 :             Expr       *expr = (Expr *) lfirst(lc);
     850             : 
     851         317 :             if (path->pathtarget->sortgrouprefs[i])
     852             :             {
     853         232 :                 if (expr && IsA(expr, Var))
     854         214 :                 {
     855         216 :                     int         attno = ((Var *) expr)->varattno;
     856             : 
     857         216 :                     attno -= FirstLowInvalidHeapAttributeNumber;
     858         216 :                     if (bms_is_member(attno, sortgroupatts))
     859           2 :                         return false;
     860         214 :                     sortgroupatts = bms_add_member(sortgroupatts, attno);
     861             :                 }
     862             :                 else
     863          16 :                     return false;
     864             :             }
     865         299 :             i++;
     866             :         }
     867             :     }
     868             : 
     869        3911 :     return true;
     870             : }
     871             : 
     872             : /*
     873             :  * get_gating_quals
     874             :  *    See if there are pseudoconstant quals in a node's quals list
     875             :  *
     876             :  * If the node's quals list includes any pseudoconstant quals,
     877             :  * return just those quals.
     878             :  */
     879             : static List *
     880       22185 : get_gating_quals(PlannerInfo *root, List *quals)
     881             : {
     882             :     /* No need to look if we know there are no pseudoconstants */
     883       22185 :     if (!root->hasPseudoConstantQuals)
     884       21625 :         return NIL;
     885             : 
     886             :     /* Sort into desirable execution order while still in RestrictInfo form */
     887         560 :     quals = order_qual_clauses(root, quals);
     888             : 
     889             :     /* Pull out any pseudoconstant quals from the RestrictInfo list */
     890         560 :     return extract_actual_clauses(quals, true);
     891             : }
     892             : 
     893             : /*
     894             :  * create_gating_plan
     895             :  *    Deal with pseudoconstant qual clauses
     896             :  *
     897             :  * Add a gating Result node atop the already-built plan.
     898             :  */
     899             : static Plan *
     900         446 : create_gating_plan(PlannerInfo *root, Path *path, Plan *plan,
     901             :                    List *gating_quals)
     902             : {
     903             :     Plan       *gplan;
     904             : 
     905         446 :     Assert(gating_quals);
     906             : 
     907             :     /*
     908             :      * Since we need a Result node anyway, always return the path's requested
     909             :      * tlist; that's never a wrong choice, even if the parent node didn't ask
     910             :      * for CP_EXACT_TLIST.
     911             :      */
     912         446 :     gplan = (Plan *) make_result(build_path_tlist(root, path),
     913             :                                  (Node *) gating_quals,
     914             :                                  plan);
     915             : 
     916             :     /*
     917             :      * Notice that we don't change cost or size estimates when doing gating.
     918             :      * The costs of qual eval were already included in the subplan's cost.
     919             :      * Leaving the size alone amounts to assuming that the gating qual will
     920             :      * succeed, which is the conservative estimate for planning upper queries.
     921             :      * We certainly don't want to assume the output size is zero (unless the
     922             :      * gating qual is actually constant FALSE, and that case is dealt with in
     923             :      * clausesel.c).  Interpolating between the two cases is silly, because it
     924             :      * doesn't reflect what will really happen at runtime, and besides which
     925             :      * in most cases we have only a very bad idea of the probability of the
     926             :      * gating qual being true.
     927             :      */
     928         446 :     copy_plan_costsize(gplan, plan);
     929             : 
     930             :     /* Gating quals could be unsafe, so better use the Path's safety flag */
     931         446 :     gplan->parallel_safe = path->parallel_safe;
     932             : 
     933         446 :     return gplan;
     934             : }
     935             : 
     936             : /*
     937             :  * create_join_plan
     938             :  *    Create a join plan for 'best_path' and (recursively) plans for its
     939             :  *    inner and outer paths.
     940             :  */
     941             : static Plan *
     942        3715 : create_join_plan(PlannerInfo *root, JoinPath *best_path)
     943             : {
     944             :     Plan       *plan;
     945             :     List       *gating_clauses;
     946             : 
     947        3715 :     switch (best_path->path.pathtype)
     948             :     {
     949             :         case T_MergeJoin:
     950         165 :             plan = (Plan *) create_mergejoin_plan(root,
     951             :                                                   (MergePath *) best_path);
     952         165 :             break;
     953             :         case T_HashJoin:
     954        1364 :             plan = (Plan *) create_hashjoin_plan(root,
     955             :                                                  (HashPath *) best_path);
     956        1364 :             break;
     957             :         case T_NestLoop:
     958        2186 :             plan = (Plan *) create_nestloop_plan(root,
     959             :                                                  (NestPath *) best_path);
     960        2186 :             break;
     961             :         default:
     962           0 :             elog(ERROR, "unrecognized node type: %d",
     963             :                  (int) best_path->path.pathtype);
     964             :             plan = NULL;        /* keep compiler quiet */
     965             :             break;
     966             :     }
     967             : 
     968             :     /*
     969             :      * If there are any pseudoconstant clauses attached to this node, insert a
     970             :      * gating Result node that evaluates the pseudoconstants as one-time
     971             :      * quals.
     972             :      */
     973        3715 :     gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
     974        3715 :     if (gating_clauses)
     975          20 :         plan = create_gating_plan(root, (Path *) best_path, plan,
     976             :                                   gating_clauses);
     977             : 
     978             : #ifdef NOT_USED
     979             : 
     980             :     /*
     981             :      * * Expensive function pullups may have pulled local predicates * into
     982             :      * this path node.  Put them in the qpqual of the plan node. * JMH,
     983             :      * 6/15/92
     984             :      */
     985             :     if (get_loc_restrictinfo(best_path) != NIL)
     986             :         set_qpqual((Plan) plan,
     987             :                    list_concat(get_qpqual((Plan) plan),
     988             :                                get_actual_clauses(get_loc_restrictinfo(best_path))));
     989             : #endif
     990             : 
     991        3715 :     return plan;
     992             : }
     993             : 
     994             : /*
     995             :  * create_append_plan
     996             :  *    Create an Append plan for 'best_path' and (recursively) plans
     997             :  *    for its subpaths.
     998             :  *
     999             :  *    Returns a Plan node.
    1000             :  */
    1001             : static Plan *
    1002         630 : create_append_plan(PlannerInfo *root, AppendPath *best_path)
    1003             : {
    1004             :     Append     *plan;
    1005         630 :     List       *tlist = build_path_tlist(root, &best_path->path);
    1006         630 :     List       *subplans = NIL;
    1007             :     ListCell   *subpaths;
    1008             : 
    1009             :     /*
    1010             :      * The subpaths list could be empty, if every child was proven empty by
    1011             :      * constraint exclusion.  In that case generate a dummy plan that returns
    1012             :      * no rows.
    1013             :      *
    1014             :      * Note that an AppendPath with no members is also generated in certain
    1015             :      * cases where there was no appending construct at all, but we know the
    1016             :      * relation is empty (see set_dummy_rel_pathlist).
    1017             :      */
    1018         630 :     if (best_path->subpaths == NIL)
    1019             :     {
    1020             :         /* Generate a Result plan with constant-FALSE gating qual */
    1021             :         Plan       *plan;
    1022             : 
    1023          29 :         plan = (Plan *) make_result(tlist,
    1024          29 :                                     (Node *) list_make1(makeBoolConst(false,
    1025             :                                                                       false)),
    1026             :                                     NULL);
    1027             : 
    1028          29 :         copy_generic_path_info(plan, (Path *) best_path);
    1029             : 
    1030          29 :         return plan;
    1031             :     }
    1032             : 
    1033             :     /* Build the plan for each child */
    1034        2096 :     foreach(subpaths, best_path->subpaths)
    1035             :     {
    1036        1495 :         Path       *subpath = (Path *) lfirst(subpaths);
    1037             :         Plan       *subplan;
    1038             : 
    1039             :         /* Must insist that all children return the same tlist */
    1040        1495 :         subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
    1041             : 
    1042        1495 :         subplans = lappend(subplans, subplan);
    1043             :     }
    1044             : 
    1045             :     /*
    1046             :      * XXX ideally, if there's just one child, we'd not bother to generate an
    1047             :      * Append node but just return the single child.  At the moment this does
    1048             :      * not work because the varno of the child scan plan won't match the
    1049             :      * parent-rel Vars it'll be asked to emit.
    1050             :      */
    1051             : 
    1052         601 :     plan = make_append(subplans, tlist, best_path->partitioned_rels);
    1053             : 
    1054         601 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1055             : 
    1056         601 :     return (Plan *) plan;
    1057             : }
    1058             : 
    1059             : /*
    1060             :  * create_merge_append_plan
    1061             :  *    Create a MergeAppend plan for 'best_path' and (recursively) plans
    1062             :  *    for its subpaths.
    1063             :  *
    1064             :  *    Returns a Plan node.
    1065             :  */
    1066             : static Plan *
    1067          34 : create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
    1068             : {
    1069          34 :     MergeAppend *node = makeNode(MergeAppend);
    1070          34 :     Plan       *plan = &node->plan;
    1071          34 :     List       *tlist = build_path_tlist(root, &best_path->path);
    1072          34 :     List       *pathkeys = best_path->path.pathkeys;
    1073          34 :     List       *subplans = NIL;
    1074             :     ListCell   *subpaths;
    1075             : 
    1076             :     /*
    1077             :      * We don't have the actual creation of the MergeAppend node split out
    1078             :      * into a separate make_xxx function.  This is because we want to run
    1079             :      * prepare_sort_from_pathkeys on it before we do so on the individual
    1080             :      * child plans, to make cross-checking the sort info easier.
    1081             :      */
    1082          34 :     copy_generic_path_info(plan, (Path *) best_path);
    1083          34 :     plan->targetlist = tlist;
    1084          34 :     plan->qual = NIL;
    1085          34 :     plan->lefttree = NULL;
    1086          34 :     plan->righttree = NULL;
    1087             : 
    1088             :     /* Compute sort column info, and adjust MergeAppend's tlist as needed */
    1089          68 :     (void) prepare_sort_from_pathkeys(plan, pathkeys,
    1090          34 :                                       best_path->path.parent->relids,
    1091             :                                       NULL,
    1092             :                                       true,
    1093             :                                       &node->numCols,
    1094             :                                       &node->sortColIdx,
    1095             :                                       &node->sortOperators,
    1096             :                                       &node->collations,
    1097             :                                       &node->nullsFirst);
    1098             : 
    1099             :     /*
    1100             :      * Now prepare the child plans.  We must apply prepare_sort_from_pathkeys
    1101             :      * even to subplans that don't need an explicit sort, to make sure they
    1102             :      * are returning the same sort key columns the MergeAppend expects.
    1103             :      */
    1104         134 :     foreach(subpaths, best_path->subpaths)
    1105             :     {
    1106         100 :         Path       *subpath = (Path *) lfirst(subpaths);
    1107             :         Plan       *subplan;
    1108             :         int         numsortkeys;
    1109             :         AttrNumber *sortColIdx;
    1110             :         Oid        *sortOperators;
    1111             :         Oid        *collations;
    1112             :         bool       *nullsFirst;
    1113             : 
    1114             :         /* Build the child plan */
    1115             :         /* Must insist that all children return the same tlist */
    1116         100 :         subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
    1117             : 
    1118             :         /* Compute sort column info, and adjust subplan's tlist as needed */
    1119         100 :         subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
    1120         100 :                                              subpath->parent->relids,
    1121         100 :                                              node->sortColIdx,
    1122             :                                              false,
    1123             :                                              &numsortkeys,
    1124             :                                              &sortColIdx,
    1125             :                                              &sortOperators,
    1126             :                                              &collations,
    1127             :                                              &nullsFirst);
    1128             : 
    1129             :         /*
    1130             :          * Check that we got the same sort key information.  We just Assert
    1131             :          * that the sortops match, since those depend only on the pathkeys;
    1132             :          * but it seems like a good idea to check the sort column numbers
    1133             :          * explicitly, to ensure the tlists really do match up.
    1134             :          */
    1135         100 :         Assert(numsortkeys == node->numCols);
    1136         100 :         if (memcmp(sortColIdx, node->sortColIdx,
    1137             :                    numsortkeys * sizeof(AttrNumber)) != 0)
    1138           0 :             elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
    1139         100 :         Assert(memcmp(sortOperators, node->sortOperators,
    1140             :                       numsortkeys * sizeof(Oid)) == 0);
    1141         100 :         Assert(memcmp(collations, node->collations,
    1142             :                       numsortkeys * sizeof(Oid)) == 0);
    1143         100 :         Assert(memcmp(nullsFirst, node->nullsFirst,
    1144             :                       numsortkeys * sizeof(bool)) == 0);
    1145             : 
    1146             :         /* Now, insert a Sort node if subplan isn't sufficiently ordered */
    1147         100 :         if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
    1148             :         {
    1149          10 :             Sort       *sort = make_sort(subplan, numsortkeys,
    1150             :                                          sortColIdx, sortOperators,
    1151             :                                          collations, nullsFirst);
    1152             : 
    1153          10 :             label_sort_with_costsize(root, sort, best_path->limit_tuples);
    1154          10 :             subplan = (Plan *) sort;
    1155             :         }
    1156             : 
    1157         100 :         subplans = lappend(subplans, subplan);
    1158             :     }
    1159             : 
    1160          34 :     node->partitioned_rels = best_path->partitioned_rels;
    1161          34 :     node->mergeplans = subplans;
    1162             : 
    1163          34 :     return (Plan *) node;
    1164             : }
    1165             : 
    1166             : /*
    1167             :  * create_result_plan
    1168             :  *    Create a Result plan for 'best_path'.
    1169             :  *    This is only used for degenerate cases, such as a query with an empty
    1170             :  *    jointree.
    1171             :  *
    1172             :  *    Returns a Plan node.
    1173             :  */
    1174             : static Result *
    1175       11509 : create_result_plan(PlannerInfo *root, ResultPath *best_path)
    1176             : {
    1177             :     Result     *plan;
    1178             :     List       *tlist;
    1179             :     List       *quals;
    1180             : 
    1181       11509 :     tlist = build_path_tlist(root, &best_path->path);
    1182             : 
    1183             :     /* best_path->quals is just bare clauses */
    1184       11509 :     quals = order_qual_clauses(root, best_path->quals);
    1185             : 
    1186       11509 :     plan = make_result(tlist, (Node *) quals, NULL);
    1187             : 
    1188       11509 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1189             : 
    1190       11509 :     return plan;
    1191             : }
    1192             : 
    1193             : /*
    1194             :  * create_project_set_plan
    1195             :  *    Create a ProjectSet plan for 'best_path'.
    1196             :  *
    1197             :  *    Returns a Plan node.
    1198             :  */
    1199             : static ProjectSet *
    1200         226 : create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
    1201             : {
    1202             :     ProjectSet *plan;
    1203             :     Plan       *subplan;
    1204             :     List       *tlist;
    1205             : 
    1206             :     /* Since we intend to project, we don't need to constrain child tlist */
    1207         226 :     subplan = create_plan_recurse(root, best_path->subpath, 0);
    1208             : 
    1209         226 :     tlist = build_path_tlist(root, &best_path->path);
    1210             : 
    1211         226 :     plan = make_project_set(tlist, subplan);
    1212             : 
    1213         226 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1214             : 
    1215         226 :     return plan;
    1216             : }
    1217             : 
    1218             : /*
    1219             :  * create_material_plan
    1220             :  *    Create a Material plan for 'best_path' and (recursively) plans
    1221             :  *    for its subpaths.
    1222             :  *
    1223             :  *    Returns a Plan node.
    1224             :  */
    1225             : static Material *
    1226         200 : create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
    1227             : {
    1228             :     Material   *plan;
    1229             :     Plan       *subplan;
    1230             : 
    1231             :     /*
    1232             :      * We don't want any excess columns in the materialized tuples, so request
    1233             :      * a smaller tlist.  Otherwise, since Material doesn't project, tlist
    1234             :      * requirements pass through.
    1235             :      */
    1236         200 :     subplan = create_plan_recurse(root, best_path->subpath,
    1237             :                                   flags | CP_SMALL_TLIST);
    1238             : 
    1239         200 :     plan = make_material(subplan);
    1240             : 
    1241         200 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1242             : 
    1243         200 :     return plan;
    1244             : }
    1245             : 
    1246             : /*
    1247             :  * create_unique_plan
    1248             :  *    Create a Unique plan for 'best_path' and (recursively) plans
    1249             :  *    for its subpaths.
    1250             :  *
    1251             :  *    Returns a Plan node.
    1252             :  */
    1253             : static Plan *
    1254          28 : create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
    1255             : {
    1256             :     Plan       *plan;
    1257             :     Plan       *subplan;
    1258             :     List       *in_operators;
    1259             :     List       *uniq_exprs;
    1260             :     List       *newtlist;
    1261             :     int         nextresno;
    1262             :     bool        newitems;
    1263             :     int         numGroupCols;
    1264             :     AttrNumber *groupColIdx;
    1265             :     int         groupColPos;
    1266             :     ListCell   *l;
    1267             : 
    1268             :     /* Unique doesn't project, so tlist requirements pass through */
    1269          28 :     subplan = create_plan_recurse(root, best_path->subpath, flags);
    1270             : 
    1271             :     /* Done if we don't need to do any actual unique-ifying */
    1272          28 :     if (best_path->umethod == UNIQUE_PATH_NOOP)
    1273           0 :         return subplan;
    1274             : 
    1275             :     /*
    1276             :      * As constructed, the subplan has a "flat" tlist containing just the Vars
    1277             :      * needed here and at upper levels.  The values we are supposed to
    1278             :      * unique-ify may be expressions in these variables.  We have to add any
    1279             :      * such expressions to the subplan's tlist.
    1280             :      *
    1281             :      * The subplan may have a "physical" tlist if it is a simple scan plan. If
    1282             :      * we're going to sort, this should be reduced to the regular tlist, so
    1283             :      * that we don't sort more data than we need to.  For hashing, the tlist
    1284             :      * should be left as-is if we don't need to add any expressions; but if we
    1285             :      * do have to add expressions, then a projection step will be needed at
    1286             :      * runtime anyway, so we may as well remove unneeded items. Therefore
    1287             :      * newtlist starts from build_path_tlist() not just a copy of the
    1288             :      * subplan's tlist; and we don't install it into the subplan unless we are
    1289             :      * sorting or stuff has to be added.
    1290             :      */
    1291          28 :     in_operators = best_path->in_operators;
    1292          28 :     uniq_exprs = best_path->uniq_exprs;
    1293             : 
    1294             :     /* initialize modified subplan tlist as just the "required" vars */
    1295          28 :     newtlist = build_path_tlist(root, &best_path->path);
    1296          28 :     nextresno = list_length(newtlist) + 1;
    1297          28 :     newitems = false;
    1298             : 
    1299          59 :     foreach(l, uniq_exprs)
    1300             :     {
    1301          31 :         Expr       *uniqexpr = lfirst(l);
    1302             :         TargetEntry *tle;
    1303             : 
    1304          31 :         tle = tlist_member(uniqexpr, newtlist);
    1305          31 :         if (!tle)
    1306             :         {
    1307           5 :             tle = makeTargetEntry((Expr *) uniqexpr,
    1308             :                                   nextresno,
    1309             :                                   NULL,
    1310             :                                   false);
    1311           5 :             newtlist = lappend(newtlist, tle);
    1312           5 :             nextresno++;
    1313           5 :             newitems = true;
    1314             :         }
    1315             :     }
    1316             : 
    1317          28 :     if (newitems || best_path->umethod == UNIQUE_PATH_SORT)
    1318             :     {
    1319             :         /*
    1320             :          * If the top plan node can't do projections and its existing target
    1321             :          * list isn't already what we need, we need to add a Result node to
    1322             :          * help it along.
    1323             :          */
    1324           5 :         if (!is_projection_capable_plan(subplan) &&
    1325           0 :             !tlist_same_exprs(newtlist, subplan->targetlist))
    1326           0 :             subplan = inject_projection_plan(subplan, newtlist,
    1327           0 :                                              best_path->path.parallel_safe);
    1328             :         else
    1329           5 :             subplan->targetlist = newtlist;
    1330             :     }
    1331             : 
    1332             :     /*
    1333             :      * Build control information showing which subplan output columns are to
    1334             :      * be examined by the grouping step.  Unfortunately we can't merge this
    1335             :      * with the previous loop, since we didn't then know which version of the
    1336             :      * subplan tlist we'd end up using.
    1337             :      */
    1338          28 :     newtlist = subplan->targetlist;
    1339          28 :     numGroupCols = list_length(uniq_exprs);
    1340          28 :     groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));
    1341             : 
    1342          28 :     groupColPos = 0;
    1343          59 :     foreach(l, uniq_exprs)
    1344             :     {
    1345          31 :         Expr       *uniqexpr = lfirst(l);
    1346             :         TargetEntry *tle;
    1347             : 
    1348          31 :         tle = tlist_member(uniqexpr, newtlist);
    1349          31 :         if (!tle)               /* shouldn't happen */
    1350           0 :             elog(ERROR, "failed to find unique expression in subplan tlist");
    1351          31 :         groupColIdx[groupColPos++] = tle->resno;
    1352             :     }
    1353             : 
    1354          28 :     if (best_path->umethod == UNIQUE_PATH_HASH)
    1355             :     {
    1356             :         Oid        *groupOperators;
    1357             : 
    1358             :         /*
    1359             :          * Get the hashable equality operators for the Agg node to use.
    1360             :          * Normally these are the same as the IN clause operators, but if
    1361             :          * those are cross-type operators then the equality operators are the
    1362             :          * ones for the IN clause operators' RHS datatype.
    1363             :          */
    1364          28 :         groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid));
    1365          28 :         groupColPos = 0;
    1366          59 :         foreach(l, in_operators)
    1367             :         {
    1368          31 :             Oid         in_oper = lfirst_oid(l);
    1369             :             Oid         eq_oper;
    1370             : 
    1371          31 :             if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
    1372           0 :                 elog(ERROR, "could not find compatible hash operator for operator %u",
    1373             :                      in_oper);
    1374          31 :             groupOperators[groupColPos++] = eq_oper;
    1375             :         }
    1376             : 
    1377             :         /*
    1378             :          * Since the Agg node is going to project anyway, we can give it the
    1379             :          * minimum output tlist, without any stuff we might have added to the
    1380             :          * subplan tlist.
    1381             :          */
    1382          28 :         plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path),
    1383             :                                  NIL,
    1384             :                                  AGG_HASHED,
    1385             :                                  AGGSPLIT_SIMPLE,
    1386             :                                  numGroupCols,
    1387             :                                  groupColIdx,
    1388             :                                  groupOperators,
    1389             :                                  NIL,
    1390             :                                  NIL,
    1391             :                                  best_path->path.rows,
    1392             :                                  subplan);
    1393             :     }
    1394             :     else
    1395             :     {
    1396           0 :         List       *sortList = NIL;
    1397             :         Sort       *sort;
    1398             : 
    1399             :         /* Create an ORDER BY list to sort the input compatibly */
    1400           0 :         groupColPos = 0;
    1401           0 :         foreach(l, in_operators)
    1402             :         {
    1403           0 :             Oid         in_oper = lfirst_oid(l);
    1404             :             Oid         sortop;
    1405             :             Oid         eqop;
    1406             :             TargetEntry *tle;
    1407             :             SortGroupClause *sortcl;
    1408             : 
    1409           0 :             sortop = get_ordering_op_for_equality_op(in_oper, false);
    1410           0 :             if (!OidIsValid(sortop))    /* shouldn't happen */
    1411           0 :                 elog(ERROR, "could not find ordering operator for equality operator %u",
    1412             :                      in_oper);
    1413             : 
    1414             :             /*
    1415             :              * The Unique node will need equality operators.  Normally these
    1416             :              * are the same as the IN clause operators, but if those are
    1417             :              * cross-type operators then the equality operators are the ones
    1418             :              * for the IN clause operators' RHS datatype.
    1419             :              */
    1420           0 :             eqop = get_equality_op_for_ordering_op(sortop, NULL);
    1421           0 :             if (!OidIsValid(eqop))  /* shouldn't happen */
    1422           0 :                 elog(ERROR, "could not find equality operator for ordering operator %u",
    1423             :                      sortop);
    1424             : 
    1425           0 :             tle = get_tle_by_resno(subplan->targetlist,
    1426           0 :                                    groupColIdx[groupColPos]);
    1427           0 :             Assert(tle != NULL);
    1428             : 
    1429           0 :             sortcl = makeNode(SortGroupClause);
    1430           0 :             sortcl->tleSortGroupRef = assignSortGroupRef(tle,
    1431             :                                                          subplan->targetlist);
    1432           0 :             sortcl->eqop = eqop;
    1433           0 :             sortcl->sortop = sortop;
    1434           0 :             sortcl->nulls_first = false;
    1435           0 :             sortcl->hashable = false;    /* no need to make this accurate */
    1436           0 :             sortList = lappend(sortList, sortcl);
    1437           0 :             groupColPos++;
    1438             :         }
    1439           0 :         sort = make_sort_from_sortclauses(sortList, subplan);
    1440           0 :         label_sort_with_costsize(root, sort, -1.0);
    1441           0 :         plan = (Plan *) make_unique_from_sortclauses((Plan *) sort, sortList);
    1442             :     }
    1443             : 
    1444             :     /* Copy cost data from Path to Plan */
    1445          28 :     copy_generic_path_info(plan, &best_path->path);
    1446             : 
    1447          28 :     return plan;
    1448             : }
    1449             : 
    1450             : /*
    1451             :  * create_gather_plan
    1452             :  *
    1453             :  *    Create a Gather plan for 'best_path' and (recursively) plans
    1454             :  *    for its subpaths.
    1455             :  */
    1456             : static Gather *
    1457          23 : create_gather_plan(PlannerInfo *root, GatherPath *best_path)
    1458             : {
    1459             :     Gather     *gather_plan;
    1460             :     Plan       *subplan;
    1461             :     List       *tlist;
    1462             : 
    1463             :     /*
    1464             :      * Although the Gather node can project, we prefer to push down such work
    1465             :      * to its child node, so demand an exact tlist from the child.
    1466             :      */
    1467          23 :     subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
    1468             : 
    1469          23 :     tlist = build_path_tlist(root, &best_path->path);
    1470             : 
    1471          23 :     gather_plan = make_gather(tlist,
    1472             :                               NIL,
    1473             :                               best_path->num_workers,
    1474             :                               SS_assign_special_param(root),
    1475          23 :                               best_path->single_copy,
    1476             :                               subplan);
    1477             : 
    1478          23 :     copy_generic_path_info(&gather_plan->plan, &best_path->path);
    1479             : 
    1480             :     /* use parallel mode for parallel plans. */
    1481          23 :     root->glob->parallelModeNeeded = true;
    1482             : 
    1483          23 :     return gather_plan;
    1484             : }
    1485             : 
    1486             : /*
    1487             :  * create_gather_merge_plan
    1488             :  *
    1489             :  *    Create a Gather Merge plan for 'best_path' and (recursively)
    1490             :  *    plans for its subpaths.
    1491             :  */
    1492             : static GatherMerge *
    1493           8 : create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
    1494             : {
    1495             :     GatherMerge *gm_plan;
    1496             :     Plan       *subplan;
    1497           8 :     List       *pathkeys = best_path->path.pathkeys;
    1498           8 :     List       *tlist = build_path_tlist(root, &best_path->path);
    1499             : 
    1500             :     /* As with Gather, it's best to project away columns in the workers. */
    1501           8 :     subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
    1502             : 
    1503             :     /* Create a shell for a GatherMerge plan. */
    1504           8 :     gm_plan = makeNode(GatherMerge);
    1505           8 :     gm_plan->plan.targetlist = tlist;
    1506           8 :     gm_plan->num_workers = best_path->num_workers;
    1507           8 :     copy_generic_path_info(&gm_plan->plan, &best_path->path);
    1508             : 
    1509             :     /* Assign the rescan Param. */
    1510           8 :     gm_plan->rescan_param = SS_assign_special_param(root);
    1511             : 
    1512             :     /* Gather Merge is pointless with no pathkeys; use Gather instead. */
    1513           8 :     Assert(pathkeys != NIL);
    1514             : 
    1515             :     /* Compute sort column info, and adjust subplan's tlist as needed */
    1516          16 :     subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
    1517           8 :                                          best_path->subpath->parent->relids,
    1518           8 :                                          gm_plan->sortColIdx,
    1519             :                                          false,
    1520             :                                          &gm_plan->numCols,
    1521             :                                          &gm_plan->sortColIdx,
    1522             :                                          &gm_plan->sortOperators,
    1523             :                                          &gm_plan->collations,
    1524             :                                          &gm_plan->nullsFirst);
    1525             : 
    1526             : 
    1527             :     /* Now, insert a Sort node if subplan isn't sufficiently ordered */
    1528           8 :     if (!pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys))
    1529           0 :         subplan = (Plan *) make_sort(subplan, gm_plan->numCols,
    1530             :                                      gm_plan->sortColIdx,
    1531             :                                      gm_plan->sortOperators,
    1532             :                                      gm_plan->collations,
    1533             :                                      gm_plan->nullsFirst);
    1534             : 
    1535             :     /* Now insert the subplan under GatherMerge. */
    1536           8 :     gm_plan->plan.lefttree = subplan;
    1537             : 
    1538             :     /* use parallel mode for parallel plans. */
    1539           8 :     root->glob->parallelModeNeeded = true;
    1540             : 
    1541           8 :     return gm_plan;
    1542             : }
    1543             : 
    1544             : /*
    1545             :  * create_projection_plan
    1546             :  *
    1547             :  *    Create a plan tree to do a projection step and (recursively) plans
    1548             :  *    for its subpaths.  We may need a Result node for the projection,
    1549             :  *    but sometimes we can just let the subplan do the work.
    1550             :  */
    1551             : static Plan *
    1552         559 : create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
    1553             : {
    1554             :     Plan       *plan;
    1555             :     Plan       *subplan;
    1556             :     List       *tlist;
    1557             : 
    1558             :     /* Since we intend to project, we don't need to constrain child tlist */
    1559         559 :     subplan = create_plan_recurse(root, best_path->subpath, 0);
    1560             : 
    1561         559 :     tlist = build_path_tlist(root, &best_path->path);
    1562             : 
    1563             :     /*
    1564             :      * We might not really need a Result node here, either because the subplan
    1565             :      * can project or because it's returning the right list of expressions
    1566             :      * anyway.  Usually create_projection_path will have detected that and set
    1567             :      * dummypp if we don't need a Result; but its decision can't be final,
    1568             :      * because some createplan.c routines change the tlists of their nodes.
    1569             :      * (An example is that create_merge_append_plan might add resjunk sort
    1570             :      * columns to a MergeAppend.)  So we have to recheck here.  If we do
    1571             :      * arrive at a different answer than create_projection_path did, we'll
    1572             :      * have made slightly wrong cost estimates; but label the plan with the
    1573             :      * cost estimates we actually used, not "corrected" ones.  (XXX this could
    1574             :      * be cleaned up if we moved more of the sortcolumn setup logic into Path
    1575             :      * creation, but that would add expense to creating Paths we might end up
    1576             :      * not using.)
    1577             :      */
    1578        1093 :     if (is_projection_capable_path(best_path->subpath) ||
    1579         534 :         tlist_same_exprs(tlist, subplan->targetlist))
    1580             :     {
    1581             :         /* Don't need a separate Result, just assign tlist to subplan */
    1582         453 :         plan = subplan;
    1583         453 :         plan->targetlist = tlist;
    1584             : 
    1585             :         /* Label plan with the estimated costs we actually used */
    1586         453 :         plan->startup_cost = best_path->path.startup_cost;
    1587         453 :         plan->total_cost = best_path->path.total_cost;
    1588         453 :         plan->plan_rows = best_path->path.rows;
    1589         453 :         plan->plan_width = best_path->path.pathtarget->width;
    1590         453 :         plan->parallel_safe = best_path->path.parallel_safe;
    1591             :         /* ... but don't change subplan's parallel_aware flag */
    1592             :     }
    1593             :     else
    1594             :     {
    1595             :         /* We need a Result node */
    1596         106 :         plan = (Plan *) make_result(tlist, NULL, subplan);
    1597             : 
    1598         106 :         copy_generic_path_info(plan, (Path *) best_path);
    1599             :     }
    1600             : 
    1601         559 :     return plan;
    1602             : }
    1603             : 
    1604             : /*
    1605             :  * inject_projection_plan
    1606             :  *    Insert a Result node to do a projection step.
    1607             :  *
    1608             :  * This is used in a few places where we decide on-the-fly that we need a
    1609             :  * projection step as part of the tree generated for some Path node.
    1610             :  * We should try to get rid of this in favor of doing it more honestly.
    1611             :  *
    1612             :  * One reason it's ugly is we have to be told the right parallel_safe marking
    1613             :  * to apply (since the tlist might be unsafe even if the child plan is safe).
    1614             :  */
    1615             : static Plan *
    1616           0 : inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
    1617             : {
    1618             :     Plan       *plan;
    1619             : 
    1620           0 :     plan = (Plan *) make_result(tlist, NULL, subplan);
    1621             : 
    1622             :     /*
    1623             :      * In principle, we should charge tlist eval cost plus cpu_per_tuple per
    1624             :      * row for the Result node.  But the former has probably been factored in
    1625             :      * already and the latter was not accounted for during Path construction,
    1626             :      * so being formally correct might just make the EXPLAIN output look less
    1627             :      * consistent not more so.  Hence, just copy the subplan's cost.
    1628             :      */
    1629           0 :     copy_plan_costsize(plan, subplan);
    1630           0 :     plan->parallel_safe = parallel_safe;
    1631             : 
    1632           0 :     return plan;
    1633             : }
    1634             : 
    1635             : /*
    1636             :  * create_sort_plan
    1637             :  *
    1638             :  *    Create a Sort plan for 'best_path' and (recursively) plans
    1639             :  *    for its subpaths.
    1640             :  */
    1641             : static Sort *
    1642        2516 : create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
    1643             : {
    1644             :     Sort       *plan;
    1645             :     Plan       *subplan;
    1646             : 
    1647             :     /*
    1648             :      * We don't want any excess columns in the sorted tuples, so request a
    1649             :      * smaller tlist.  Otherwise, since Sort doesn't project, tlist
    1650             :      * requirements pass through.
    1651             :      */
    1652        2516 :     subplan = create_plan_recurse(root, best_path->subpath,
    1653             :                                   flags | CP_SMALL_TLIST);
    1654             : 
    1655        2516 :     plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys);
    1656             : 
    1657        2516 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1658             : 
    1659        2516 :     return plan;
    1660             : }
    1661             : 
    1662             : /*
    1663             :  * create_group_plan
    1664             :  *
    1665             :  *    Create a Group plan for 'best_path' and (recursively) plans
    1666             :  *    for its subpaths.
    1667             :  */
    1668             : static Group *
    1669          11 : create_group_plan(PlannerInfo *root, GroupPath *best_path)
    1670             : {
    1671             :     Group      *plan;
    1672             :     Plan       *subplan;
    1673             :     List       *tlist;
    1674             :     List       *quals;
    1675             : 
    1676             :     /*
    1677             :      * Group can project, so no need to be terribly picky about child tlist,
    1678             :      * but we do need grouping columns to be available
    1679             :      */
    1680          11 :     subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
    1681             : 
    1682          11 :     tlist = build_path_tlist(root, &best_path->path);
    1683             : 
    1684          11 :     quals = order_qual_clauses(root, best_path->qual);
    1685             : 
    1686          22 :     plan = make_group(tlist,
    1687             :                       quals,
    1688          11 :                       list_length(best_path->groupClause),
    1689             :                       extract_grouping_cols(best_path->groupClause,
    1690             :                                             subplan->targetlist),
    1691             :                       extract_grouping_ops(best_path->groupClause),
    1692             :                       subplan);
    1693             : 
    1694          11 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1695             : 
    1696          11 :     return plan;
    1697             : }
    1698             : 
    1699             : /*
    1700             :  * create_upper_unique_plan
    1701             :  *
    1702             :  *    Create a Unique plan for 'best_path' and (recursively) plans
    1703             :  *    for its subpaths.
    1704             :  */
    1705             : static Unique *
    1706          53 : create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
    1707             : {
    1708             :     Unique     *plan;
    1709             :     Plan       *subplan;
    1710             : 
    1711             :     /*
    1712             :      * Unique doesn't project, so tlist requirements pass through; moreover we
    1713             :      * need grouping columns to be labeled.
    1714             :      */
    1715          53 :     subplan = create_plan_recurse(root, best_path->subpath,
    1716             :                                   flags | CP_LABEL_TLIST);
    1717             : 
    1718          53 :     plan = make_unique_from_pathkeys(subplan,
    1719             :                                      best_path->path.pathkeys,
    1720             :                                      best_path->numkeys);
    1721             : 
    1722          53 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1723             : 
    1724          53 :     return plan;
    1725             : }
    1726             : 
    1727             : /*
    1728             :  * create_agg_plan
    1729             :  *
    1730             :  *    Create an Agg plan for 'best_path' and (recursively) plans
    1731             :  *    for its subpaths.
    1732             :  */
    1733             : static Agg *
    1734        2305 : create_agg_plan(PlannerInfo *root, AggPath *best_path)
    1735             : {
    1736             :     Agg        *plan;
    1737             :     Plan       *subplan;
    1738             :     List       *tlist;
    1739             :     List       *quals;
    1740             : 
    1741             :     /*
    1742             :      * Agg can project, so no need to be terribly picky about child tlist, but
    1743             :      * we do need grouping columns to be available
    1744             :      */
    1745        2305 :     subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
    1746             : 
    1747        2305 :     tlist = build_path_tlist(root, &best_path->path);
    1748             : 
    1749        2305 :     quals = order_qual_clauses(root, best_path->qual);
    1750             : 
    1751        4610 :     plan = make_agg(tlist, quals,
    1752             :                     best_path->aggstrategy,
    1753             :                     best_path->aggsplit,
    1754        2305 :                     list_length(best_path->groupClause),
    1755             :                     extract_grouping_cols(best_path->groupClause,
    1756             :                                           subplan->targetlist),
    1757             :                     extract_grouping_ops(best_path->groupClause),
    1758             :                     NIL,
    1759             :                     NIL,
    1760             :                     best_path->numGroups,
    1761             :                     subplan);
    1762             : 
    1763        2305 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    1764             : 
    1765        2305 :     return plan;
    1766             : }
    1767             : 
    1768             : /*
    1769             :  * Given a groupclause for a collection of grouping sets, produce the
    1770             :  * corresponding groupColIdx.
    1771             :  *
    1772             :  * root->grouping_map maps the tleSortGroupRef to the actual column position in
    1773             :  * the input tuple. So we get the ref from the entries in the groupclause and
    1774             :  * look them up there.
    1775             :  */
    1776             : static AttrNumber *
    1777         170 : remap_groupColIdx(PlannerInfo *root, List *groupClause)
    1778             : {
    1779         170 :     AttrNumber *grouping_map = root->grouping_map;
    1780             :     AttrNumber *new_grpColIdx;
    1781             :     ListCell   *lc;
    1782             :     int         i;
    1783             : 
    1784         170 :     Assert(grouping_map);
    1785             : 
    1786         170 :     new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
    1787             : 
    1788         170 :     i = 0;
    1789         405 :     foreach(lc, groupClause)
    1790             :     {
    1791         235 :         SortGroupClause *clause = lfirst(lc);
    1792             : 
    1793         235 :         new_grpColIdx[i++] = grouping_map[clause->tleSortGroupRef];
    1794             :     }
    1795             : 
    1796         170 :     return new_grpColIdx;
    1797             : }
    1798             : 
    1799             : /*
    1800             :  * create_groupingsets_plan
    1801             :  *    Create a plan for 'best_path' and (recursively) plans
    1802             :  *    for its subpaths.
    1803             :  *
    1804             :  *    What we emit is an Agg plan with some vestigial Agg and Sort nodes
    1805             :  *    hanging off the side.  The top Agg implements the last grouping set
    1806             :  *    specified in the GroupingSetsPath, and any additional grouping sets
    1807             :  *    each give rise to a subsidiary Agg and Sort node in the top Agg's
    1808             :  *    "chain" list.  These nodes don't participate in the plan directly,
    1809             :  *    but they are a convenient way to represent the required data for
    1810             :  *    the extra steps.
    1811             :  *
    1812             :  *    Returns a Plan node.
    1813             :  */
    1814             : static Plan *
    1815          88 : create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
    1816             : {
    1817             :     Agg        *plan;
    1818             :     Plan       *subplan;
    1819          88 :     List       *rollups = best_path->rollups;
    1820             :     AttrNumber *grouping_map;
    1821             :     int         maxref;
    1822             :     List       *chain;
    1823             :     ListCell   *lc;
    1824             : 
    1825             :     /* Shouldn't get here without grouping sets */
    1826          88 :     Assert(root->parse->groupingSets);
    1827          88 :     Assert(rollups != NIL);
    1828             : 
    1829             :     /*
    1830             :      * Agg can project, so no need to be terribly picky about child tlist, but
    1831             :      * we do need grouping columns to be available
    1832             :      */
    1833          88 :     subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
    1834             : 
    1835             :     /*
    1836             :      * Compute the mapping from tleSortGroupRef to column index in the child's
    1837             :      * tlist.  First, identify max SortGroupRef in groupClause, for array
    1838             :      * sizing.
    1839             :      */
    1840          88 :     maxref = 0;
    1841         277 :     foreach(lc, root->parse->groupClause)
    1842             :     {
    1843         189 :         SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
    1844             : 
    1845         189 :         if (gc->tleSortGroupRef > maxref)
    1846         187 :             maxref = gc->tleSortGroupRef;
    1847             :     }
    1848             : 
    1849          88 :     grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
    1850             : 
    1851             :     /* Now look up the column numbers in the child's tlist */
    1852         277 :     foreach(lc, root->parse->groupClause)
    1853             :     {
    1854         189 :         SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
    1855         189 :         TargetEntry *tle = get_sortgroupclause_tle(gc, subplan->targetlist);
    1856             : 
    1857         189 :         grouping_map[gc->tleSortGroupRef] = tle->resno;
    1858             :     }
    1859             : 
    1860             :     /*
    1861             :      * During setrefs.c, we'll need the grouping_map to fix up the cols lists
    1862             :      * in GroupingFunc nodes.  Save it for setrefs.c to use.
    1863             :      *
    1864             :      * This doesn't work if we're in an inheritance subtree (see notes in
    1865             :      * create_modifytable_plan).  Fortunately we can't be because there would
    1866             :      * never be grouping in an UPDATE/DELETE; but let's Assert that.
    1867             :      */
    1868          88 :     Assert(!root->hasInheritedTarget);
    1869          88 :     Assert(root->grouping_map == NULL);
    1870          88 :     root->grouping_map = grouping_map;
    1871             : 
    1872             :     /*
    1873             :      * Generate the side nodes that describe the other sort and group
    1874             :      * operations besides the top one.  Note that we don't worry about putting
    1875             :      * accurate cost estimates in the side nodes; only the topmost Agg node's
    1876             :      * costs will be shown by EXPLAIN.
    1877             :      */
    1878          88 :     chain = NIL;
    1879          88 :     if (list_length(rollups) > 1)
    1880             :     {
    1881          47 :         ListCell   *lc2 = lnext(list_head(rollups));
    1882          47 :         bool        is_first_sort = ((RollupData *) linitial(rollups))->is_hashed;
    1883             : 
    1884         129 :         for_each_cell(lc, lc2)
    1885             :         {
    1886          82 :             RollupData *rollup = lfirst(lc);
    1887             :             AttrNumber *new_grpColIdx;
    1888          82 :             Plan       *sort_plan = NULL;
    1889             :             Plan       *agg_plan;
    1890             :             AggStrategy strat;
    1891             : 
    1892          82 :             new_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
    1893             : 
    1894          82 :             if (!rollup->is_hashed && !is_first_sort)
    1895             :             {
    1896          24 :                 sort_plan = (Plan *)
    1897          24 :                     make_sort_from_groupcols(rollup->groupClause,
    1898             :                                              new_grpColIdx,
    1899             :                                              subplan);
    1900             :             }
    1901             : 
    1902          82 :             if (!rollup->is_hashed)
    1903          42 :                 is_first_sort = false;
    1904             : 
    1905          82 :             if (rollup->is_hashed)
    1906          40 :                 strat = AGG_HASHED;
    1907          42 :             else if (list_length(linitial(rollup->gsets)) == 0)
    1908          11 :                 strat = AGG_PLAIN;
    1909             :             else
    1910          31 :                 strat = AGG_SORTED;
    1911             : 
    1912         164 :             agg_plan = (Plan *) make_agg(NIL,
    1913             :                                          NIL,
    1914             :                                          strat,
    1915             :                                          AGGSPLIT_SIMPLE,
    1916          82 :                                          list_length((List *) linitial(rollup->gsets)),
    1917             :                                          new_grpColIdx,
    1918             :                                          extract_grouping_ops(rollup->groupClause),
    1919             :                                          rollup->gsets,
    1920             :                                          NIL,
    1921             :                                          rollup->numGroups,
    1922             :                                          sort_plan);
    1923             : 
    1924             :             /*
    1925             :              * Remove stuff we don't need to avoid bloating debug output.
    1926             :              */
    1927          82 :             if (sort_plan)
    1928             :             {
    1929          24 :                 sort_plan->targetlist = NIL;
    1930          24 :                 sort_plan->lefttree = NULL;
    1931             :             }
    1932             : 
    1933          82 :             chain = lappend(chain, agg_plan);
    1934             :         }
    1935             :     }
    1936             : 
    1937             :     /*
    1938             :      * Now make the real Agg node
    1939             :      */
    1940             :     {
    1941          88 :         RollupData *rollup = linitial(rollups);
    1942             :         AttrNumber *top_grpColIdx;
    1943             :         int         numGroupCols;
    1944             : 
    1945          88 :         top_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
    1946             : 
    1947          88 :         numGroupCols = list_length((List *) linitial(rollup->gsets));
    1948             : 
    1949          88 :         plan = make_agg(build_path_tlist(root, &best_path->path),
    1950             :                         best_path->qual,
    1951             :                         best_path->aggstrategy,
    1952             :                         AGGSPLIT_SIMPLE,
    1953             :                         numGroupCols,
    1954             :                         top_grpColIdx,
    1955             :                         extract_grouping_ops(rollup->groupClause),
    1956             :                         rollup->gsets,
    1957             :                         chain,
    1958             :                         rollup->numGroups,
    1959             :                         subplan);
    1960             : 
    1961             :         /* Copy cost data from Path to Plan */
    1962          88 :         copy_generic_path_info(&plan->plan, &best_path->path);
    1963             :     }
    1964             : 
    1965          88 :     return (Plan *) plan;
    1966             : }
    1967             : 
    1968             : /*
    1969             :  * create_minmaxagg_plan
    1970             :  *
    1971             :  *    Create a Result plan for 'best_path' and (recursively) plans
    1972             :  *    for its subpaths.
    1973             :  */
    1974             : static Result *
    1975          73 : create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
    1976             : {
    1977             :     Result     *plan;
    1978             :     List       *tlist;
    1979             :     ListCell   *lc;
    1980             : 
    1981             :     /* Prepare an InitPlan for each aggregate's subquery. */
    1982         152 :     foreach(lc, best_path->mmaggregates)
    1983             :     {
    1984          79 :         MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
    1985          79 :         PlannerInfo *subroot = mminfo->subroot;
    1986          79 :         Query      *subparse = subroot->parse;
    1987             :         Plan       *plan;
    1988             : 
    1989             :         /*
    1990             :          * Generate the plan for the subquery. We already have a Path, but we
    1991             :          * have to convert it to a Plan and attach a LIMIT node above it.
    1992             :          * Since we are entering a different planner context (subroot),
    1993             :          * recurse to create_plan not create_plan_recurse.
    1994             :          */
    1995          79 :         plan = create_plan(subroot, mminfo->path);
    1996             : 
    1997          79 :         plan = (Plan *) make_limit(plan,
    1998             :                                    subparse->limitOffset,
    1999             :                                    subparse->limitCount);
    2000             : 
    2001             :         /* Must apply correct cost/width data to Limit node */
    2002          79 :         plan->startup_cost = mminfo->path->startup_cost;
    2003          79 :         plan->total_cost = mminfo->pathcost;
    2004          79 :         plan->plan_rows = 1;
    2005          79 :         plan->plan_width = mminfo->path->pathtarget->width;
    2006          79 :         plan->parallel_aware = false;
    2007          79 :         plan->parallel_safe = mminfo->path->parallel_safe;
    2008             : 
    2009             :         /* Convert the plan into an InitPlan in the outer query. */
    2010          79 :         SS_make_initplan_from_plan(root, subroot, plan, mminfo->param);
    2011             :     }
    2012             : 
    2013             :     /* Generate the output plan --- basically just a Result */
    2014          73 :     tlist = build_path_tlist(root, &best_path->path);
    2015             : 
    2016          73 :     plan = make_result(tlist, (Node *) best_path->quals, NULL);
    2017             : 
    2018          73 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2019             : 
    2020             :     /*
    2021             :      * During setrefs.c, we'll need to replace references to the Agg nodes
    2022             :      * with InitPlan output params.  (We can't just do that locally in the
    2023             :      * MinMaxAgg node, because path nodes above here may have Agg references
    2024             :      * as well.)  Save the mmaggregates list to tell setrefs.c to do that.
    2025             :      *
    2026             :      * This doesn't work if we're in an inheritance subtree (see notes in
    2027             :      * create_modifytable_plan).  Fortunately we can't be because there would
    2028             :      * never be aggregates in an UPDATE/DELETE; but let's Assert that.
    2029             :      */
    2030          73 :     Assert(!root->hasInheritedTarget);
    2031          73 :     Assert(root->minmax_aggs == NIL);
    2032          73 :     root->minmax_aggs = best_path->mmaggregates;
    2033             : 
    2034          73 :     return plan;
    2035             : }
    2036             : 
    2037             : /*
    2038             :  * create_windowagg_plan
    2039             :  *
    2040             :  *    Create a WindowAgg plan for 'best_path' and (recursively) plans
    2041             :  *    for its subpaths.
    2042             :  */
    2043             : static WindowAgg *
    2044         140 : create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
    2045             : {
    2046             :     WindowAgg  *plan;
    2047         140 :     WindowClause *wc = best_path->winclause;
    2048             :     Plan       *subplan;
    2049             :     List       *tlist;
    2050             :     int         numsortkeys;
    2051             :     AttrNumber *sortColIdx;
    2052             :     Oid        *sortOperators;
    2053             :     Oid        *collations;
    2054             :     bool       *nullsFirst;
    2055             :     int         partNumCols;
    2056             :     AttrNumber *partColIdx;
    2057             :     Oid        *partOperators;
    2058             :     int         ordNumCols;
    2059             :     AttrNumber *ordColIdx;
    2060             :     Oid        *ordOperators;
    2061             : 
    2062             :     /*
    2063             :      * WindowAgg can project, so no need to be terribly picky about child
    2064             :      * tlist, but we do need grouping columns to be available
    2065             :      */
    2066         140 :     subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
    2067             : 
    2068         140 :     tlist = build_path_tlist(root, &best_path->path);
    2069             : 
    2070             :     /*
    2071             :      * We shouldn't need to actually sort, but it's convenient to use
    2072             :      * prepare_sort_from_pathkeys to identify the input's sort columns.
    2073             :      */
    2074         140 :     subplan = prepare_sort_from_pathkeys(subplan,
    2075             :                                          best_path->winpathkeys,
    2076             :                                          NULL,
    2077             :                                          NULL,
    2078             :                                          false,
    2079             :                                          &numsortkeys,
    2080             :                                          &sortColIdx,
    2081             :                                          &sortOperators,
    2082             :                                          &collations,
    2083             :                                          &nullsFirst);
    2084             : 
    2085             :     /* Now deconstruct that into partition and ordering portions */
    2086         140 :     get_column_info_for_window(root,
    2087             :                                wc,
    2088             :                                subplan->targetlist,
    2089             :                                numsortkeys,
    2090             :                                sortColIdx,
    2091             :                                &partNumCols,
    2092             :                                &partColIdx,
    2093             :                                &partOperators,
    2094             :                                &ordNumCols,
    2095             :                                &ordColIdx,
    2096             :                                &ordOperators);
    2097             : 
    2098             :     /* And finally we can make the WindowAgg node */
    2099         140 :     plan = make_windowagg(tlist,
    2100             :                           wc->winref,
    2101             :                           partNumCols,
    2102             :                           partColIdx,
    2103             :                           partOperators,
    2104             :                           ordNumCols,
    2105             :                           ordColIdx,
    2106             :                           ordOperators,
    2107             :                           wc->frameOptions,
    2108             :                           wc->startOffset,
    2109             :                           wc->endOffset,
    2110             :                           subplan);
    2111             : 
    2112         140 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2113             : 
    2114         140 :     return plan;
    2115             : }
    2116             : 
    2117             : /*
    2118             :  * get_column_info_for_window
    2119             :  *      Get the partitioning/ordering column numbers and equality operators
    2120             :  *      for a WindowAgg node.
    2121             :  *
    2122             :  * This depends on the behavior of planner.c's make_pathkeys_for_window!
    2123             :  *
    2124             :  * We are given the target WindowClause and an array of the input column
    2125             :  * numbers associated with the resulting pathkeys.  In the easy case, there
    2126             :  * are the same number of pathkey columns as partitioning + ordering columns
    2127             :  * and we just have to copy some data around.  However, it's possible that
    2128             :  * some of the original partitioning + ordering columns were eliminated as
    2129             :  * redundant during the transformation to pathkeys.  (This can happen even
    2130             :  * though the parser gets rid of obvious duplicates.  A typical scenario is a
    2131             :  * window specification "PARTITION BY x ORDER BY y" coupled with a clause
    2132             :  * "WHERE x = y" that causes the two sort columns to be recognized as
    2133             :  * redundant.)  In that unusual case, we have to work a lot harder to
    2134             :  * determine which keys are significant.
    2135             :  *
    2136             :  * The method used here is a bit brute-force: add the sort columns to a list
    2137             :  * one at a time and note when the resulting pathkey list gets longer.  But
    2138             :  * it's a sufficiently uncommon case that a faster way doesn't seem worth
    2139             :  * the amount of code refactoring that'd be needed.
    2140             :  */
    2141             : static void
    2142         140 : get_column_info_for_window(PlannerInfo *root, WindowClause *wc, List *tlist,
    2143             :                            int numSortCols, AttrNumber *sortColIdx,
    2144             :                            int *partNumCols,
    2145             :                            AttrNumber **partColIdx,
    2146             :                            Oid **partOperators,
    2147             :                            int *ordNumCols,
    2148             :                            AttrNumber **ordColIdx,
    2149             :                            Oid **ordOperators)
    2150             : {
    2151         140 :     int         numPart = list_length(wc->partitionClause);
    2152         140 :     int         numOrder = list_length(wc->orderClause);
    2153             : 
    2154         140 :     if (numSortCols == numPart + numOrder)
    2155             :     {
    2156             :         /* easy case */
    2157         136 :         *partNumCols = numPart;
    2158         136 :         *partColIdx = sortColIdx;
    2159         136 :         *partOperators = extract_grouping_ops(wc->partitionClause);
    2160         136 :         *ordNumCols = numOrder;
    2161         136 :         *ordColIdx = sortColIdx + numPart;
    2162         136 :         *ordOperators = extract_grouping_ops(wc->orderClause);
    2163             :     }
    2164             :     else
    2165             :     {
    2166             :         List       *sortclauses;
    2167             :         List       *pathkeys;
    2168             :         int         scidx;
    2169             :         ListCell   *lc;
    2170             : 
    2171             :         /* first, allocate what's certainly enough space for the arrays */
    2172           4 :         *partNumCols = 0;
    2173           4 :         *partColIdx = (AttrNumber *) palloc(numPart * sizeof(AttrNumber));
    2174           4 :         *partOperators = (Oid *) palloc(numPart * sizeof(Oid));
    2175           4 :         *ordNumCols = 0;
    2176           4 :         *ordColIdx = (AttrNumber *) palloc(numOrder * sizeof(AttrNumber));
    2177           4 :         *ordOperators = (Oid *) palloc(numOrder * sizeof(Oid));
    2178           4 :         sortclauses = NIL;
    2179           4 :         pathkeys = NIL;
    2180           4 :         scidx = 0;
    2181           8 :         foreach(lc, wc->partitionClause)
    2182             :         {
    2183           4 :             SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
    2184             :             List       *new_pathkeys;
    2185             : 
    2186           4 :             sortclauses = lappend(sortclauses, sgc);
    2187           4 :             new_pathkeys = make_pathkeys_for_sortclauses(root,
    2188             :                                                          sortclauses,
    2189             :                                                          tlist);
    2190           4 :             if (list_length(new_pathkeys) > list_length(pathkeys))
    2191             :             {
    2192             :                 /* this sort clause is actually significant */
    2193           2 :                 (*partColIdx)[*partNumCols] = sortColIdx[scidx++];
    2194           2 :                 (*partOperators)[*partNumCols] = sgc->eqop;
    2195           2 :                 (*partNumCols)++;
    2196           2 :                 pathkeys = new_pathkeys;
    2197             :             }
    2198             :         }
    2199           6 :         foreach(lc, wc->orderClause)
    2200             :         {
    2201           2 :             SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
    2202             :             List       *new_pathkeys;
    2203             : 
    2204           2 :             sortclauses = lappend(sortclauses, sgc);
    2205           2 :             new_pathkeys = make_pathkeys_for_sortclauses(root,
    2206             :                                                          sortclauses,
    2207             :                                                          tlist);
    2208           2 :             if (list_length(new_pathkeys) > list_length(pathkeys))
    2209             :             {
    2210             :                 /* this sort clause is actually significant */
    2211           0 :                 (*ordColIdx)[*ordNumCols] = sortColIdx[scidx++];
    2212           0 :                 (*ordOperators)[*ordNumCols] = sgc->eqop;
    2213           0 :                 (*ordNumCols)++;
    2214           0 :                 pathkeys = new_pathkeys;
    2215             :             }
    2216             :         }
    2217             :         /* complain if we didn't eat exactly the right number of sort cols */
    2218           4 :         if (scidx != numSortCols)
    2219           0 :             elog(ERROR, "failed to deconstruct sort operators into partitioning/ordering operators");
    2220             :     }
    2221         140 : }
    2222             : 
    2223             : /*
    2224             :  * create_setop_plan
    2225             :  *
    2226             :  *    Create a SetOp plan for 'best_path' and (recursively) plans
    2227             :  *    for its subpaths.
    2228             :  */
    2229             : static SetOp *
    2230          37 : create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
    2231             : {
    2232             :     SetOp      *plan;
    2233             :     Plan       *subplan;
    2234             :     long        numGroups;
    2235             : 
    2236             :     /*
    2237             :      * SetOp doesn't project, so tlist requirements pass through; moreover we
    2238             :      * need grouping columns to be labeled.
    2239             :      */
    2240          37 :     subplan = create_plan_recurse(root, best_path->subpath,
    2241             :                                   flags | CP_LABEL_TLIST);
    2242             : 
    2243             :     /* Convert numGroups to long int --- but 'ware overflow! */
    2244          37 :     numGroups = (long) Min(best_path->numGroups, (double) LONG_MAX);
    2245             : 
    2246          74 :     plan = make_setop(best_path->cmd,
    2247             :                       best_path->strategy,
    2248             :                       subplan,
    2249             :                       best_path->distinctList,
    2250          37 :                       best_path->flagColIdx,
    2251             :                       best_path->firstFlag,
    2252             :                       numGroups);
    2253             : 
    2254          37 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2255             : 
    2256          37 :     return plan;
    2257             : }
    2258             : 
    2259             : /*
    2260             :  * create_recursiveunion_plan
    2261             :  *
    2262             :  *    Create a RecursiveUnion plan for 'best_path' and (recursively) plans
    2263             :  *    for its subpaths.
    2264             :  */
    2265             : static RecursiveUnion *
    2266          40 : create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
    2267             : {
    2268             :     RecursiveUnion *plan;
    2269             :     Plan       *leftplan;
    2270             :     Plan       *rightplan;
    2271             :     List       *tlist;
    2272             :     long        numGroups;
    2273             : 
    2274             :     /* Need both children to produce same tlist, so force it */
    2275          40 :     leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
    2276          40 :     rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
    2277             : 
    2278          40 :     tlist = build_path_tlist(root, &best_path->path);
    2279             : 
    2280             :     /* Convert numGroups to long int --- but 'ware overflow! */
    2281          40 :     numGroups = (long) Min(best_path->numGroups, (double) LONG_MAX);
    2282             : 
    2283          40 :     plan = make_recursive_union(tlist,
    2284             :                                 leftplan,
    2285             :                                 rightplan,
    2286             :                                 best_path->wtParam,
    2287             :                                 best_path->distinctList,
    2288             :                                 numGroups);
    2289             : 
    2290          40 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2291             : 
    2292          40 :     return plan;
    2293             : }
    2294             : 
    2295             : /*
    2296             :  * create_lockrows_plan
    2297             :  *
    2298             :  *    Create a LockRows plan for 'best_path' and (recursively) plans
    2299             :  *    for its subpaths.
    2300             :  */
    2301             : static LockRows *
    2302         328 : create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path,
    2303             :                      int flags)
    2304             : {
    2305             :     LockRows   *plan;
    2306             :     Plan       *subplan;
    2307             : 
    2308             :     /* LockRows doesn't project, so tlist requirements pass through */
    2309         328 :     subplan = create_plan_recurse(root, best_path->subpath, flags);
    2310             : 
    2311         328 :     plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
    2312             : 
    2313         328 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2314             : 
    2315         328 :     return plan;
    2316             : }
    2317             : 
    2318             : /*
    2319             :  * create_modifytable_plan
    2320             :  *    Create a ModifyTable plan for 'best_path'.
    2321             :  *
    2322             :  *    Returns a Plan node.
    2323             :  */
    2324             : static ModifyTable *
    2325        4340 : create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
    2326             : {
    2327             :     ModifyTable *plan;
    2328        4340 :     List       *subplans = NIL;
    2329             :     ListCell   *subpaths,
    2330             :                *subroots;
    2331             : 
    2332             :     /* Build the plan for each input path */
    2333        8796 :     forboth(subpaths, best_path->subpaths,
    2334             :             subroots, best_path->subroots)
    2335             :     {
    2336        4456 :         Path       *subpath = (Path *) lfirst(subpaths);
    2337        4456 :         PlannerInfo *subroot = (PlannerInfo *) lfirst(subroots);
    2338             :         Plan       *subplan;
    2339             : 
    2340             :         /*
    2341             :          * In an inherited UPDATE/DELETE, reference the per-child modified
    2342             :          * subroot while creating Plans from Paths for the child rel.  This is
    2343             :          * a kluge, but otherwise it's too hard to ensure that Plan creation
    2344             :          * functions (particularly in FDWs) don't depend on the contents of
    2345             :          * "root" matching what they saw at Path creation time.  The main
    2346             :          * downside is that creation functions for Plans that might appear
    2347             :          * below a ModifyTable cannot expect to modify the contents of "root"
    2348             :          * and have it "stick" for subsequent processing such as setrefs.c.
    2349             :          * That's not great, but it seems better than the alternative.
    2350             :          */
    2351        4456 :         subplan = create_plan_recurse(subroot, subpath, CP_EXACT_TLIST);
    2352             : 
    2353             :         /* Transfer resname/resjunk labeling, too, to keep executor happy */
    2354        4456 :         apply_tlist_labeling(subplan->targetlist, subroot->processed_tlist);
    2355             : 
    2356        4456 :         subplans = lappend(subplans, subplan);
    2357             :     }
    2358             : 
    2359        8680 :     plan = make_modifytable(root,
    2360             :                             best_path->operation,
    2361        4340 :                             best_path->canSetTag,
    2362             :                             best_path->nominalRelation,
    2363             :                             best_path->partitioned_rels,
    2364             :                             best_path->resultRelations,
    2365             :                             subplans,
    2366             :                             best_path->withCheckOptionLists,
    2367             :                             best_path->returningLists,
    2368             :                             best_path->rowMarks,
    2369             :                             best_path->onconflict,
    2370             :                             best_path->epqParam);
    2371             : 
    2372        4314 :     copy_generic_path_info(&plan->plan, &best_path->path);
    2373             : 
    2374        4314 :     return plan;
    2375             : }
    2376             : 
    2377             : /*
    2378             :  * create_limit_plan
    2379             :  *
    2380             :  *    Create a Limit plan for 'best_path' and (recursively) plans
    2381             :  *    for its subpaths.
    2382             :  */
    2383             : static Limit *
    2384         181 : create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
    2385             : {
    2386             :     Limit      *plan;
    2387             :     Plan       *subplan;
    2388             : 
    2389             :     /* Limit doesn't project, so tlist requirements pass through */
    2390         181 :     subplan = create_plan_recurse(root, best_path->subpath, flags);
    2391             : 
    2392         181 :     plan = make_limit(subplan,
    2393             :                       best_path->limitOffset,
    2394             :                       best_path->limitCount);
    2395             : 
    2396         181 :     copy_generic_path_info(&plan->plan, (Path *) best_path);
    2397             : 
    2398         181 :     return plan;
    2399             : }
    2400             : 
    2401             : 
    2402             : /*****************************************************************************
    2403             :  *
    2404             :  *  BASE-RELATION SCAN METHODS
    2405             :  *
    2406             :  *****************************************************************************/
    2407             : 
    2408             : 
    2409             : /*
    2410             :  * create_seqscan_plan
    2411             :  *   Returns a seqscan plan for the base relation scanned by 'best_path'
    2412             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    2413             :  */
    2414             : static SeqScan *
    2415        9154 : create_seqscan_plan(PlannerInfo *root, Path *best_path,
    2416             :                     List *tlist, List *scan_clauses)
    2417             : {
    2418             :     SeqScan    *scan_plan;
    2419        9154 :     Index       scan_relid = best_path->parent->relid;
    2420             : 
    2421             :     /* it should be a base rel... */
    2422        9154 :     Assert(scan_relid > 0);
    2423        9154 :     Assert(best_path->parent->rtekind == RTE_RELATION);
    2424             : 
    2425             :     /* Sort clauses into best execution order */
    2426        9154 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    2427             : 
    2428             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    2429        9154 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    2430             : 
    2431             :     /* Replace any outer-relation variables with nestloop params */
    2432        9154 :     if (best_path->param_info)
    2433             :     {
    2434          33 :         scan_clauses = (List *)
    2435             :             replace_nestloop_params(root, (Node *) scan_clauses);
    2436             :     }
    2437             : 
    2438        9154 :     scan_plan = make_seqscan(tlist,
    2439             :                              scan_clauses,
    2440             :                              scan_relid);
    2441             : 
    2442        9154 :     copy_generic_path_info(&scan_plan->plan, best_path);
    2443             : 
    2444        9154 :     return scan_plan;
    2445             : }
    2446             : 
    2447             : /*
    2448             :  * create_samplescan_plan
    2449             :  *   Returns a samplescan plan for the base relation scanned by 'best_path'
    2450             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    2451             :  */
    2452             : static SampleScan *
    2453          36 : create_samplescan_plan(PlannerInfo *root, Path *best_path,
    2454             :                        List *tlist, List *scan_clauses)
    2455             : {
    2456             :     SampleScan *scan_plan;
    2457          36 :     Index       scan_relid = best_path->parent->relid;
    2458             :     RangeTblEntry *rte;
    2459             :     TableSampleClause *tsc;
    2460             : 
    2461             :     /* it should be a base rel with a tablesample clause... */
    2462          36 :     Assert(scan_relid > 0);
    2463          36 :     rte = planner_rt_fetch(scan_relid, root);
    2464          36 :     Assert(rte->rtekind == RTE_RELATION);
    2465          36 :     tsc = rte->tablesample;
    2466          36 :     Assert(tsc != NULL);
    2467             : 
    2468             :     /* Sort clauses into best execution order */
    2469          36 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    2470             : 
    2471             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    2472          36 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    2473             : 
    2474             :     /* Replace any outer-relation variables with nestloop params */
    2475          36 :     if (best_path->param_info)
    2476             :     {
    2477           3 :         scan_clauses = (List *)
    2478             :             replace_nestloop_params(root, (Node *) scan_clauses);
    2479           3 :         tsc = (TableSampleClause *)
    2480             :             replace_nestloop_params(root, (Node *) tsc);
    2481             :     }
    2482             : 
    2483          36 :     scan_plan = make_samplescan(tlist,
    2484             :                                 scan_clauses,
    2485             :                                 scan_relid,
    2486             :                                 tsc);
    2487             : 
    2488          36 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    2489             : 
    2490          36 :     return scan_plan;
    2491             : }
    2492             : 
    2493             : /*
    2494             :  * create_indexscan_plan
    2495             :  *    Returns an indexscan plan for the base relation scanned by 'best_path'
    2496             :  *    with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    2497             :  *
    2498             :  * We use this for both plain IndexScans and IndexOnlyScans, because the
    2499             :  * qual preprocessing work is the same for both.  Note that the caller tells
    2500             :  * us which to build --- we don't look at best_path->path.pathtype, because
    2501             :  * create_bitmap_subplan needs to be able to override the prior decision.
    2502             :  */
    2503             : static Scan *
    2504        6123 : create_indexscan_plan(PlannerInfo *root,
    2505             :                       IndexPath *best_path,
    2506             :                       List *tlist,
    2507             :                       List *scan_clauses,
    2508             :                       bool indexonly)
    2509             : {
    2510             :     Scan       *scan_plan;
    2511        6123 :     List       *indexquals = best_path->indexquals;
    2512        6123 :     List       *indexorderbys = best_path->indexorderbys;
    2513        6123 :     Index       baserelid = best_path->path.parent->relid;
    2514        6123 :     Oid         indexoid = best_path->indexinfo->indexoid;
    2515             :     List       *qpqual;
    2516             :     List       *stripped_indexquals;
    2517             :     List       *fixed_indexquals;
    2518             :     List       *fixed_indexorderbys;
    2519        6123 :     List       *indexorderbyops = NIL;
    2520             :     ListCell   *l;
    2521             : 
    2522             :     /* it should be a base rel... */
    2523        6123 :     Assert(baserelid > 0);
    2524        6123 :     Assert(best_path->path.parent->rtekind == RTE_RELATION);
    2525             : 
    2526             :     /*
    2527             :      * Build "stripped" indexquals structure (no RestrictInfos) to pass to
    2528             :      * executor as indexqualorig
    2529             :      */
    2530        6123 :     stripped_indexquals = get_actual_clauses(indexquals);
    2531             : 
    2532             :     /*
    2533             :      * The executor needs a copy with the indexkey on the left of each clause
    2534             :      * and with index Vars substituted for table ones.
    2535             :      */
    2536        6123 :     fixed_indexquals = fix_indexqual_references(root, best_path);
    2537             : 
    2538             :     /*
    2539             :      * Likewise fix up index attr references in the ORDER BY expressions.
    2540             :      */
    2541        6123 :     fixed_indexorderbys = fix_indexorderby_references(root, best_path);
    2542             : 
    2543             :     /*
    2544             :      * The qpqual list must contain all restrictions not automatically handled
    2545             :      * by the index, other than pseudoconstant clauses which will be handled
    2546             :      * by a separate gating plan node.  All the predicates in the indexquals
    2547             :      * will be checked (either by the index itself, or by nodeIndexscan.c),
    2548             :      * but if there are any "special" operators involved then they must be
    2549             :      * included in qpqual.  The upshot is that qpqual must contain
    2550             :      * scan_clauses minus whatever appears in indexquals.
    2551             :      *
    2552             :      * In normal cases simple pointer equality checks will be enough to spot
    2553             :      * duplicate RestrictInfos, so we try that first.
    2554             :      *
    2555             :      * Another common case is that a scan_clauses entry is generated from the
    2556             :      * same EquivalenceClass as some indexqual, and is therefore redundant
    2557             :      * with it, though not equal.  (This happens when indxpath.c prefers a
    2558             :      * different derived equality than what generate_join_implied_equalities
    2559             :      * picked for a parameterized scan's ppi_clauses.)
    2560             :      *
    2561             :      * In some situations (particularly with OR'd index conditions) we may
    2562             :      * have scan_clauses that are not equal to, but are logically implied by,
    2563             :      * the index quals; so we also try a predicate_implied_by() check to see
    2564             :      * if we can discard quals that way.  (predicate_implied_by assumes its
    2565             :      * first input contains only immutable functions, so we have to check
    2566             :      * that.)
    2567             :      *
    2568             :      * Note: if you change this bit of code you should also look at
    2569             :      * extract_nonindex_conditions() in costsize.c.
    2570             :      */
    2571        6123 :     qpqual = NIL;
    2572       13256 :     foreach(l, scan_clauses)
    2573             :     {
    2574        7133 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
    2575             : 
    2576        7133 :         if (rinfo->pseudoconstant)
    2577         115 :             continue;           /* we may drop pseudoconstants here */
    2578        7018 :         if (list_member_ptr(indexquals, rinfo))
    2579        4469 :             continue;           /* simple duplicate */
    2580        2549 :         if (is_redundant_derived_clause(rinfo, indexquals))
    2581         568 :             continue;           /* derived from same EquivalenceClass */
    2582        3671 :         if (!contain_mutable_functions((Node *) rinfo->clause) &&
    2583        1690 :             predicate_implied_by(list_make1(rinfo->clause), indexquals, false))
    2584          11 :             continue;           /* provably implied by indexquals */
    2585        1970 :         qpqual = lappend(qpqual, rinfo);
    2586             :     }
    2587             : 
    2588             :     /* Sort clauses into best execution order */
    2589        6123 :     qpqual = order_qual_clauses(root, qpqual);
    2590             : 
    2591             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    2592        6123 :     qpqual = extract_actual_clauses(qpqual, false);
    2593             : 
    2594             :     /*
    2595             :      * We have to replace any outer-relation variables with nestloop params in
    2596             :      * the indexqualorig, qpqual, and indexorderbyorig expressions.  A bit
    2597             :      * annoying to have to do this separately from the processing in
    2598             :      * fix_indexqual_references --- rethink this when generalizing the inner
    2599             :      * indexscan support.  But note we can't really do this earlier because
    2600             :      * it'd break the comparisons to predicates above ... (or would it?  Those
    2601             :      * wouldn't have outer refs)
    2602             :      */
    2603        6123 :     if (best_path->path.param_info)
    2604             :     {
    2605         876 :         stripped_indexquals = (List *)
    2606             :             replace_nestloop_params(root, (Node *) stripped_indexquals);
    2607         876 :         qpqual = (List *)
    2608             :             replace_nestloop_params(root, (Node *) qpqual);
    2609         876 :         indexorderbys = (List *)
    2610             :             replace_nestloop_params(root, (Node *) indexorderbys);
    2611             :     }
    2612             : 
    2613             :     /*
    2614             :      * If there are ORDER BY expressions, look up the sort operators for their
    2615             :      * result datatypes.
    2616             :      */
    2617        6123 :     if (indexorderbys)
    2618             :     {
    2619             :         ListCell   *pathkeyCell,
    2620             :                    *exprCell;
    2621             : 
    2622             :         /*
    2623             :          * PathKey contains OID of the btree opfamily we're sorting by, but
    2624             :          * that's not quite enough because we need the expression's datatype
    2625             :          * to look up the sort operator in the operator family.
    2626             :          */
    2627          18 :         Assert(list_length(best_path->path.pathkeys) == list_length(indexorderbys));
    2628          36 :         forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
    2629             :         {
    2630          18 :             PathKey    *pathkey = (PathKey *) lfirst(pathkeyCell);
    2631          18 :             Node       *expr = (Node *) lfirst(exprCell);
    2632          18 :             Oid         exprtype = exprType(expr);
    2633             :             Oid         sortop;
    2634             : 
    2635             :             /* Get sort operator from opfamily */
    2636          18 :             sortop = get_opfamily_member(pathkey->pk_opfamily,
    2637             :                                          exprtype,
    2638             :                                          exprtype,
    2639          18 :                                          pathkey->pk_strategy);
    2640          18 :             if (!OidIsValid(sortop))
    2641           0 :                 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
    2642             :                      pathkey->pk_strategy, exprtype, exprtype, pathkey->pk_opfamily);
    2643          18 :             indexorderbyops = lappend_oid(indexorderbyops, sortop);
    2644             :         }
    2645             :     }
    2646             : 
    2647             :     /* Finally ready to build the plan node */
    2648        6123 :     if (indexonly)
    2649        1318 :         scan_plan = (Scan *) make_indexonlyscan(tlist,
    2650             :                                                 qpqual,
    2651             :                                                 baserelid,
    2652             :                                                 indexoid,
    2653             :                                                 fixed_indexquals,
    2654             :                                                 fixed_indexorderbys,
    2655         659 :                                                 best_path->indexinfo->indextlist,
    2656             :                                                 best_path->indexscandir);
    2657             :     else
    2658        5464 :         scan_plan = (Scan *) make_indexscan(tlist,
    2659             :                                             qpqual,
    2660             :                                             baserelid,
    2661             :                                             indexoid,
    2662             :                                             fixed_indexquals,
    2663             :                                             stripped_indexquals,
    2664             :                                             fixed_indexorderbys,
    2665             :                                             indexorderbys,
    2666             :                                             indexorderbyops,
    2667             :                                             best_path->indexscandir);
    2668             : 
    2669        6123 :     copy_generic_path_info(&scan_plan->plan, &best_path->path);
    2670             : 
    2671        6123 :     return scan_plan;
    2672             : }
    2673             : 
    2674             : /*
    2675             :  * create_bitmap_scan_plan
    2676             :  *    Returns a bitmap scan plan for the base relation scanned by 'best_path'
    2677             :  *    with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    2678             :  */
    2679             : static BitmapHeapScan *
    2680        1587 : create_bitmap_scan_plan(PlannerInfo *root,
    2681             :                         BitmapHeapPath *best_path,
    2682             :                         List *tlist,
    2683             :                         List *scan_clauses)
    2684             : {
    2685        1587 :     Index       baserelid = best_path->path.parent->relid;
    2686             :     Plan       *bitmapqualplan;
    2687             :     List       *bitmapqualorig;
    2688             :     List       *indexquals;
    2689             :     List       *indexECs;
    2690             :     List       *qpqual;
    2691             :     ListCell   *l;
    2692             :     BitmapHeapScan *scan_plan;
    2693             : 
    2694             :     /* it should be a base rel... */
    2695        1587 :     Assert(baserelid > 0);
    2696        1587 :     Assert(best_path->path.parent->rtekind == RTE_RELATION);
    2697             : 
    2698             :     /* Process the bitmapqual tree into a Plan tree and qual lists */
    2699        1587 :     bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
    2700             :                                            &bitmapqualorig, &indexquals,
    2701             :                                            &indexECs);
    2702             : 
    2703        1587 :     if (best_path->path.parallel_aware)
    2704           3 :         bitmap_subplan_mark_shared(bitmapqualplan);
    2705             : 
    2706             :     /*
    2707             :      * The qpqual list must contain all restrictions not automatically handled
    2708             :      * by the index, other than pseudoconstant clauses which will be handled
    2709             :      * by a separate gating plan node.  All the predicates in the indexquals
    2710             :      * will be checked (either by the index itself, or by
    2711             :      * nodeBitmapHeapscan.c), but if there are any "special" operators
    2712             :      * involved then they must be added to qpqual.  The upshot is that qpqual
    2713             :      * must contain scan_clauses minus whatever appears in indexquals.
    2714             :      *
    2715             :      * This loop is similar to the comparable code in create_indexscan_plan(),
    2716             :      * but with some differences because it has to compare the scan clauses to
    2717             :      * stripped (no RestrictInfos) indexquals.  See comments there for more
    2718             :      * info.
    2719             :      *
    2720             :      * In normal cases simple equal() checks will be enough to spot duplicate
    2721             :      * clauses, so we try that first.  We next see if the scan clause is
    2722             :      * redundant with any top-level indexqual by virtue of being generated
    2723             :      * from the same EC.  After that, try predicate_implied_by().
    2724             :      *
    2725             :      * Unlike create_indexscan_plan(), the predicate_implied_by() test here is
    2726             :      * useful for getting rid of qpquals that are implied by index predicates,
    2727             :      * because the predicate conditions are included in the "indexquals"
    2728             :      * returned by create_bitmap_subplan().  Bitmap scans have to do it that
    2729             :      * way because predicate conditions need to be rechecked if the scan
    2730             :      * becomes lossy, so they have to be included in bitmapqualorig.
    2731             :      */
    2732        1587 :     qpqual = NIL;
    2733        3238 :     foreach(l, scan_clauses)
    2734             :     {
    2735        1651 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
    2736        1651 :         Node       *clause = (Node *) rinfo->clause;
    2737             : 
    2738        1651 :         if (rinfo->pseudoconstant)
    2739           0 :             continue;           /* we may drop pseudoconstants here */
    2740        1651 :         if (list_member(indexquals, clause))
    2741        1617 :             continue;           /* simple duplicate */
    2742          34 :         if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
    2743          10 :             continue;           /* derived from same EquivalenceClass */
    2744          48 :         if (!contain_mutable_functions(clause) &&
    2745          24 :             predicate_implied_by(list_make1(clause), indexquals, false))
    2746          10 :             continue;           /* provably implied by indexquals */
    2747          14 :         qpqual = lappend(qpqual, rinfo);
    2748             :     }
    2749             : 
    2750             :     /* Sort clauses into best execution order */
    2751        1587 :     qpqual = order_qual_clauses(root, qpqual);
    2752             : 
    2753             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    2754        1587 :     qpqual = extract_actual_clauses(qpqual, false);
    2755             : 
    2756             :     /*
    2757             :      * When dealing with special operators, we will at this point have
    2758             :      * duplicate clauses in qpqual and bitmapqualorig.  We may as well drop
    2759             :      * 'em from bitmapqualorig, since there's no point in making the tests
    2760             :      * twice.
    2761             :      */
    2762        1587 :     bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
    2763             : 
    2764             :     /*
    2765             :      * We have to replace any outer-relation variables with nestloop params in
    2766             :      * the qpqual and bitmapqualorig expressions.  (This was already done for
    2767             :      * expressions attached to plan nodes in the bitmapqualplan tree.)
    2768             :      */
    2769        1587 :     if (best_path->path.param_info)
    2770             :     {
    2771          15 :         qpqual = (List *)
    2772             :             replace_nestloop_params(root, (Node *) qpqual);
    2773          15 :         bitmapqualorig = (List *)
    2774          15 :             replace_nestloop_params(root, (Node *) bitmapqualorig);
    2775             :     }
    2776             : 
    2777             :     /* Finally ready to build the plan node */
    2778        1587 :     scan_plan = make_bitmap_heapscan(tlist,
    2779             :                                      qpqual,
    2780             :                                      bitmapqualplan,
    2781             :                                      bitmapqualorig,
    2782             :                                      baserelid);
    2783             : 
    2784        1587 :     copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
    2785             : 
    2786        1587 :     return scan_plan;
    2787             : }
    2788             : 
    2789             : /*
    2790             :  * Given a bitmapqual tree, generate the Plan tree that implements it
    2791             :  *
    2792             :  * As byproducts, we also return in *qual and *indexqual the qual lists
    2793             :  * (in implicit-AND form, without RestrictInfos) describing the original index
    2794             :  * conditions and the generated indexqual conditions.  (These are the same in
    2795             :  * simple cases, but when special index operators are involved, the former
    2796             :  * list includes the special conditions while the latter includes the actual
    2797             :  * indexable conditions derived from them.)  Both lists include partial-index
    2798             :  * predicates, because we have to recheck predicates as well as index
    2799             :  * conditions if the bitmap scan becomes lossy.
    2800             :  *
    2801             :  * In addition, we return a list of EquivalenceClass pointers for all the
    2802             :  * top-level indexquals that were possibly-redundantly derived from ECs.
    2803             :  * This allows removal of scan_clauses that are redundant with such quals.
    2804             :  * (We do not attempt to detect such redundancies for quals that are within
    2805             :  * OR subtrees.  This could be done in a less hacky way if we returned the
    2806             :  * indexquals in RestrictInfo form, but that would be slower and still pretty
    2807             :  * messy, since we'd have to build new RestrictInfos in many cases.)
    2808             :  */
    2809             : static Plan *
    2810        1632 : create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual,
    2811             :                       List **qual, List **indexqual, List **indexECs)
    2812             : {
    2813             :     Plan       *plan;
    2814             : 
    2815        1632 :     if (IsA(bitmapqual, BitmapAndPath))
    2816             :     {
    2817           3 :         BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
    2818           3 :         List       *subplans = NIL;
    2819           3 :         List       *subquals = NIL;
    2820           3 :         List       *subindexquals = NIL;
    2821           3 :         List       *subindexECs = NIL;
    2822             :         ListCell   *l;
    2823             : 
    2824             :         /*
    2825             :          * There may well be redundant quals among the subplans, since a
    2826             :          * top-level WHERE qual might have gotten used to form several
    2827             :          * different index quals.  We don't try exceedingly hard to eliminate
    2828             :          * redundancies, but we do eliminate obvious duplicates by using
    2829             :          * list_concat_unique.
    2830             :          */
    2831           9 :         foreach(l, apath->bitmapquals)
    2832             :         {
    2833             :             Plan       *subplan;
    2834             :             List       *subqual;
    2835             :             List       *subindexqual;
    2836             :             List       *subindexEC;
    2837             : 
    2838           6 :             subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
    2839             :                                             &subqual, &subindexqual,
    2840             :                                             &subindexEC);
    2841           6 :             subplans = lappend(subplans, subplan);
    2842           6 :             subquals = list_concat_unique(subquals, subqual);
    2843           6 :             subindexquals = list_concat_unique(subindexquals, subindexqual);
    2844             :             /* Duplicates in indexECs aren't worth getting rid of */
    2845           6 :             subindexECs = list_concat(subindexECs, subindexEC);
    2846             :         }
    2847           3 :         plan = (Plan *) make_bitmap_and(subplans);
    2848           3 :         plan->startup_cost = apath->path.startup_cost;
    2849           3 :         plan->total_cost = apath->path.total_cost;
    2850           3 :         plan->plan_rows =
    2851           3 :             clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
    2852           3 :         plan->plan_width = 0;    /* meaningless */
    2853           3 :         plan->parallel_aware = false;
    2854           3 :         plan->parallel_safe = apath->path.parallel_safe;
    2855           3 :         *qual = subquals;
    2856           3 :         *indexqual = subindexquals;
    2857           3 :         *indexECs = subindexECs;
    2858             :     }
    2859        1629 :     else if (IsA(bitmapqual, BitmapOrPath))
    2860             :     {
    2861          17 :         BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
    2862          17 :         List       *subplans = NIL;
    2863          17 :         List       *subquals = NIL;
    2864          17 :         List       *subindexquals = NIL;
    2865          17 :         bool        const_true_subqual = false;
    2866          17 :         bool        const_true_subindexqual = false;
    2867             :         ListCell   *l;
    2868             : 
    2869             :         /*
    2870             :          * Here, we only detect qual-free subplans.  A qual-free subplan would
    2871             :          * cause us to generate "... OR true ..."  which we may as well reduce
    2872             :          * to just "true".  We do not try to eliminate redundant subclauses
    2873             :          * because (a) it's not as likely as in the AND case, and (b) we might
    2874             :          * well be working with hundreds or even thousands of OR conditions,
    2875             :          * perhaps from a long IN list.  The performance of list_append_unique
    2876             :          * would be unacceptable.
    2877             :          */
    2878          56 :         foreach(l, opath->bitmapquals)
    2879             :         {
    2880             :             Plan       *subplan;
    2881             :             List       *subqual;
    2882             :             List       *subindexqual;
    2883             :             List       *subindexEC;
    2884             : 
    2885          39 :             subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
    2886             :                                             &subqual, &subindexqual,
    2887             :                                             &subindexEC);
    2888          39 :             subplans = lappend(subplans, subplan);
    2889          39 :             if (subqual == NIL)
    2890           0 :                 const_true_subqual = true;
    2891          39 :             else if (!const_true_subqual)
    2892          78 :                 subquals = lappend(subquals,
    2893          39 :                                    make_ands_explicit(subqual));
    2894          39 :             if (subindexqual == NIL)
    2895           0 :                 const_true_subindexqual = true;
    2896          39 :             else if (!const_true_subindexqual)
    2897          78 :                 subindexquals = lappend(subindexquals,
    2898          39 :                                         make_ands_explicit(subindexqual));
    2899             :         }
    2900             : 
    2901             :         /*
    2902             :          * In the presence of ScalarArrayOpExpr quals, we might have built
    2903             :          * BitmapOrPaths with just one subpath; don't add an OR step.
    2904             :          */
    2905          17 :         if (list_length(subplans) == 1)
    2906             :         {
    2907           0 :             plan = (Plan *) linitial(subplans);
    2908             :         }
    2909             :         else
    2910             :         {
    2911          17 :             plan = (Plan *) make_bitmap_or(subplans);
    2912          17 :             plan->startup_cost = opath->path.startup_cost;
    2913          17 :             plan->total_cost = opath->path.total_cost;
    2914          17 :             plan->plan_rows =
    2915          17 :                 clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
    2916          17 :             plan->plan_width = 0;    /* meaningless */
    2917          17 :             plan->parallel_aware = false;
    2918          17 :             plan->parallel_safe = opath->path.parallel_safe;
    2919             :         }
    2920             : 
    2921             :         /*
    2922             :          * If there were constant-TRUE subquals, the OR reduces to constant
    2923             :          * TRUE.  Also, avoid generating one-element ORs, which could happen
    2924             :          * due to redundancy elimination or ScalarArrayOpExpr quals.
    2925             :          */
    2926          17 :         if (const_true_subqual)
    2927           0 :             *qual = NIL;
    2928          17 :         else if (list_length(subquals) <= 1)
    2929           0 :             *qual = subquals;
    2930             :         else
    2931          17 :             *qual = list_make1(make_orclause(subquals));
    2932          17 :         if (const_true_subindexqual)
    2933           0 :             *indexqual = NIL;
    2934          17 :         else if (list_length(subindexquals) <= 1)
    2935           0 :             *indexqual = subindexquals;
    2936             :         else
    2937          17 :             *indexqual = list_make1(make_orclause(subindexquals));
    2938          17 :         *indexECs = NIL;
    2939             :     }
    2940        1612 :     else if (IsA(bitmapqual, IndexPath))
    2941             :     {
    2942        1612 :         IndexPath  *ipath = (IndexPath *) bitmapqual;
    2943             :         IndexScan  *iscan;
    2944             :         List       *subindexECs;
    2945             :         ListCell   *l;
    2946             : 
    2947             :         /* Use the regular indexscan plan build machinery... */
    2948        1612 :         iscan = castNode(IndexScan,
    2949             :                          create_indexscan_plan(root, ipath,
    2950             :                                                NIL, NIL, false));
    2951             :         /* then convert to a bitmap indexscan */
    2952        1612 :         plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
    2953             :                                               iscan->indexid,
    2954             :                                               iscan->indexqual,
    2955             :                                               iscan->indexqualorig);
    2956             :         /* and set its cost/width fields appropriately */
    2957        1612 :         plan->startup_cost = 0.0;
    2958        1612 :         plan->total_cost = ipath->indextotalcost;
    2959        1612 :         plan->plan_rows =
    2960        1612 :             clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
    2961        1612 :         plan->plan_width = 0;    /* meaningless */
    2962        1612 :         plan->parallel_aware = false;
    2963        1612 :         plan->parallel_safe = ipath->path.parallel_safe;
    2964        1612 :         *qual = get_actual_clauses(ipath->indexclauses);
    2965        1612 :         *indexqual = get_actual_clauses(ipath->indexquals);
    2966        1623 :         foreach(l, ipath->indexinfo->indpred)
    2967             :         {
    2968          11 :             Expr       *pred = (Expr *) lfirst(l);
    2969             : 
    2970             :             /*
    2971             :              * We know that the index predicate must have been implied by the
    2972             :              * query condition as a whole, but it may or may not be implied by
    2973             :              * the conditions that got pushed into the bitmapqual.  Avoid
    2974             :              * generating redundant conditions.
    2975             :              */
    2976          11 :             if (!predicate_implied_by(list_make1(pred), ipath->indexclauses,
    2977             :                                       false))
    2978             :             {
    2979           6 :                 *qual = lappend(*qual, pred);
    2980           6 :                 *indexqual = lappend(*indexqual, pred);
    2981             :             }
    2982             :         }
    2983        1612 :         subindexECs = NIL;
    2984        3287 :         foreach(l, ipath->indexquals)
    2985             :         {
    2986        1675 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
    2987             : 
    2988        1675 :             if (rinfo->parent_ec)
    2989          10 :                 subindexECs = lappend(subindexECs, rinfo->parent_ec);
    2990             :         }
    2991        1612 :         *indexECs = subindexECs;
    2992             :     }
    2993             :     else
    2994             :     {
    2995           0 :         elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
    2996             :         plan = NULL;            /* keep compiler quiet */
    2997             :     }
    2998             : 
    2999        1632 :     return plan;
    3000             : }
    3001             : 
    3002             : /*
    3003             :  * create_tidscan_plan
    3004             :  *   Returns a tidscan plan for the base relation scanned by 'best_path'
    3005             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3006             :  */
    3007             : static TidScan *
    3008          66 : create_tidscan_plan(PlannerInfo *root, TidPath *best_path,
    3009             :                     List *tlist, List *scan_clauses)
    3010             : {
    3011             :     TidScan    *scan_plan;
    3012          66 :     Index       scan_relid = best_path->path.parent->relid;
    3013          66 :     List       *tidquals = best_path->tidquals;
    3014             :     List       *ortidquals;
    3015             : 
    3016             :     /* it should be a base rel... */
    3017          66 :     Assert(scan_relid > 0);
    3018          66 :     Assert(best_path->path.parent->rtekind == RTE_RELATION);
    3019             : 
    3020             :     /* Sort clauses into best execution order */
    3021          66 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3022             : 
    3023             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3024          66 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3025             : 
    3026             :     /* Replace any outer-relation variables with nestloop params */
    3027          66 :     if (best_path->path.param_info)
    3028             :     {
    3029           0 :         tidquals = (List *)
    3030             :             replace_nestloop_params(root, (Node *) tidquals);
    3031           0 :         scan_clauses = (List *)
    3032             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3033             :     }
    3034             : 
    3035             :     /*
    3036             :      * Remove any clauses that are TID quals.  This is a bit tricky since the
    3037             :      * tidquals list has implicit OR semantics.
    3038             :      */
    3039          66 :     ortidquals = tidquals;
    3040          66 :     if (list_length(ortidquals) > 1)
    3041           2 :         ortidquals = list_make1(make_orclause(ortidquals));
    3042          66 :     scan_clauses = list_difference(scan_clauses, ortidquals);
    3043             : 
    3044          66 :     scan_plan = make_tidscan(tlist,
    3045             :                              scan_clauses,
    3046             :                              scan_relid,
    3047             :                              tidquals);
    3048             : 
    3049          66 :     copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
    3050             : 
    3051          66 :     return scan_plan;
    3052             : }
    3053             : 
    3054             : /*
    3055             :  * create_subqueryscan_plan
    3056             :  *   Returns a subqueryscan plan for the base relation scanned by 'best_path'
    3057             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3058             :  */
    3059             : static SubqueryScan *
    3060        1059 : create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path,
    3061             :                          List *tlist, List *scan_clauses)
    3062             : {
    3063             :     SubqueryScan *scan_plan;
    3064        1059 :     RelOptInfo *rel = best_path->path.parent;
    3065        1059 :     Index       scan_relid = rel->relid;
    3066             :     Plan       *subplan;
    3067             : 
    3068             :     /* it should be a subquery base rel... */
    3069        1059 :     Assert(scan_relid > 0);
    3070        1059 :     Assert(rel->rtekind == RTE_SUBQUERY);
    3071             : 
    3072             :     /*
    3073             :      * Recursively create Plan from Path for subquery.  Since we are entering
    3074             :      * a different planner context (subroot), recurse to create_plan not
    3075             :      * create_plan_recurse.
    3076             :      */
    3077        1059 :     subplan = create_plan(rel->subroot, best_path->subpath);
    3078             : 
    3079             :     /* Sort clauses into best execution order */
    3080        1059 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3081             : 
    3082             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3083        1059 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3084             : 
    3085             :     /* Replace any outer-relation variables with nestloop params */
    3086        1059 :     if (best_path->path.param_info)
    3087             :     {
    3088          59 :         scan_clauses = (List *)
    3089             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3090          59 :         process_subquery_nestloop_params(root,
    3091             :                                          rel->subplan_params);
    3092             :     }
    3093             : 
    3094        1059 :     scan_plan = make_subqueryscan(tlist,
    3095             :                                   scan_clauses,
    3096             :                                   scan_relid,
    3097             :                                   subplan);
    3098             : 
    3099        1059 :     copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
    3100             : 
    3101        1059 :     return scan_plan;
    3102             : }
    3103             : 
    3104             : /*
    3105             :  * create_functionscan_plan
    3106             :  *   Returns a functionscan plan for the base relation scanned by 'best_path'
    3107             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3108             :  */
    3109             : static FunctionScan *
    3110        1327 : create_functionscan_plan(PlannerInfo *root, Path *best_path,
    3111             :                          List *tlist, List *scan_clauses)
    3112             : {
    3113             :     FunctionScan *scan_plan;
    3114        1327 :     Index       scan_relid = best_path->parent->relid;
    3115             :     RangeTblEntry *rte;
    3116             :     List       *functions;
    3117             : 
    3118             :     /* it should be a function base rel... */
    3119        1327 :     Assert(scan_relid > 0);
    3120        1327 :     rte = planner_rt_fetch(scan_relid, root);
    3121        1327 :     Assert(rte->rtekind == RTE_FUNCTION);
    3122        1327 :     functions = rte->functions;
    3123             : 
    3124             :     /* Sort clauses into best execution order */
    3125        1327 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3126             : 
    3127             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3128        1327 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3129             : 
    3130             :     /* Replace any outer-relation variables with nestloop params */
    3131        1327 :     if (best_path->param_info)
    3132             :     {
    3133          51 :         scan_clauses = (List *)
    3134             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3135             :         /* The function expressions could contain nestloop params, too */
    3136          51 :         functions = (List *) replace_nestloop_params(root, (Node *) functions);
    3137             :     }
    3138             : 
    3139        1327 :     scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
    3140        1327 :                                   functions, rte->funcordinality);
    3141             : 
    3142        1327 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3143             : 
    3144        1327 :     return scan_plan;
    3145             : }
    3146             : 
    3147             : /*
    3148             :  * create_tablefuncscan_plan
    3149             :  *   Returns a tablefuncscan plan for the base relation scanned by 'best_path'
    3150             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3151             :  */
    3152             : static TableFuncScan *
    3153          22 : create_tablefuncscan_plan(PlannerInfo *root, Path *best_path,
    3154             :                           List *tlist, List *scan_clauses)
    3155             : {
    3156             :     TableFuncScan *scan_plan;
    3157          22 :     Index       scan_relid = best_path->parent->relid;
    3158             :     RangeTblEntry *rte;
    3159             :     TableFunc  *tablefunc;
    3160             : 
    3161             :     /* it should be a function base rel... */
    3162          22 :     Assert(scan_relid > 0);
    3163          22 :     rte = planner_rt_fetch(scan_relid, root);
    3164          22 :     Assert(rte->rtekind == RTE_TABLEFUNC);
    3165          22 :     tablefunc = rte->tablefunc;
    3166             : 
    3167             :     /* Sort clauses into best execution order */
    3168          22 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3169             : 
    3170             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3171          22 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3172             : 
    3173             :     /* Replace any outer-relation variables with nestloop params */
    3174          22 :     if (best_path->param_info)
    3175             :     {
    3176          22 :         scan_clauses = (List *)
    3177             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3178             :         /* The function expressions could contain nestloop params, too */
    3179          22 :         tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
    3180             :     }
    3181             : 
    3182          22 :     scan_plan = make_tablefuncscan(tlist, scan_clauses, scan_relid,
    3183             :                                    tablefunc);
    3184             : 
    3185          22 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3186             : 
    3187          22 :     return scan_plan;
    3188             : }
    3189             : 
    3190             : /*
    3191             :  * create_valuesscan_plan
    3192             :  *   Returns a valuesscan plan for the base relation scanned by 'best_path'
    3193             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3194             :  */
    3195             : static ValuesScan *
    3196         463 : create_valuesscan_plan(PlannerInfo *root, Path *best_path,
    3197             :                        List *tlist, List *scan_clauses)
    3198             : {
    3199             :     ValuesScan *scan_plan;
    3200         463 :     Index       scan_relid = best_path->parent->relid;
    3201             :     RangeTblEntry *rte;
    3202             :     List       *values_lists;
    3203             : 
    3204             :     /* it should be a values base rel... */
    3205         463 :     Assert(scan_relid > 0);
    3206         463 :     rte = planner_rt_fetch(scan_relid, root);
    3207         463 :     Assert(rte->rtekind == RTE_VALUES);
    3208         463 :     values_lists = rte->values_lists;
    3209             : 
    3210             :     /* Sort clauses into best execution order */
    3211         463 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3212             : 
    3213             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3214         463 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3215             : 
    3216             :     /* Replace any outer-relation variables with nestloop params */
    3217         463 :     if (best_path->param_info)
    3218             :     {
    3219           6 :         scan_clauses = (List *)
    3220             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3221             :         /* The values lists could contain nestloop params, too */
    3222           6 :         values_lists = (List *)
    3223             :             replace_nestloop_params(root, (Node *) values_lists);
    3224             :     }
    3225             : 
    3226         463 :     scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
    3227             :                                 values_lists);
    3228             : 
    3229         463 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3230             : 
    3231         463 :     return scan_plan;
    3232             : }
    3233             : 
    3234             : /*
    3235             :  * create_ctescan_plan
    3236             :  *   Returns a ctescan plan for the base relation scanned by 'best_path'
    3237             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3238             :  */
    3239             : static CteScan *
    3240         162 : create_ctescan_plan(PlannerInfo *root, Path *best_path,
    3241             :                     List *tlist, List *scan_clauses)
    3242             : {
    3243             :     CteScan    *scan_plan;
    3244         162 :     Index       scan_relid = best_path->parent->relid;
    3245             :     RangeTblEntry *rte;
    3246         162 :     SubPlan    *ctesplan = NULL;
    3247             :     int         plan_id;
    3248             :     int         cte_param_id;
    3249             :     PlannerInfo *cteroot;
    3250             :     Index       levelsup;
    3251             :     int         ndx;
    3252             :     ListCell   *lc;
    3253             : 
    3254         162 :     Assert(scan_relid > 0);
    3255         162 :     rte = planner_rt_fetch(scan_relid, root);
    3256         162 :     Assert(rte->rtekind == RTE_CTE);
    3257         162 :     Assert(!rte->self_reference);
    3258             : 
    3259             :     /*
    3260             :      * Find the referenced CTE, and locate the SubPlan previously made for it.
    3261             :      */
    3262         162 :     levelsup = rte->ctelevelsup;
    3263         162 :     cteroot = root;
    3264         384 :     while (levelsup-- > 0)
    3265             :     {
    3266          60 :         cteroot = cteroot->parent_root;
    3267          60 :         if (!cteroot)           /* shouldn't happen */
    3268           0 :             elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
    3269             :     }
    3270             : 
    3271             :     /*
    3272             :      * Note: cte_plan_ids can be shorter than cteList, if we are still working
    3273             :      * on planning the CTEs (ie, this is a side-reference from another CTE).
    3274             :      * So we mustn't use forboth here.
    3275             :      */
    3276         162 :     ndx = 0;
    3277         188 :     foreach(lc, cteroot->parse->cteList)
    3278             :     {
    3279         188 :         CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
    3280             : 
    3281         188 :         if (strcmp(cte->ctename, rte->ctename) == 0)
    3282         162 :             break;
    3283          26 :         ndx++;
    3284             :     }
    3285         162 :     if (lc == NULL)             /* shouldn't happen */
    3286           0 :         elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
    3287         162 :     if (ndx >= list_length(cteroot->cte_plan_ids))
    3288           0 :         elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
    3289         162 :     plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
    3290         162 :     Assert(plan_id > 0);
    3291         187 :     foreach(lc, cteroot->init_plans)
    3292             :     {
    3293         187 :         ctesplan = (SubPlan *) lfirst(lc);
    3294         187 :         if (ctesplan->plan_id == plan_id)
    3295         162 :             break;
    3296             :     }
    3297         162 :     if (lc == NULL)             /* shouldn't happen */
    3298           0 :         elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
    3299             : 
    3300             :     /*
    3301             :      * We need the CTE param ID, which is the sole member of the SubPlan's
    3302             :      * setParam list.
    3303             :      */
    3304         162 :     cte_param_id = linitial_int(ctesplan->setParam);
    3305             : 
    3306             :     /* Sort clauses into best execution order */
    3307         162 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3308             : 
    3309             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3310         162 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3311             : 
    3312             :     /* Replace any outer-relation variables with nestloop params */
    3313         162 :     if (best_path->param_info)
    3314             :     {
    3315           0 :         scan_clauses = (List *)
    3316             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3317             :     }
    3318             : 
    3319         162 :     scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
    3320             :                              plan_id, cte_param_id);
    3321             : 
    3322         162 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3323             : 
    3324         162 :     return scan_plan;
    3325             : }
    3326             : 
    3327             : /*
    3328             :  * create_namedtuplestorescan_plan
    3329             :  *   Returns a tuplestorescan plan for the base relation scanned by
    3330             :  *  'best_path' with restriction clauses 'scan_clauses' and targetlist
    3331             :  *  'tlist'.
    3332             :  */
    3333             : static NamedTuplestoreScan *
    3334          43 : create_namedtuplestorescan_plan(PlannerInfo *root, Path *best_path,
    3335             :                                 List *tlist, List *scan_clauses)
    3336             : {
    3337             :     NamedTuplestoreScan *scan_plan;
    3338          43 :     Index       scan_relid = best_path->parent->relid;
    3339             :     RangeTblEntry *rte;
    3340             : 
    3341          43 :     Assert(scan_relid > 0);
    3342          43 :     rte = planner_rt_fetch(scan_relid, root);
    3343          43 :     Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
    3344             : 
    3345             :     /* Sort clauses into best execution order */
    3346          43 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3347             : 
    3348             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3349          43 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3350             : 
    3351             :     /* Replace any outer-relation variables with nestloop params */
    3352          43 :     if (best_path->param_info)
    3353             :     {
    3354           0 :         scan_clauses = (List *)
    3355             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3356             :     }
    3357             : 
    3358          43 :     scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
    3359             :                                          rte->enrname);
    3360             : 
    3361          43 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3362             : 
    3363          43 :     return scan_plan;
    3364             : }
    3365             : 
    3366             : /*
    3367             :  * create_worktablescan_plan
    3368             :  *   Returns a worktablescan plan for the base relation scanned by 'best_path'
    3369             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3370             :  */
    3371             : static WorkTableScan *
    3372          40 : create_worktablescan_plan(PlannerInfo *root, Path *best_path,
    3373             :                           List *tlist, List *scan_clauses)
    3374             : {
    3375             :     WorkTableScan *scan_plan;
    3376          40 :     Index       scan_relid = best_path->parent->relid;
    3377             :     RangeTblEntry *rte;
    3378             :     Index       levelsup;
    3379             :     PlannerInfo *cteroot;
    3380             : 
    3381          40 :     Assert(scan_relid > 0);
    3382          40 :     rte = planner_rt_fetch(scan_relid, root);
    3383          40 :     Assert(rte->rtekind == RTE_CTE);
    3384          40 :     Assert(rte->self_reference);
    3385             : 
    3386             :     /*
    3387             :      * We need to find the worktable param ID, which is in the plan level
    3388             :      * that's processing the recursive UNION, which is one level *below* where
    3389             :      * the CTE comes from.
    3390             :      */
    3391          40 :     levelsup = rte->ctelevelsup;
    3392          40 :     if (levelsup == 0)          /* shouldn't happen */
    3393           0 :         elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
    3394          40 :     levelsup--;
    3395          40 :     cteroot = root;
    3396         126 :     while (levelsup-- > 0)
    3397             :     {
    3398          46 :         cteroot = cteroot->parent_root;
    3399          46 :         if (!cteroot)           /* shouldn't happen */
    3400           0 :             elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
    3401             :     }
    3402          40 :     if (cteroot->wt_param_id < 0) /* shouldn't happen */
    3403           0 :         elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
    3404             : 
    3405             :     /* Sort clauses into best execution order */
    3406          40 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3407             : 
    3408             :     /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
    3409          40 :     scan_clauses = extract_actual_clauses(scan_clauses, false);
    3410             : 
    3411             :     /* Replace any outer-relation variables with nestloop params */
    3412          40 :     if (best_path->param_info)
    3413             :     {
    3414           0 :         scan_clauses = (List *)
    3415             :             replace_nestloop_params(root, (Node *) scan_clauses);
    3416             :     }
    3417             : 
    3418          40 :     scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
    3419             :                                    cteroot->wt_param_id);
    3420             : 
    3421          40 :     copy_generic_path_info(&scan_plan->scan.plan, best_path);
    3422             : 
    3423          40 :     return scan_plan;
    3424             : }
    3425             : 
    3426             : /*
    3427             :  * create_foreignscan_plan
    3428             :  *   Returns a foreignscan plan for the relation scanned by 'best_path'
    3429             :  *   with restriction clauses 'scan_clauses' and targetlist 'tlist'.
    3430             :  */
    3431             : static ForeignScan *
    3432           0 : create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
    3433             :                         List *tlist, List *scan_clauses)
    3434             : {
    3435             :     ForeignScan *scan_plan;
    3436           0 :     RelOptInfo *rel = best_path->path.parent;
    3437           0 :     Index       scan_relid = rel->relid;
    3438           0 :     Oid         rel_oid = InvalidOid;
    3439           0 :     Plan       *outer_plan = NULL;
    3440             : 
    3441           0 :     Assert(rel->fdwroutine != NULL);
    3442             : 
    3443             :     /* transform the child path if any */
    3444           0 :     if (best_path->fdw_outerpath)
    3445           0 :         outer_plan = create_plan_recurse(root, best_path->fdw_outerpath,
    3446             :                                          CP_EXACT_TLIST);
    3447             : 
    3448             :     /*
    3449             :      * If we're scanning a base relation, fetch its OID.  (Irrelevant if
    3450             :      * scanning a join relation.)
    3451             :      */
    3452           0 :     if (scan_relid > 0)
    3453             :     {
    3454             :         RangeTblEntry *rte;
    3455             : 
    3456           0 :         Assert(rel->rtekind == RTE_RELATION);
    3457           0 :         rte = planner_rt_fetch(scan_relid, root);
    3458           0 :         Assert(rte->rtekind == RTE_RELATION);
    3459           0 :         rel_oid = rte->relid;
    3460             :     }
    3461             : 
    3462             :     /*
    3463             :      * Sort clauses into best execution order.  We do this first since the FDW
    3464             :      * might have more info than we do and wish to adjust the ordering.
    3465             :      */
    3466           0 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3467             : 
    3468             :     /*
    3469             :      * Let the FDW perform its processing on the restriction clauses and
    3470             :      * generate the plan node.  Note that the FDW might remove restriction
    3471             :      * clauses that it intends to execute remotely, or even add more (if it
    3472             :      * has selected some join clauses for remote use but also wants them
    3473             :      * rechecked locally).
    3474             :      */
    3475           0 :     scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid,
    3476             :                                                 best_path,
    3477             :                                                 tlist, scan_clauses,
    3478             :                                                 outer_plan);
    3479             : 
    3480             :     /* Copy cost data from Path to Plan; no need to make FDW do this */
    3481           0 :     copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
    3482             : 
    3483             :     /* Copy foreign server OID; likewise, no need to make FDW do this */
    3484           0 :     scan_plan->fs_server = rel->serverid;
    3485             : 
    3486             :     /*
    3487             :      * Likewise, copy the relids that are represented by this foreign scan. An
    3488             :      * upper rel doesn't have relids set, but it covers all the base relations
    3489             :      * participating in the underlying scan, so use root's all_baserels.
    3490             :      */
    3491           0 :     if (IS_UPPER_REL(rel))
    3492           0 :         scan_plan->fs_relids = root->all_baserels;
    3493             :     else
    3494           0 :         scan_plan->fs_relids = best_path->path.parent->relids;
    3495             : 
    3496             :     /*
    3497             :      * If this is a foreign join, and to make it valid to push down we had to
    3498             :      * assume that the current user is the same as some user explicitly named
    3499             :      * in the query, mark the finished plan as depending on the current user.
    3500             :      */
    3501           0 :     if (rel->useridiscurrent)
    3502           0 :         root->glob->dependsOnRole = true;
    3503             : 
    3504             :     /*
    3505             :      * Replace any outer-relation variables with nestloop params in the qual,
    3506             :      * fdw_exprs and fdw_recheck_quals expressions.  We do this last so that
    3507             :      * the FDW doesn't have to be involved.  (Note that parts of fdw_exprs or
    3508             :      * fdw_recheck_quals could have come from join clauses, so doing this
    3509             :      * beforehand on the scan_clauses wouldn't work.)  We assume
    3510             :      * fdw_scan_tlist contains no such variables.
    3511             :      */
    3512           0 :     if (best_path->path.param_info)
    3513             :     {
    3514           0 :         scan_plan->scan.plan.qual = (List *)
    3515           0 :             replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
    3516           0 :         scan_plan->fdw_exprs = (List *)
    3517           0 :             replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
    3518           0 :         scan_plan->fdw_recheck_quals = (List *)
    3519           0 :             replace_nestloop_params(root,
    3520           0 :                                     (Node *) scan_plan->fdw_recheck_quals);
    3521             :     }
    3522             : 
    3523             :     /*
    3524             :      * If rel is a base relation, detect whether any system columns are
    3525             :      * requested from the rel.  (If rel is a join relation, rel->relid will be
    3526             :      * 0, but there can be no Var with relid 0 in the rel's targetlist or the
    3527             :      * restriction clauses, so we skip this in that case.  Note that any such
    3528             :      * columns in base relations that were joined are assumed to be contained
    3529             :      * in fdw_scan_tlist.)  This is a bit of a kluge and might go away
    3530             :      * someday, so we intentionally leave it out of the API presented to FDWs.
    3531             :      */
    3532           0 :     scan_plan->fsSystemCol = false;
    3533           0 :     if (scan_relid > 0)
    3534             :     {
    3535           0 :         Bitmapset  *attrs_used = NULL;
    3536             :         ListCell   *lc;
    3537             :         int         i;
    3538             : 
    3539             :         /*
    3540             :          * First, examine all the attributes needed for joins or final output.
    3541             :          * Note: we must look at rel's targetlist, not the attr_needed data,
    3542             :          * because attr_needed isn't computed for inheritance child rels.
    3543             :          */
    3544           0 :         pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used);
    3545             : 
    3546             :         /* Add all the attributes used by restriction clauses. */
    3547           0 :         foreach(lc, rel->baserestrictinfo)
    3548             :         {
    3549           0 :             RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
    3550             : 
    3551           0 :             pull_varattnos((Node *) rinfo->clause, scan_relid, &attrs_used);
    3552             :         }
    3553             : 
    3554             :         /* Now, are any system columns requested from rel? */
    3555           0 :         for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
    3556             :         {
    3557           0 :             if (bms_is_member(i - FirstLowInvalidHeapAttributeNumber, attrs_used))
    3558             :             {
    3559           0 :                 scan_plan->fsSystemCol = true;
    3560           0 :                 break;
    3561             :             }
    3562             :         }
    3563             : 
    3564           0 :         bms_free(attrs_used);
    3565             :     }
    3566             : 
    3567           0 :     return scan_plan;
    3568             : }
    3569             : 
    3570             : /*
    3571             :  * create_custom_plan
    3572             :  *
    3573             :  * Transform a CustomPath into a Plan.
    3574             :  */
    3575             : static CustomScan *
    3576           0 : create_customscan_plan(PlannerInfo *root, CustomPath *best_path,
    3577             :                        List *tlist, List *scan_clauses)
    3578             : {
    3579             :     CustomScan *cplan;
    3580           0 :     RelOptInfo *rel = best_path->path.parent;
    3581           0 :     List       *custom_plans = NIL;
    3582             :     ListCell   *lc;
    3583             : 
    3584             :     /* Recursively transform child paths. */
    3585           0 :     foreach(lc, best_path->custom_paths)
    3586             :     {
    3587           0 :         Plan       *plan = create_plan_recurse(root, (Path *) lfirst(lc),
    3588             :                                                CP_EXACT_TLIST);
    3589             : 
    3590           0 :         custom_plans = lappend(custom_plans, plan);
    3591             :     }
    3592             : 
    3593             :     /*
    3594             :      * Sort clauses into the best execution order, although custom-scan
    3595             :      * provider can reorder them again.
    3596             :      */
    3597           0 :     scan_clauses = order_qual_clauses(root, scan_clauses);
    3598             : 
    3599             :     /*
    3600             :      * Invoke custom plan provider to create the Plan node represented by the
    3601             :      * CustomPath.
    3602             :      */
    3603           0 :     cplan = castNode(CustomScan,
    3604             :                      best_path->methods->PlanCustomPath(root,
    3605             :                                                         rel,
    3606             :                                                         best_path,
    3607             :                                                         tlist,
    3608             :                                                         scan_clauses,
    3609             :                                                         custom_plans));
    3610             : 
    3611             :     /*
    3612             :      * Copy cost data from Path to Plan; no need to make custom-plan providers
    3613             :      * do this
    3614             :      */
    3615           0 :     copy_generic_path_info(&cplan->scan.plan, &best_path->path);
    3616             : 
    3617             :     /* Likewise, copy the relids that are represented by this custom scan */
    3618           0 :     cplan->custom_relids = best_path->path.parent->relids;
    3619             : 
    3620             :     /*
    3621             :      * Replace any outer-relation variables with nestloop params in the qual
    3622             :      * and custom_exprs expressions.  We do this last so that the custom-plan
    3623             :      * provider doesn't have to be involved.  (Note that parts of custom_exprs
    3624             :      * could have come from join clauses, so doing this beforehand on the
    3625             :      * scan_clauses wouldn't work.)  We assume custom_scan_tlist contains no
    3626             :      * such variables.
    3627             :      */
    3628           0 :     if (best_path->path.param_info)
    3629             :     {
    3630           0 :         cplan->scan.plan.qual = (List *)
    3631           0 :             replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
    3632           0 :         cplan->custom_exprs = (List *)
    3633           0 :             replace_nestloop_params(root, (Node *) cplan->custom_exprs);
    3634             :     }
    3635             : 
    3636           0 :     return cplan;
    3637             : }
    3638             : 
    3639             : 
    3640             : /*****************************************************************************
    3641             :  *
    3642             :  *  JOIN METHODS
    3643             :  *
    3644             :  *****************************************************************************/
    3645             : 
    3646             : static NestLoop *
    3647        2186 : create_nestloop_plan(PlannerInfo *root,
    3648             :                      NestPath *best_path)
    3649             : {
    3650             :     NestLoop   *join_plan;
    3651             :     Plan       *outer_plan;
    3652             :     Plan       *inner_plan;
    3653        2186 :     List       *tlist = build_path_tlist(root, &best_path->path);
    3654        2186 :     List       *joinrestrictclauses = best_path->joinrestrictinfo;
    3655             :     List       *joinclauses;
    3656             :     List       *otherclauses;
    3657             :     Relids      outerrelids;
    3658             :     List       *nestParams;
    3659        2186 :     Relids      saveOuterRels = root->curOuterRels;
    3660             :     ListCell   *cell;
    3661             :     ListCell   *prev;
    3662             :     ListCell   *next;
    3663             : 
    3664             :     /* NestLoop can project, so no need to be picky about child tlists */
    3665        2186 :     outer_plan = create_plan_recurse(root, best_path->outerjoinpath, 0);
    3666             : 
    3667             :     /* For a nestloop, include outer relids in curOuterRels for inner side */
    3668        2186 :     root->curOuterRels = bms_union(root->curOuterRels,
    3669        2186 :                                    best_path->outerjoinpath->parent->relids);
    3670             : 
    3671        2186 :     inner_plan = create_plan_recurse(root, best_path->innerjoinpath, 0);
    3672             : 
    3673             :     /* Restore curOuterRels */
    3674        2186 :     bms_free(root->curOuterRels);
    3675        2186 :     root->curOuterRels = saveOuterRels;
    3676             : 
    3677             :     /* Sort join qual clauses into best execution order */
    3678        2186 :     joinrestrictclauses = order_qual_clauses(root, joinrestrictclauses);
    3679             : 
    3680             :     /* Get the join qual clauses (in plain expression form) */
    3681             :     /* Any pseudoconstant clauses are ignored here */
    3682        2186 :     if (IS_OUTER_JOIN(best_path->jointype))
    3683             :     {
    3684         528 :         extract_actual_join_clauses(joinrestrictclauses,
    3685             :                                     &joinclauses, &otherclauses);
    3686             :     }
    3687             :     else
    3688             :     {
    3689             :         /* We can treat all clauses alike for an inner join */
    3690        1658 :         joinclauses = extract_actual_clauses(joinrestrictclauses, false);
    3691        1658 :         otherclauses = NIL;
    3692             :     }
    3693             : 
    3694             :     /* Replace any outer-relation variables with nestloop params */
    3695        2186 :     if (best_path->path.param_info)
    3696             :     {
    3697          70 :         joinclauses = (List *)
    3698          70 :             replace_nestloop_params(root, (Node *) joinclauses);
    3699          70 :         otherclauses = (List *)
    3700          70 :             replace_nestloop_params(root, (Node *) otherclauses);
    3701             :     }
    3702             : 
    3703             :     /*
    3704             :      * Identify any nestloop parameters that should be supplied by this join
    3705             :      * node, and move them from root->curOuterParams to the nestParams list.
    3706             :      */
    3707        2186 :     outerrelids = best_path->outerjoinpath->parent->relids;
    3708        2186 :     nestParams = NIL;
    3709        2186 :     prev = NULL;
    3710        3374 :     for (cell = list_head(root->curOuterParams); cell; cell = next)
    3711             :     {
    3712        1188 :         NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
    3713             : 
    3714        1188 :         next = lnext(cell);
    3715        2361 :         if (IsA(nlp->paramval, Var) &&
    3716        1173 :             bms_is_member(nlp->paramval->varno, outerrelids))
    3717             :         {
    3718        1097 :             root->curOuterParams = list_delete_cell(root->curOuterParams,
    3719             :                                                     cell, prev);
    3720        1097 :             nestParams = lappend(nestParams, nlp);
    3721             :         }
    3722         106 :         else if (IsA(nlp->paramval, PlaceHolderVar) &&
    3723          15 :                  bms_overlap(((PlaceHolderVar *) nlp->paramval)->phrels,
    3724          15 :                              outerrelids) &&
    3725          30 :                  bms_is_subset(find_placeholder_info(root,
    3726          15 :                                                      (PlaceHolderVar *) nlp->paramval,
    3727          15 :                                                      false)->ph_eval_at,
    3728             :                                outerrelids))
    3729             :         {
    3730          15 :             root->curOuterParams = list_delete_cell(root->curOuterParams,
    3731             :                                                     cell, prev);
    3732          15 :             nestParams = lappend(nestParams, nlp);
    3733             :         }
    3734             :         else
    3735          76 :             prev = cell;
    3736             :     }
    3737             : 
    3738        2186 :     join_plan = make_nestloop(tlist,
    3739             :                               joinclauses,
    3740             :                               otherclauses,
    3741             :                               nestParams,
    3742             :                               outer_plan,
    3743             :                               inner_plan,
    3744             :                               best_path->jointype,
    3745        2186 :                               best_path->inner_unique);
    3746             : 
    3747        2186 :     copy_generic_path_info(&join_plan->join.plan, &best_path->path);
    3748             : 
    3749        2186 :     return join_plan;
    3750             : }
    3751             : 
    3752             : static MergeJoin *
    3753         165 : create_mergejoin_plan(PlannerInfo *root,
    3754             :                       MergePath *best_path)
    3755             : {
    3756             :     MergeJoin  *join_plan;
    3757             :     Plan       *outer_plan;
    3758             :     Plan       *inner_plan;
    3759         165 :     List       *tlist = build_path_tlist(root, &best_path->jpath.path);
    3760             :     List       *joinclauses;
    3761             :     List       *otherclauses;
    3762             :     List       *mergeclauses;
    3763             :     List       *outerpathkeys;
    3764             :     List       *innerpathkeys;
    3765             :     int         nClauses;
    3766             :     Oid        *mergefamilies;
    3767             :     Oid        *mergecollations;
    3768             :     int        *mergestrategies;
    3769             :     bool       *mergenullsfirst;
    3770             :     int         i;
    3771             :     ListCell   *lc;
    3772             :     ListCell   *lop;
    3773             :     ListCell   *lip;
    3774             : 
    3775             :     /*
    3776             :      * MergeJoin can project, so we don't have to demand exact tlists from the
    3777             :      * inputs.  However, if we're intending to sort an input's result, it's
    3778             :      * best to request a small tlist so we aren't sorting more data than
    3779             :      * necessary.
    3780             :      */
    3781         165 :     outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
    3782         165 :                                      (best_path->outersortkeys != NIL) ? CP_SMALL_TLIST : 0);
    3783             : 
    3784         165 :     inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
    3785         165 :                                      (best_path->innersortkeys != NIL) ? CP_SMALL_TLIST : 0);
    3786             : 
    3787             :     /* Sort join qual clauses into best execution order */
    3788             :     /* NB: do NOT reorder the mergeclauses */
    3789         165 :     joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
    3790             : 
    3791             :     /* Get the join qual clauses (in plain expression form) */
    3792             :     /* Any pseudoconstant clauses are ignored here */
    3793         165 :     if (IS_OUTER_JOIN(best_path->jpath.jointype))
    3794             :     {
    3795          66 :         extract_actual_join_clauses(joinclauses,
    3796             :                                     &joinclauses, &otherclauses);
    3797             :     }
    3798             :     else
    3799             :     {
    3800             :         /* We can treat all clauses alike for an inner join */
    3801          99 :         joinclauses = extract_actual_clauses(joinclauses, false);
    3802          99 :         otherclauses = NIL;
    3803             :     }
    3804             : 
    3805             :     /*
    3806             :      * Remove the mergeclauses from the list of join qual clauses, leaving the
    3807             :      * list of quals that must be checked as qpquals.
    3808             :      */
    3809         165 :     mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
    3810         165 :     joinclauses = list_difference(joinclauses, mergeclauses);
    3811             : 
    3812             :     /*
    3813             :      * Replace any outer-relation variables with nestloop params.  There
    3814             :      * should not be any in the mergeclauses.
    3815             :      */
    3816         165 :     if (best_path->jpath.path.param_info)
    3817             :     {
    3818           0 :         joinclauses = (List *)
    3819           0 :             replace_nestloop_params(root, (Node *) joinclauses);
    3820           0 :         otherclauses = (List *)
    3821           0 :             replace_nestloop_params(root, (Node *) otherclauses);
    3822             :     }
    3823             : 
    3824             :     /*
    3825             :      * Rearrange mergeclauses, if needed, so that the outer variable is always
    3826             :      * on the left; mark the mergeclause restrictinfos with correct
    3827             :      * outer_is_left status.
    3828             :      */
    3829         165 :     mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
    3830         165 :                                         best_path->jpath.outerjoinpath->parent->relids);
    3831             : 
    3832             :     /*
    3833             :      * Create explicit sort nodes for the outer and inner paths if necessary.
    3834             :      */
    3835         165 :     if (best_path->outersortkeys)
    3836             :     {
    3837         137 :         Sort       *sort = make_sort_from_pathkeys(outer_plan,
    3838             :                                                    best_path->outersortkeys);
    3839             : 
    3840         137 :         label_sort_with_costsize(root, sort, -1.0);
    3841         137 :         outer_plan = (Plan *) sort;
    3842         137 :         outerpathkeys = best_path->outersortkeys;
    3843             :     }
    3844             :     else
    3845          28 :         outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
    3846             : 
    3847         165 :     if (best_path->innersortkeys)
    3848             :     {
    3849         133 :         Sort       *sort = make_sort_from_pathkeys(inner_plan,
    3850             :                                                    best_path->innersortkeys);
    3851             : 
    3852         133 :         label_sort_with_costsize(root, sort, -1.0);
    3853         133 :         inner_plan = (Plan *) sort;
    3854         133 :         innerpathkeys = best_path->innersortkeys;
    3855             :     }
    3856             :     else
    3857          32 :         innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
    3858             : 
    3859             :     /*
    3860             :      * If specified, add a materialize node to shield the inner plan from the
    3861             :      * need to handle mark/restore.
    3862             :      */
    3863         165 :     if (best_path->materialize_inner)
    3864             :     {
    3865          14 :         Plan       *matplan = (Plan *) make_material(inner_plan);
    3866             : 
    3867             :         /*
    3868             :          * We assume the materialize will not spill to disk, and therefore
    3869             :          * charge just cpu_operator_cost per tuple.  (Keep this estimate in
    3870             :          * sync with final_cost_mergejoin.)
    3871             :          */
    3872          14 :         copy_plan_costsize(matplan, inner_plan);
    3873          14 :         matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
    3874             : 
    3875          14 :         inner_plan = matplan;
    3876             :     }
    3877             : 
    3878             :     /*
    3879             :      * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
    3880             :      * executor.  The information is in the pathkeys for the two inputs, but
    3881             :      * we need to be careful about the possibility of mergeclauses sharing a
    3882             :      * pathkey (compare find_mergeclauses_for_pathkeys()).
    3883             :      */
    3884         165 :     nClauses = list_length(mergeclauses);
    3885         165 :     Assert(nClauses == list_length(best_path->path_mergeclauses));
    3886         165 :     mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
    3887         165 :     mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
    3888         165 :     mergestrategies = (int *) palloc(nClauses * sizeof(int));
    3889         165 :     mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
    3890             : 
    3891         165 :     lop = list_head(outerpathkeys);
    3892         165 :     lip = list_head(innerpathkeys);
    3893         165 :     i = 0;
    3894         335 :     foreach(lc, best_path->path_mergeclauses)
    3895             :     {
    3896         170 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
    3897             :         EquivalenceClass *oeclass;
    3898             :         EquivalenceClass *ieclass;
    3899             :         PathKey    *opathkey;
    3900             :         PathKey    *ipathkey;
    3901             :         EquivalenceClass *opeclass;
    3902             :         EquivalenceClass *ipeclass;
    3903             :         ListCell   *l2;
    3904             : 
    3905             :         /* fetch outer/inner eclass from mergeclause */
    3906         170 :         if (rinfo->outer_is_left)
    3907             :         {
    3908         134 :             oeclass = rinfo->left_ec;
    3909         134 :             ieclass = rinfo->right_ec;
    3910             :         }
    3911             :         else
    3912             :         {
    3913          36 :             oeclass = rinfo->right_ec;
    3914          36 :             ieclass = rinfo->left_ec;
    3915             :         }
    3916         170 :         Assert(oeclass != NULL);
    3917         170 :         Assert(ieclass != NULL);
    3918             : 
    3919             :         /*
    3920             :          * For debugging purposes, we check that the eclasses match the paths'
    3921             :          * pathkeys.  In typical cases the merge clauses are one-to-one with
    3922             :          * the pathkeys, but when dealing with partially redundant query
    3923             :          * conditions, we might have clauses that re-reference earlier path
    3924             :          * keys.  The case that we need to reject is where a pathkey is
    3925             :          * entirely skipped over.
    3926             :          *
    3927             :          * lop and lip reference the first as-yet-unused pathkey elements;
    3928             :          * it's okay to match them, or any element before them.  If they're
    3929             :          * NULL then we have found all pathkey elements to be used.
    3930             :          */
    3931         170 :         if (lop)
    3932             :         {
    3933         168 :             opathkey = (PathKey *) lfirst(lop);
    3934         168 :             opeclass = opathkey->pk_eclass;
    3935         168 :             if (oeclass == opeclass)
    3936             :             {
    3937             :                 /* fast path for typical case */
    3938         168 :                 lop = lnext(lop);
    3939             :             }
    3940             :             else
    3941             :             {
    3942             :                 /* redundant clauses ... must match something before lop */
    3943           0 :                 foreach(l2, outerpathkeys)
    3944             :                 {
    3945           0 :                     if (l2 == lop)
    3946           0 :                         break;
    3947           0 :                     opathkey = (PathKey *) lfirst(l2);
    3948           0 :                     opeclass = opathkey->pk_eclass;
    3949           0 :                     if (oeclass == opeclass)
    3950           0 :                         break;
    3951             :                 }
    3952           0 :                 if (oeclass != opeclass)
    3953           0 :                     elog(ERROR, "outer pathkeys do not match mergeclauses");
    3954             :             }
    3955             :         }
    3956             :         else
    3957             :         {
    3958             :             /* redundant clauses ... must match some already-used pathkey */
    3959           2 :             opathkey = NULL;
    3960           2 :             opeclass = NULL;
    3961           2 :             foreach(l2, outerpathkeys)
    3962             :             {
    3963           2 :                 opathkey = (PathKey *) lfirst(l2);
    3964           2 :                 opeclass = opathkey->pk_eclass;
    3965           2 :                 if (oeclass == opeclass)
    3966           2 :                     break;
    3967             :             }
    3968           2 :             if (l2 == NULL)
    3969           0 :                 elog(ERROR, "outer pathkeys do not match mergeclauses");
    3970             :         }
    3971             : 
    3972         170 :         if (lip)
    3973             :         {
    3974         169 :             ipathkey = (PathKey *) lfirst(lip);
    3975         169 :             ipeclass = ipathkey->pk_eclass;
    3976         169 :             if (ieclass == ipeclass)
    3977             :             {
    3978             :                 /* fast path for typical case */
    3979         169 :                 lip = lnext(lip);
    3980             :             }
    3981             :             else
    3982             :             {
    3983             :                 /* redundant clauses ... must match something before lip */
    3984           0 :                 foreach(l2, innerpathkeys)
    3985             :                 {
    3986           0 :                     if (l2 == lip)
    3987           0 :                         break;
    3988           0 :                     ipathkey = (PathKey *) lfirst(l2);
    3989           0 :                     ipeclass = ipathkey->pk_eclass;
    3990           0 :                     if (ieclass == ipeclass)
    3991           0 :                         break;
    3992             :                 }
    3993           0 :                 if (ieclass != ipeclass)
    3994           0 :                     elog(ERROR, "inner pathkeys do not match mergeclauses");
    3995             :             }
    3996             :         }
    3997             :         else
    3998             :         {
    3999             :             /* redundant clauses ... must match some already-used pathkey */
    4000           1 :             ipathkey = NULL;
    4001           1 :             ipeclass = NULL;
    4002           1 :             foreach(l2, innerpathkeys)
    4003             :             {
    4004           1 :                 ipathkey = (PathKey *) lfirst(l2);
    4005           1 :                 ipeclass = ipathkey->pk_eclass;
    4006           1 :                 if (ieclass == ipeclass)
    4007           1 :                     break;
    4008             :             }
    4009           1 :             if (l2 == NULL)
    4010           0 :                 elog(ERROR, "inner pathkeys do not match mergeclauses");
    4011             :         }
    4012             : 
    4013             :         /* pathkeys should match each other too (more debugging) */
    4014         340 :         if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
    4015         340 :             opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation ||
    4016         340 :             opathkey->pk_strategy != ipathkey->pk_strategy ||
    4017         170 :             opathkey->pk_nulls_first != ipathkey->pk_nulls_first)
    4018           0 :             elog(ERROR, "left and right pathkeys do not match in mergejoin");
    4019             : 
    4020             :         /* OK, save info for executor */
    4021         170 :         mergefamilies[i] = opathkey->pk_opfamily;
    4022         170 :         mergecollations[i] = opathkey->pk_eclass->ec_collation;
    4023         170 :         mergestrategies[i] = opathkey->pk_strategy;
    4024         170 :         mergenullsfirst[i] = opathkey->pk_nulls_first;
    4025         170 :         i++;
    4026             :     }
    4027             : 
    4028             :     /*
    4029             :      * Note: it is not an error if we have additional pathkey elements (i.e.,
    4030             :      * lop or lip isn't NULL here).  The input paths might be better-sorted
    4031             :      * than we need for the current mergejoin.
    4032             :      */
    4033             : 
    4034             :     /*
    4035             :      * Now we can build the mergejoin node.
    4036             :      */
    4037         330 :     join_plan = make_mergejoin(tlist,
    4038             :                                joinclauses,
    4039             :                                otherclauses,
    4040             :                                mergeclauses,
    4041             :                                mergefamilies,
    4042             :                                mergecollations,
    4043             :                                mergestrategies,
    4044             :                                mergenullsfirst,
    4045             :                                outer_plan,
    4046             :                                inner_plan,
    4047             :                                best_path->jpath.jointype,
    4048         165 :                                best_path->jpath.inner_unique,
    4049         165 :                                best_path->skip_mark_restore);
    4050             : 
    4051             :     /* Costs of sort and material steps are included in path cost already */
    4052         165 :     copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
    4053             : 
    4054         165 :     return join_plan;
    4055             : }
    4056             : 
    4057             : static HashJoin *
    4058        1364 : create_hashjoin_plan(PlannerInfo *root,
    4059             :                      HashPath *best_path)
    4060             : {
    4061             :     HashJoin   *join_plan;
    4062             :     Hash       *hash_plan;
    4063             :     Plan       *outer_plan;
    4064             :     Plan       *inner_plan;
    4065        1364 :     List       *tlist = build_path_tlist(root, &best_path->jpath.path);
    4066             :     List       *joinclauses;
    4067             :     List       *otherclauses;
    4068             :     List       *hashclauses;
    4069        1364 :     Oid         skewTable = InvalidOid;
    4070        1364 :     AttrNumber  skewColumn = InvalidAttrNumber;
    4071        1364 :     bool        skewInherit = false;
    4072             : 
    4073             :     /*
    4074             :      * HashJoin can project, so we don't have to demand exact tlists from the
    4075             :      * inputs.  However, it's best to request a small tlist from the inner
    4076             :      * side, so that we aren't storing more data than necessary.  Likewise, if
    4077             :      * we anticipate batching, request a small tlist from the outer side so
    4078             :      * that we don't put extra data in the outer batch files.
    4079             :      */
    4080        1364 :     outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
    4081        1364 :                                      (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
    4082             : 
    4083        1364 :     inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
    4084             :                                      CP_SMALL_TLIST);
    4085             : 
    4086             :     /* Sort join qual clauses into best execution order */
    4087        1364 :     joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
    4088             :     /* There's no point in sorting the hash clauses ... */
    4089             : 
    4090             :     /* Get the join qual clauses (in plain expression form) */
    4091             :     /* Any pseudoconstant clauses are ignored here */
    4092        1364 :     if (IS_OUTER_JOIN(best_path->jpath.jointype))
    4093             :     {
    4094         440 :         extract_actual_join_clauses(joinclauses,
    4095             :                                     &joinclauses, &otherclauses);
    4096             :     }
    4097             :     else
    4098             :     {
    4099             :         /* We can treat all clauses alike for an inner join */
    4100         924 :         joinclauses = extract_actual_clauses(joinclauses, false);
    4101         924 :         otherclauses = NIL;
    4102             :     }
    4103             : 
    4104             :     /*
    4105             :      * Remove the hashclauses from the list of join qual clauses, leaving the
    4106             :      * list of quals that must be checked as qpquals.
    4107             :      */
    4108        1364 :     hashclauses = get_actual_clauses(best_path->path_hashclauses);
    4109        1364 :     joinclauses = list_difference(joinclauses, hashclauses);
    4110             : 
    4111             :     /*
    4112             :      * Replace any outer-relation variables with nestloop params.  There
    4113             :      * should not be any in the hashclauses.
    4114             :      */
    4115        1364 :     if (best_path->jpath.path.param_info)
    4116             :     {
    4117          12 :         joinclauses = (List *)
    4118          12 :             replace_nestloop_params(root, (Node *) joinclauses);
    4119          12 :         otherclauses = (List *)
    4120          12 :             replace_nestloop_params(root, (Node *) otherclauses);
    4121             :     }
    4122             : 
    4123             :     /*
    4124             :      * Rearrange hashclauses, if needed, so that the outer variable is always
    4125             :      * on the left.
    4126             :      */
    4127        1364 :     hashclauses = get_switched_clauses(best_path->path_hashclauses,
    4128        1364 :                                        best_path->jpath.outerjoinpath->parent->relids);
    4129             : 
    4130             :     /*
    4131             :      * If there is a single join clause and we can identify the outer variable
    4132             :      * as a simple column reference, supply its identity for possible use in
    4133             :      * skew optimization.  (Note: in principle we could do skew optimization
    4134             :      * with multiple join clauses, but we'd have to be able to determine the
    4135             :      * most common combinations of outer values, which we don't currently have
    4136             :      * enough stats for.)
    4137             :      */
    4138        1364 :     if (list_length(hashclauses) == 1)
    4139             :     {
    4140        1299 :         OpExpr     *clause = (OpExpr *) linitial(hashclauses);
    4141             :         Node       *node;
    4142             : 
    4143        1299 :         Assert(is_opclause(clause));
    4144        1299 :         node = (Node *) linitial(clause->args);
    4145        1299 :         if (IsA(node, RelabelType))
    4146          50 :             node = (Node *) ((RelabelType *) node)->arg;
    4147        1299 :         if (IsA(node, Var))
    4148             :         {
    4149        1279 :             Var        *var = (Var *) node;
    4150             :             RangeTblEntry *rte;
    4151             : 
    4152        1279 :             rte = root->simple_rte_array[var->varno];
    4153        1279 :             if (rte->rtekind == RTE_RELATION)
    4154             :             {
    4155        1238 :                 skewTable = rte->relid;
    4156        1238 :                 skewColumn = var->varattno;
    4157        1238 :                 skewInherit = rte->inh;
    4158             :             }
    4159             :         }
    4160             :     }
    4161             : 
    4162             :     /*
    4163             :      * Build the hash node and hash join node.
    4164             :      */
    4165        1364 :     hash_plan = make_hash(inner_plan,
    4166             :                           skewTable,
    4167             :                           skewColumn,
    4168             :                           skewInherit);
    4169             : 
    4170             :     /*
    4171             :      * Set Hash node's startup & total costs equal to total cost of input
    4172             :      * plan; this only affects EXPLAIN display not decisions.
    4173             :      */
    4174        1364 :     copy_plan_costsize(&hash_plan->plan, inner_plan);
    4175        1364 :     hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
    4176             : 
    4177        1364 :     join_plan = make_hashjoin(tlist,
    4178             :                               joinclauses,
    4179             :                               otherclauses,
    4180             :                               hashclauses,
    4181             :                               outer_plan,
    4182             :                               (Plan *) hash_plan,
    4183             :                               best_path->jpath.jointype,
    4184        1364 :                               best_path->jpath.inner_unique);
    4185             : 
    4186        1364 :     copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
    4187             : 
    4188        1364 :     return join_plan;
    4189             : }
    4190             : 
    4191             : 
    4192             : /*****************************************************************************
    4193             :  *
    4194             :  *  SUPPORTING ROUTINES
    4195             :  *
    4196             :  *****************************************************************************/
    4197             : 
    4198             : /*
    4199             :  * replace_nestloop_params
    4200             :  *    Replace outer-relation Vars and PlaceHolderVars in the given expression
    4201             :  *    with nestloop Params
    4202             :  *
    4203             :  * All Vars and PlaceHolderVars belonging to the relation(s) identified by
    4204             :  * root->curOuterRels are replaced by Params, and entries are added to
    4205             :  * root->curOuterParams if not already present.
    4206             :  */
    4207             : static Node *
    4208       11843 : replace_nestloop_params(PlannerInfo *root, Node *expr)
    4209             : {
    4210             :     /* No setup needed for tree walk, so away we go */
    4211       11843 :     return replace_nestloop_params_mutator(expr, root);
    4212             : }
    4213             : 
    4214             : static Node *
    4215       39596 : replace_nestloop_params_mutator(Node *node, PlannerInfo *root)
    4216             : {
    4217       39596 :     if (node == NULL)
    4218        1989 :         return NULL;
    4219       37607 :     if (IsA(node, Var))
    4220             :     {
    4221       12129 :         Var        *var = (Var *) node;
    4222             :         Param      *param;
    4223             :         NestLoopParam *nlp;
    4224             :         ListCell   *lc;
    4225             : 
    4226             :         /* Upper-level Vars should be long gone at this point */
    4227       12129 :         Assert(var->varlevelsup == 0);
    4228             :         /* If not to be replaced, we can just return the Var unmodified */
    4229       12129 :         if (!bms_is_member(var->varno, root->curOuterRels))
    4230       10094 :             return node;
    4231             :         /* Create a Param representing the Var */
    4232        2035 :         param = assign_nestloop_param_var(root, var);
    4233             :         /* Is this param already listed in root->curOuterParams? */
    4234        2268 :         foreach(lc, root->curOuterParams)
    4235             :         {
    4236        1227 :             nlp = (NestLoopParam *) lfirst(lc);
    4237        1227 :             if (nlp->paramno == param->paramid)
    4238             :             {
    4239         994 :                 Assert(equal(var, nlp->paramval));
    4240             :                 /* Present, so we can just return the Param */
    4241         994 :                 return (Node *) param;
    4242             :             }
    4243             :         }
    4244             :         /* No, so add it */
    4245        1041 :         nlp = makeNode(NestLoopParam);
    4246        1041 :         nlp->paramno = param->paramid;
    4247        1041 :         nlp->paramval = var;
    4248        1041 :         root->curOuterParams = lappend(root->curOuterParams, nlp);
    4249             :         /* And return the replacement Param */
    4250        1041 :         return (Node *) param;
    4251             :     }
    4252       25478 :     if (IsA(node, PlaceHolderVar))
    4253             :     {
    4254          35 :         PlaceHolderVar *phv = (PlaceHolderVar *) node;
    4255             :         Param      *param;
    4256             :         NestLoopParam *nlp;
    4257             :         ListCell   *lc;
    4258             : 
    4259             :         /* Upper-level PlaceHolderVars should be long gone at this point */
    4260          35 :         Assert(phv->phlevelsup == 0);
    4261             : 
    4262             :         /*
    4263             :          * Check whether we need to replace the PHV.  We use bms_overlap as a
    4264             :          * cheap/quick test to see if the PHV might be evaluated in the outer
    4265             :          * rels, and then grab its PlaceHolderInfo to tell for sure.
    4266             :          */
    4267          56 :         if (!bms_overlap(phv->phrels, root->curOuterRels) ||
    4268          21 :             !bms_is_subset(find_placeholder_info(root, phv, false)->ph_eval_at,
    4269          21 :                            root->curOuterRels))
    4270             :         {
    4271             :             /*
    4272             :              * We can't replace the whole PHV, but we might still need to
    4273             :              * replace Vars or PHVs within its expression, in case it ends up
    4274             :              * actually getting evaluated here.  (It might get evaluated in
    4275             :              * this plan node, or some child node; in the latter case we don't
    4276             :              * really need to process the expression here, but we haven't got
    4277             :              * enough info to tell if that's the case.)  Flat-copy the PHV
    4278             :              * node and then recurse on its expression.
    4279             :              *
    4280             :              * Note that after doing this, we might have different
    4281             :              * representations of the contents of the same PHV in different
    4282             :              * parts of the plan tree.  This is OK because equal() will just
    4283             :              * match on phid/phlevelsup, so setrefs.c will still recognize an
    4284             :              * upper-level reference to a lower-level copy of the same PHV.
    4285             :              */
    4286          18 :             PlaceHolderVar *newphv = makeNode(PlaceHolderVar);
    4287             : 
    4288          18 :             memcpy(newphv, phv, sizeof(PlaceHolderVar));
    4289          18 :             newphv->phexpr = (Expr *)
    4290          18 :                 replace_nestloop_params_mutator((Node *) phv->phexpr,
    4291             :                                                 root);
    4292          18 :             return (Node *) newphv;
    4293             :         }
    4294             :         /* Create a Param representing the PlaceHolderVar */
    4295          17 :         param = assign_nestloop_param_placeholdervar(root, phv);
    4296             :         /* Is this param already listed in root->curOuterParams? */
    4297          24 :         foreach(lc, root->curOuterParams)
    4298             :         {
    4299          14 :             nlp = (NestLoopParam *) lfirst(lc);
    4300          14 :             if (nlp->paramno == param->paramid)
    4301             :             {
    4302           7 :                 Assert(equal(phv, nlp->paramval));
    4303             :                 /* Present, so we can just return the Param */
    4304           7 :                 return (Node *) param;
    4305             :             }
    4306             :         }
    4307             :         /* No, so add it */
    4308          10 :         nlp = makeNode(NestLoopParam);
    4309          10 :         nlp->paramno = param->paramid;
    4310          10 :         nlp->paramval = (Var *) phv;
    4311          10 :         root->curOuterParams = lappend(root->curOuterParams, nlp);
    4312             :         /* And return the replacement Param */
    4313          10 :         return (Node *) param;
    4314             :     }
    4315       25443 :     return expression_tree_mutator(node,
    4316             :                                    replace_nestloop_params_mutator,
    4317             :                                    (void *) root);
    4318             : }
    4319             : 
    4320             : /*
    4321             :  * process_subquery_nestloop_params
    4322             :  *    Handle params of a parameterized subquery that need to be fed
    4323             :  *    from an outer nestloop.
    4324             :  *
    4325             :  * Currently, that would be *all* params that a subquery in FROM has demanded
    4326             :  * from the current query level, since they must be LATERAL references.
    4327             :  *
    4328             :  * The subplan's references to the outer variables are already represented
    4329             :  * as PARAM_EXEC Params, so we need not modify the subplan here.  What we
    4330             :  * do need to do is add entries to root->curOuterParams to signal the parent
    4331             :  * nestloop plan node that it must provide these values.
    4332             :  */
    4333             : static void
    4334          59 : process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
    4335             : {
    4336             :     ListCell   *ppl;
    4337             : 
    4338         120 :     foreach(ppl, subplan_params)
    4339             :     {
    4340          61 :         PlannerParamItem *pitem = (PlannerParamItem *) lfirst(ppl);
    4341             : 
    4342          61 :         if (IsA(pitem->item, Var))
    4343             :         {
    4344          56 :             Var        *var = (Var *) pitem->item;
    4345             :             NestLoopParam *nlp;
    4346             :             ListCell   *lc;
    4347             : 
    4348             :             /* If not from a nestloop outer rel, complain */
    4349          56 :             if (!bms_is_member(var->varno, root->curOuterRels))
    4350           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
    4351             :             /* Is this param already listed in root->curOuterParams? */
    4352          92 :             foreach(lc, root->curOuterParams)
    4353             :             {
    4354          36 :                 nlp = (NestLoopParam *) lfirst(lc);
    4355          36 :                 if (nlp->paramno == pitem->paramId)
    4356             :                 {
    4357           0 :                     Assert(equal(var, nlp->paramval));
    4358             :                     /* Present, so nothing to do */
    4359           0 :                     break;
    4360             :                 }
    4361             :             }
    4362          56 :             if (lc == NULL)
    4363             :             {
    4364             :                 /* No, so add it */
    4365          56 :                 nlp = makeNode(NestLoopParam);
    4366          56 :                 nlp->paramno = pitem->paramId;
    4367          56 :                 nlp->paramval = copyObject(var);
    4368          56 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
    4369             :             }
    4370             :         }
    4371           5 :         else if (IsA(pitem->item, PlaceHolderVar))
    4372             :         {
    4373           5 :             PlaceHolderVar *phv = (PlaceHolderVar *) pitem->item;
    4374             :             NestLoopParam *nlp;
    4375             :             ListCell   *lc;
    4376             : 
    4377             :             /* If not from a nestloop outer rel, complain */
    4378           5 :             if (!bms_is_subset(find_placeholder_info(root, phv, false)->ph_eval_at,
    4379           5 :                                root->curOuterRels))
    4380           0 :                 elog(ERROR, "non-LATERAL parameter required by subquery");
    4381             :             /* Is this param already listed in root->curOuterParams? */
    4382          21 :             foreach(lc, root->curOuterParams)
    4383             :             {
    4384          16 :                 nlp = (NestLoopParam *) lfirst(lc);
    4385          16 :                 if (nlp->paramno == pitem->paramId)
    4386             :                 {
    4387           0 :                     Assert(equal(phv, nlp->paramval));
    4388             :                     /* Present, so nothing to do */
    4389           0 :                     break;
    4390             :                 }
    4391             :             }
    4392           5 :             if (lc == NULL)
    4393             :             {
    4394             :                 /* No, so add it */
    4395           5 :                 nlp = makeNode(NestLoopParam);
    4396           5 :                 nlp->paramno = pitem->paramId;
    4397           5 :                 nlp->paramval = (Var *) copyObject(phv);
    4398           5 :                 root->curOuterParams = lappend(root->curOuterParams, nlp);
    4399             :             }
    4400             :         }
    4401             :         else
    4402           0 :             elog(ERROR, "unexpected type of subquery parameter");
    4403             :     }
    4404          59 : }
    4405             : 
    4406             : /*
    4407             :  * fix_indexqual_references
    4408             :  *    Adjust indexqual clauses to the form the executor's indexqual
    4409             :  *    machinery needs.
    4410             :  *
    4411             :  * We have four tasks here:
    4412             :  *  * Remove RestrictInfo nodes from the input clauses.
    4413             :  *  * Replace any outer-relation Var or PHV nodes with nestloop Params.
    4414             :  *    (XXX eventually, that responsibility should go elsewhere?)
    4415             :  *  * Index keys must be represented by Var nodes with varattno set to the
    4416             :  *    index's attribute number, not the attribute number in the original rel.
    4417             :  *  * If the index key is on the right, commute the clause to put it on the
    4418             :  *    left.
    4419             :  *
    4420             :  * The result is a modified copy of the path's indexquals list --- the
    4421             :  * original is not changed.  Note also that the copy shares no substructure
    4422             :  * with the original; this is needed in case there is a subplan in it (we need
    4423             :  * two separate copies of the subplan tree, or things will go awry).
    4424             :  */
    4425             : static List *
    4426        6123 : fix_indexqual_references(PlannerInfo *root, IndexPath *index_path)
    4427             : {
    4428        6123 :     IndexOptInfo *index = index_path->indexinfo;
    4429             :     List       *fixed_indexquals;
    4430             :     ListCell   *lcc,
    4431             :                *lci;
    4432             : 
    4433        6123 :     fixed_indexquals = NIL;
    4434             : 
    4435       13194 :     forboth(lcc, index_path->indexquals, lci, index_path->indexqualcols)
    4436             :     {
    4437        7071 :         RestrictInfo *rinfo = lfirst_node(RestrictInfo, lcc);
    4438        7071 :         int         indexcol = lfirst_int(lci);
    4439             :         Node       *clause;
    4440             : 
    4441             :         /*
    4442             :          * Replace any outer-relation variables with nestloop params.
    4443             :          *
    4444             :          * This also makes a copy of the clause, so it's safe to modify it
    4445             :          * in-place below.
    4446             :          */
    4447        7071 :         clause = replace_nestloop_params(root, (Node *) rinfo->clause);
    4448             : 
    4449        7071 :         if (IsA(clause, OpExpr))
    4450             :         {
    4451        6877 :             OpExpr     *op = (OpExpr *) clause;
    4452             : 
    4453        6877 :             if (list_length(op->args) != 2)
    4454           0 :                 elog(ERROR, "indexqual clause is not binary opclause");
    4455             : 
    4456             :             /*
    4457             :              * Check to see if the indexkey is on the right; if so, commute
    4458             :              * the clause.  The indexkey should be the side that refers to
    4459             :              * (only) the base relation.
    4460             :              */
    4461        6877 :             if (!bms_equal(rinfo->left_relids, index->rel->relids))
    4462         406 :                 CommuteOpExpr(op);
    4463             : 
    4464             :             /*
    4465             :              * Now replace the indexkey expression with an index Var.
    4466             :              */
    4467        6877 :             linitial(op->args) = fix_indexqual_operand(linitial(op->args),
    4468             :                                                        index,
    4469             :                                                        indexcol);
    4470             :         }
    4471         194 :         else if (IsA(clause, RowCompareExpr))
    4472             :         {
    4473           4 :             RowCompareExpr *rc = (RowCompareExpr *) clause;
    4474             :             Expr       *newrc;
    4475             :             List       *indexcolnos;
    4476             :             bool        var_on_left;
    4477             :             ListCell   *lca,
    4478             :                        *lcai;
    4479             : 
    4480             :             /*
    4481             :              * Re-discover which index columns are used in the rowcompare.
    4482             :              */
    4483           4 :             newrc = adjust_rowcompare_for_index(rc,
    4484             :                                                 index,
    4485             :                                                 indexcol,
    4486             :                                                 &indexcolnos,
    4487             :                                                 &var_on_left);
    4488             : 
    4489             :             /*
    4490             :              * Trouble if adjust_rowcompare_for_index thought the
    4491             :              * RowCompareExpr didn't match the index as-is; the clause should
    4492             :              * have gone through that routine already.
    4493             :              */
    4494           4 :             if (newrc != (Expr *) rc)
    4495           0 :                 elog(ERROR, "inconsistent results from adjust_rowcompare_for_index");
    4496             : 
    4497             :             /*
    4498             :              * Check to see if the indexkey is on the right; if so, commute
    4499             :              * the clause.
    4500             :              */
    4501           4 :             if (!var_on_left)
    4502           0 :                 CommuteRowCompareExpr(rc);
    4503             : 
    4504             :             /*
    4505             :              * Now replace the indexkey expressions with index Vars.
    4506             :              */
    4507           4 :             Assert(list_length(rc->largs) == list_length(indexcolnos));
    4508          12 :             forboth(lca, rc->largs, lcai, indexcolnos)
    4509             :             {
    4510           8 :                 lfirst(lca) = fix_indexqual_operand(lfirst(lca),
    4511             :                                                     index,
    4512             :                                                     lfirst_int(lcai));
    4513             :             }
    4514             :         }
    4515         190 :         else if (IsA(clause, ScalarArrayOpExpr))
    4516             :         {
    4517          35 :             ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
    4518             : 
    4519             :             /* Never need to commute... */
    4520             : 
    4521             :             /* Replace the indexkey expression with an index Var. */
    4522          35 :             linitial(saop->args) = fix_indexqual_operand(linitial(saop->args),
    4523             :                                                          index,
    4524             :                                                          indexcol);
    4525             :         }
    4526         155 :         else if (IsA(clause, NullTest))
    4527             :         {
    4528         155 :             NullTest   *nt = (NullTest *) clause;
    4529             : 
    4530             :             /* Replace the indexkey expression with an index Var. */
    4531         155 :             nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
    4532             :                                                      index,
    4533             :                                                      indexcol);
    4534             :         }
    4535             :         else
    4536           0 :             elog(ERROR, "unsupported indexqual type: %d",
    4537             :                  (int) nodeTag(clause));
    4538             : 
    4539        7071 :         fixed_indexquals = lappend(fixed_indexquals, clause);
    4540             :     }
    4541             : 
    4542        6123 :     return fixed_indexquals;
    4543             : }
    4544             : 
    4545             : /*
    4546             :  * fix_indexorderby_references
    4547             :  *    Adjust indexorderby clauses to the form the executor's index
    4548             :  *    machinery needs.
    4549             :  *
    4550             :  * This is a simplified version of fix_indexqual_references.  The input does
    4551             :  * not have RestrictInfo nodes, and we assume that indxpath.c already
    4552             :  * commuted the clauses to put the index keys on the left.  Also, we don't
    4553             :  * bother to support any cases except simple OpExprs, since nothing else
    4554             :  * is allowed for ordering operators.
    4555             :  */
    4556             : static List *
    4557        6123 : fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
    4558             : {
    4559        6123 :     IndexOptInfo *index = index_path->indexinfo;
    4560             :     List       *fixed_indexorderbys;
    4561             :     ListCell   *lcc,
    4562             :                *lci;
    4563             : 
    4564        6123 :     fixed_indexorderbys = NIL;
    4565             : 
    4566        6141 :     forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
    4567             :     {
    4568          18 :         Node       *clause = (Node *) lfirst(lcc);
    4569          18 :         int         indexcol = lfirst_int(lci);
    4570             : 
    4571             :         /*
    4572             :          * Replace any outer-relation variables with nestloop params.
    4573             :          *
    4574             :          * This also makes a copy of the clause, so it's safe to modify it
    4575             :          * in-place below.
    4576             :          */
    4577          18 :         clause = replace_nestloop_params(root, clause);
    4578             : 
    4579          18 :         if (IsA(clause, OpExpr))
    4580             :         {
    4581          18 :             OpExpr     *op = (OpExpr *) clause;
    4582             : 
    4583          18 :             if (list_length(op->args) != 2)
    4584           0 :                 elog(ERROR, "indexorderby clause is not binary opclause");
    4585             : 
    4586             :             /*
    4587             :              * Now replace the indexkey expression with an index Var.
    4588             :              */
    4589          18 :             linitial(op->args) = fix_indexqual_operand(linitial(op->args),
    4590             :                                                        index,
    4591             :                                                        indexcol);
    4592             :         }
    4593             :         else
    4594           0 :             elog(ERROR, "unsupported indexorderby type: %d",
    4595             :                  (int) nodeTag(clause));
    4596             : 
    4597          18 :         fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
    4598             :     }
    4599             : 
    4600        6123 :     return fixed_indexorderbys;
    4601             : }
    4602             : 
    4603             : /*
    4604             :  * fix_indexqual_operand
    4605             :  *    Convert an indexqual expression to a Var referencing the index column.
    4606             :  *
    4607             :  * We represent index keys by Var nodes having varno == INDEX_VAR and varattno
    4608             :  * equal to the index's attribute number (index column position).
    4609             :  *
    4610             :  * Most of the code here is just for sanity cross-checking that the given
    4611             :  * expression actually matches the index column it's claimed to.
    4612             :  */
    4613             : static Node *
    4614        7093 : fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
    4615             : {
    4616             :     Var        *result;
    4617             :     int         pos;
    4618             :     ListCell   *indexpr_item;
    4619             : 
    4620             :     /*
    4621             :      * Remove any binary-compatible relabeling of the indexkey
    4622             :      */
    4623        7093 :     if (IsA(node, RelabelType))
    4624          62 :         node = (Node *) ((RelabelType *) node)->arg;
    4625             : 
    4626        7093 :     Assert(indexcol >= 0 && indexcol < index->ncolumns);
    4627             : 
    4628        7093 :     if (index->indexkeys[indexcol] != 0)
    4629             :     {
    4630             :         /* It's a simple index column */
    4631       14128 :         if (IsA(node, Var) &&
    4632       14128 :             ((Var *) node)->varno == index->rel->relid &&
    4633        7064 :             ((Var *) node)->varattno == index->indexkeys[indexcol])
    4634             :         {
    4635        7064 :             result = (Var *) copyObject(node);
    4636        7064 :             result->varno = INDEX_VAR;
    4637        7064 :             result->varattno = indexcol + 1;
    4638        7064 :             return (Node *) result;
    4639             :         }
    4640             :         else
    4641           0 :             elog(ERROR, "index key does not match expected index column");
    4642             :     }
    4643             : 
    4644             :     /* It's an index expression, so find and cross-check the expression */
    4645          29 :     indexpr_item = list_head(index->indexprs);
    4646          29 :     for (pos = 0; pos < index->ncolumns; pos++)
    4647             :     {
    4648          29 :         if (index->indexkeys[pos] == 0)
    4649             :         {
    4650          29 :             if (indexpr_item == NULL)
    4651           0 :                 elog(ERROR, "too few entries in indexprs list");
    4652          29 :             if (pos == indexcol)
    4653             :             {
    4654             :                 Node       *indexkey;
    4655             : 
    4656          29 :                 indexkey = (Node *) lfirst(indexpr_item);
    4657          29 :                 if (indexkey && IsA(indexkey, RelabelType))
    4658           0 :                     indexkey = (Node *) ((RelabelType *) indexkey)->arg;
    4659          29 :                 if (equal(node, indexkey))
    4660             :                 {
    4661          58 :                     result = makeVar(INDEX_VAR, indexcol + 1,
    4662          29 :                                      exprType(lfirst(indexpr_item)), -1,
    4663          29 :                                      exprCollation(lfirst(indexpr_item)),
    4664             :                                      0);
    4665          29 :                     return (Node *) result;
    4666             :                 }
    4667             :                 else
    4668           0 :                     elog(ERROR, "index key does not match expected index column");
    4669             :             }
    4670           0 :             indexpr_item = lnext(indexpr_item);
    4671             :         }
    4672             :     }
    4673             : 
    4674             :     /* Oops... */
    4675           0 :     elog(ERROR, "index key does not match expected index column");
    4676             :     return NULL;                /* keep compiler quiet */
    4677             : }
    4678             : 
    4679             : /*
    4680             :  * get_switched_clauses
    4681             :  *    Given a list of merge or hash joinclauses (as RestrictInfo nodes),
    4682             :  *    extract the bare clauses, and rearrange the elements within the
    4683             :  *    clauses, if needed, so the outer join variable is on the left and
    4684             :  *    the inner is on the right.  The original clause data structure is not
    4685             :  *    touched; a modified list is returned.  We do, however, set the transient
    4686             :  *    outer_is_left field in each RestrictInfo to show which side was which.
    4687             :  */
    4688             : static List *
    4689        1529 : get_switched_clauses(List *clauses, Relids outerrelids)
    4690             : {
    4691        1529 :     List       *t_list = NIL;
    4692             :     ListCell   *l;
    4693             : 
    4694        3138 :     foreach(l, clauses)
    4695             :     {
    4696        1609 :         RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
    4697        1609 :         OpExpr     *clause = (OpExpr *) restrictinfo->clause;
    4698             : 
    4699        1609 :         Assert(is_opclause(clause));
    4700        1609 :         if (bms_is_subset(restrictinfo->right_relids, outerrelids))
    4701             :         {
    4702             :             /*
    4703             :              * Duplicate just enough of the structure to allow commuting the
    4704             :              * clause without changing the original list.  Could use
    4705             :              * copyObject, but a complete deep copy is overkill.
    4706             :              */
    4707         610 :             OpExpr     *temp = makeNode(OpExpr);
    4708             : 
    4709         610 :             temp->opno = clause->opno;
    4710         610 :             temp->opfuncid = InvalidOid;
    4711         610 :             temp->opresulttype = clause->opresulttype;
    4712         610 :             temp->opretset = clause->opretset;
    4713         610 :             temp->opcollid = clause->opcollid;
    4714         610 :             temp->inputcollid = clause->inputcollid;
    4715         610 :             temp->args = list_copy(clause->args);
    4716         610 :             temp->location = clause->location;
    4717             :             /* Commute it --- note this modifies the temp node in-place. */
    4718         610 :             CommuteOpExpr(temp);
    4719         610 :             t_list = lappend(t_list, temp);
    4720         610 :             restrictinfo->outer_is_left = false;
    4721             :         }
    4722             :         else
    4723             :         {
    4724         999 :             Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
    4725         999 :             t_list = lappend(t_list, clause);
    4726         999 :             restrictinfo->outer_is_left = true;
    4727             :         }
    4728             :     }
    4729        1529 :     return t_list;
    4730             : }
    4731             : 
    4732             : /*
    4733             :  * order_qual_clauses
    4734             :  *      Given a list of qual clauses that will all be evaluated at the same
    4735             :  *      plan node, sort the list into the order we want to check the quals
    4736             :  *      in at runtime.
    4737             :  *
    4738             :  * When security barrier quals are used in the query, we may have quals with
    4739             :  * different security levels in the list.  Quals of lower security_level
    4740             :  * must go before quals of higher security_level, except that we can grant
    4741             :  * exceptions to move up quals that are leakproof.  When security level
    4742             :  * doesn't force the decision, we prefer to order clauses by estimated
    4743             :  * execution cost, cheapest first.
    4744             :  *
    4745             :  * Ideally the order should be driven by a combination of execution cost and
    4746             :  * selectivity, but it's not immediately clear how to account for both,
    4747             :  * and given the uncertainty of the estimates the reliability of the decisions
    4748             :  * would be doubtful anyway.  So we just order by security level then
    4749             :  * estimated per-tuple cost, being careful not to change the order when
    4750             :  * (as is often the case) the estimates are identical.
    4751             :  *
    4752             :  * Although this will work on either bare clauses or RestrictInfos, it's
    4753             :  * much faster to apply it to RestrictInfos, since it can re-use cost
    4754             :  * information that is cached in RestrictInfos.  XXX in the bare-clause
    4755             :  * case, we are also not able to apply security considerations.  That is
    4756             :  * all right for the moment, because the bare-clause case doesn't occur
    4757             :  * anywhere that barrier quals could be present, but it would be better to
    4758             :  * get rid of it.
    4759             :  *
    4760             :  * Note: some callers pass lists that contain entries that will later be
    4761             :  * removed; this is the easiest way to let this routine see RestrictInfos
    4762             :  * instead of bare clauses.  This is another reason why trying to consider
    4763             :  * selectivity in the ordering would likely do the wrong thing.
    4764             :  */
    4765             : static List *
    4766       38182 : order_qual_clauses(PlannerInfo *root, List *clauses)
    4767             : {
    4768             :     typedef struct
    4769             :     {
    4770             :         Node       *clause;
    4771             :         Cost        cost;
    4772             :         Index       security_level;
    4773             :     } QualItem;
    4774       38182 :     int         nitems = list_length(clauses);
    4775             :     QualItem   *items;
    4776             :     ListCell   *lc;
    4777             :     int         i;
    4778             :     List       *result;
    4779             : 
    4780             :     /* No need to work hard for 0 or 1 clause */
    4781       38182 :     if (nitems <= 1)
    4782       36071 :         return clauses;
    4783             : 
    4784             :     /*
    4785             :      * Collect the items and costs into an array.  This is to avoid repeated
    4786             :      * cost_qual_eval work if the inputs aren't RestrictInfos.
    4787             :      */
    4788        2111 :     items = (QualItem *) palloc(nitems * sizeof(QualItem));
    4789        2111 :     i = 0;
    4790        7090 :     foreach(lc, clauses)
    4791             :     {
    4792        4979 :         Node       *clause = (Node *) lfirst(lc);
    4793             :         QualCost    qcost;
    4794             : 
    4795        4979 :         cost_qual_eval_node(&qcost, clause, root);
    4796        4979 :         items[i].clause = clause;
    4797        4979 :         items[i].cost = qcost.per_tuple;
    4798        4979 :         if (IsA(clause, RestrictInfo))
    4799             :         {
    4800        4979 :             RestrictInfo *rinfo = (RestrictInfo *) clause;
    4801             : 
    4802             :             /*
    4803             :              * If a clause is leakproof, it doesn't have to be constrained by
    4804             :              * its nominal security level.  If it's also reasonably cheap
    4805             :              * (here defined as 10X cpu_operator_cost), pretend it has
    4806             :              * security_level 0, which will allow it to go in front of
    4807             :              * more-expensive quals of lower security levels.  Of course, that
    4808             :              * will also force it to go in front of cheaper quals of its own
    4809             :              * security level, which is not so great, but we can alleviate
    4810             :              * that risk by applying the cost limit cutoff.
    4811             :              */
    4812        4979 :             if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
    4813         142 :                 items[i].security_level = 0;
    4814             :             else
    4815        4837 :                 items[i].security_level = rinfo->security_level;
    4816             :         }
    4817             :         else
    4818           0 :             items[i].security_level = 0;
    4819        4979 :         i++;
    4820             :     }
    4821             : 
    4822             :     /*
    4823             :      * Sort.  We don't use qsort() because it's not guaranteed stable for
    4824             :      * equal keys.  The expected number of entries is small enough that a
    4825             :      * simple insertion sort should be good enough.
    4826             :      */
    4827        4979 :     for (i = 1; i < nitems; i++)
    4828             :     {
    4829        2868 :         QualItem    newitem = items[i];
    4830             :         int         j;
    4831             : 
    4832             :         /* insert newitem into the already-sorted subarray */
    4833        3544 :         for (j = i; j > 0; j--)
    4834             :         {
    4835        3076 :             QualItem   *olditem = &items[j - 1];
    4836             : 
    4837        6067 :             if (newitem.security_level > olditem->security_level ||
    4838        5735 :                 (newitem.security_level == olditem->security_level &&
    4839        2744 :                  newitem.cost >= olditem->cost))
    4840             :                 break;
    4841         676 :             items[j] = *olditem;
    4842             :         }
    4843        2868 :         items[j] = newitem;
    4844             :     }
    4845             : 
    4846             :     /* Convert back to a list */
    4847        2111 :     result = NIL;
    4848        7090 :     for (i = 0; i < nitems; i++)
    4849        4979 :         result = lappend(result, items[i].clause);
    4850             : 
    4851        2111 :     return result;
    4852             : }
    4853             : 
    4854             : /*
    4855             :  * Copy cost and size info from a Path node to the Plan node created from it.
    4856             :  * The executor usually won't use this info, but it's needed by EXPLAIN.
    4857             :  * Also copy the parallel-related flags, which the executor *will* use.
    4858             :  */
    4859             : static void
    4860       46647 : copy_generic_path_info(Plan *dest, Path *src)
    4861             : {
    4862       46647 :     dest->startup_cost = src->startup_cost;
    4863       46647 :     dest->total_cost = src->total_cost;
    4864       46647 :     dest->plan_rows = src->rows;
    4865       46647 :     dest->plan_width = src->pathtarget->width;
    4866       46647 :     dest->parallel_aware = src->parallel_aware;
    4867       46647 :     dest->parallel_safe = src->parallel_safe;
    4868       46647 : }
    4869             : 
    4870             : /*
    4871             :  * Copy cost and size info from a lower plan node to an inserted node.
    4872             :  * (Most callers alter the info after copying it.)
    4873             :  */
    4874             : static void
    4875        1824 : copy_plan_costsize(Plan *dest, Plan *src)
    4876             : {
    4877        1824 :     dest->startup_cost = src->startup_cost;
    4878        1824 :     dest->total_cost = src->total_cost;
    4879        1824 :     dest->plan_rows = src->plan_rows;
    4880        1824 :     dest->plan_width = src->plan_width;
    4881             :     /* Assume the inserted node is not parallel-aware. */
    4882        1824 :     dest->parallel_aware = false;
    4883             :     /* Assume the inserted node is parallel-safe, if child plan is. */
    4884        1824 :     dest->parallel_safe = src->parallel_safe;
    4885        1824 : }
    4886             : 
    4887             : /*
    4888             :  * Some places in this file build Sort nodes that don't have a directly
    4889             :  * corresponding Path node.  The cost of the sort is, or should have been,
    4890             :  * included in the cost of the Path node we're working from, but since it's
    4891             :  * not split out, we have to re-figure it using cost_sort().  This is just
    4892             :  * to label the Sort node nicely for EXPLAIN.
    4893             :  *
    4894             :  * limit_tuples is as for cost_sort (in particular, pass -1 if no limit)
    4895             :  */
    4896             : static void
    4897         280 : label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
    4898             : {
    4899         280 :     Plan       *lefttree = plan->plan.lefttree;
    4900             :     Path        sort_path;      /* dummy for result of cost_sort */
    4901             : 
    4902         280 :     cost_sort(&sort_path, root, NIL,
    4903             :               lefttree->total_cost,
    4904             :               lefttree->plan_rows,
    4905             :               lefttree->plan_width,
    4906             :               0.0,
    4907             :               work_mem,
    4908             :               limit_tuples);
    4909         280 :     plan->plan.startup_cost = sort_path.startup_cost;
    4910         280 :     plan->plan.total_cost = sort_path.total_cost;
    4911         280 :     plan->plan.plan_rows = lefttree->plan_rows;
    4912         280 :     plan->plan.plan_width = lefttree->plan_width;
    4913         280 :     plan->plan.parallel_aware = false;
    4914         280 :     plan->plan.parallel_safe = lefttree->parallel_safe;
    4915         280 : }
    4916             : 
    4917             : /*
    4918             :  * bitmap_subplan_mark_shared
    4919             :  *   Set isshared flag in bitmap subplan so that it will be created in
    4920             :  *   shared memory.
    4921             :  */
    4922             : static void
    4923           3 : bitmap_subplan_mark_shared(Plan *plan)
    4924             : {
    4925           3 :     if (IsA(plan, BitmapAnd))
    4926           0 :         bitmap_subplan_mark_shared(
    4927           0 :                                    linitial(((BitmapAnd *) plan)->bitmapplans));
    4928           3 :     else if (IsA(plan, BitmapOr))
    4929           0 :         ((BitmapOr *) plan)->isshared = true;
    4930           3 :     else if (IsA(plan, BitmapIndexScan))
    4931           3 :         ((BitmapIndexScan *) plan)->isshared = true;
    4932             :     else
    4933           0 :         elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
    4934           3 : }
    4935             : 
    4936             : /*****************************************************************************
    4937             :  *
    4938             :  *  PLAN NODE BUILDING ROUTINES
    4939             :  *
    4940             :  * In general, these functions are not passed the original Path and therefore
    4941             :  * leave it to the caller to fill in the cost/width fields from the Path,
    4942             :  * typically by calling copy_generic_path_info().  This convention is
    4943             :  * somewhat historical, but it does support a few places above where we build
    4944             :  * a plan node without having an exactly corresponding Path node.  Under no
    4945             :  * circumstances should one of these functions do its own cost calculations,
    4946             :  * as that would be redundant with calculations done while building Paths.
    4947             :  *
    4948             :  *****************************************************************************/
    4949             : 
    4950             : static SeqScan *
    4951        9154 : make_seqscan(List *qptlist,
    4952             :              List *qpqual,
    4953             :              Index scanrelid)
    4954             : {
    4955        9154 :     SeqScan    *node = makeNode(SeqScan);
    4956        9154 :     Plan       *plan = &node->plan;
    4957             : 
    4958        9154 :     plan->targetlist = qptlist;
    4959        9154 :     plan->qual = qpqual;
    4960        9154 :     plan->lefttree = NULL;
    4961        9154 :     plan->righttree = NULL;
    4962        9154 :     node->scanrelid = scanrelid;
    4963             : 
    4964        9154 :     return node;
    4965             : }
    4966             : 
    4967             : static SampleScan *
    4968          36 : make_samplescan(List *qptlist,
    4969             :                 List *qpqual,
    4970             :                 Index scanrelid,
    4971             :                 TableSampleClause *tsc)
    4972             : {
    4973          36 :     SampleScan *node = makeNode(SampleScan);
    4974          36 :     Plan       *plan = &node->scan.plan;
    4975             : 
    4976          36 :     plan->targetlist = qptlist;
    4977          36 :     plan->qual = qpqual;
    4978          36 :     plan->lefttree = NULL;
    4979          36 :     plan->righttree = NULL;
    4980          36 :     node->scan.scanrelid = scanrelid;
    4981          36 :     node->tablesample = tsc;
    4982             : 
    4983          36 :     return node;
    4984             : }
    4985             : 
    4986             : static IndexScan *
    4987        5464 : make_indexscan(List *qptlist,
    4988             :                List *qpqual,
    4989             :                Index scanrelid,
    4990             :                Oid indexid,
    4991             :                List *indexqual,
    4992             :                List *indexqualorig,
    4993             :                List *indexorderby,
    4994             :                List *indexorderbyorig,
    4995             :                List *indexorderbyops,
    4996             :                ScanDirection indexscandir)
    4997             : {
    4998        5464 :     IndexScan  *node = makeNode(IndexScan);
    4999        5464 :     Plan       *plan = &node->scan.plan;
    5000             : 
    5001        5464 :     plan->targetlist = qptlist;
    5002        5464 :     plan->qual = qpqual;
    5003        5464 :     plan->lefttree = NULL;
    5004        5464 :     plan->righttree = NULL;
    5005        5464 :     node->scan.scanrelid = scanrelid;
    5006        5464 :     node->indexid = indexid;
    5007        5464 :     node->indexqual = indexqual;
    5008        5464 :     node->indexqualorig = indexqualorig;
    5009        5464 :     node->indexorderby = indexorderby;
    5010        5464 :     node->indexorderbyorig = indexorderbyorig;
    5011        5464 :     node->indexorderbyops = indexorderbyops;
    5012        5464 :     node->indexorderdir = indexscandir;
    5013             : 
    5014        5464 :     return node;
    5015             : }
    5016             : 
    5017             : static IndexOnlyScan *
    5018         659 : make_indexonlyscan(List *qptlist,
    5019             :                    List *qpqual,
    5020             :                    Index scanrelid,
    5021             :                    Oid indexid,
    5022             :                    List *indexqual,
    5023             :                    List *indexorderby,
    5024             :                    List *indextlist,
    5025             :                    ScanDirection indexscandir)
    5026             : {
    5027         659 :     IndexOnlyScan *node = makeNode(IndexOnlyScan);
    5028         659 :     Plan       *plan = &node->scan.plan;
    5029             : 
    5030         659 :     plan->targetlist = qptlist;
    5031         659 :     plan->qual = qpqual;
    5032         659 :     plan->lefttree = NULL;
    5033         659 :     plan->righttree = NULL;
    5034         659 :     node->scan.scanrelid = scanrelid;
    5035         659 :     node->indexid = indexid;
    5036         659 :     node->indexqual = indexqual;
    5037         659 :     node->indexorderby = indexorderby;
    5038         659 :     node->indextlist = indextlist;
    5039         659 :     node->indexorderdir = indexscandir;
    5040             : 
    5041         659 :     return node;
    5042             : }
    5043             : 
    5044             : static BitmapIndexScan *
    5045        1612 : make_bitmap_indexscan(Index scanrelid,
    5046             :                       Oid indexid,
    5047             :                       List *indexqual,
    5048             :                       List *indexqualorig)
    5049             : {
    5050        1612 :     BitmapIndexScan *node = makeNode(BitmapIndexScan);
    5051        1612 :     Plan       *plan = &node->scan.plan;
    5052             : 
    5053        1612 :     plan->targetlist = NIL;      /* not used */
    5054        1612 :     plan->qual = NIL;            /* not used */
    5055        1612 :     plan->lefttree = NULL;
    5056        1612 :     plan->righttree = NULL;
    5057        1612 :     node->scan.scanrelid = scanrelid;
    5058        1612 :     node->indexid = indexid;
    5059        1612 :     node->indexqual = indexqual;
    5060        1612 :     node->indexqualorig = indexqualorig;
    5061             : 
    5062        1612 :     return node;
    5063             : }
    5064             : 
    5065             : static BitmapHeapScan *
    5066        1587 : make_bitmap_heapscan(List *qptlist,
    5067             :                      List *qpqual,
    5068             :                      Plan *lefttree,
    5069             :                      List *bitmapqualorig,
    5070             :                      Index scanrelid)
    5071             : {
    5072        1587 :     BitmapHeapScan *node = makeNode(BitmapHeapScan);
    5073        1587 :     Plan       *plan = &node->scan.plan;
    5074             : 
    5075        1587 :     plan->targetlist = qptlist;
    5076        1587 :     plan->qual = qpqual;
    5077        1587 :     plan->lefttree = lefttree;
    5078        1587 :     plan->righttree = NULL;
    5079        1587 :     node->scan.scanrelid = scanrelid;
    5080        1587 :     node->bitmapqualorig = bitmapqualorig;
    5081             : 
    5082        1587 :     return node;
    5083             : }
    5084             : 
    5085             : static TidScan *
    5086          66 : make_tidscan(List *qptlist,
    5087             :              List *qpqual,
    5088             :              Index scanrelid,
    5089             :              List *tidquals)
    5090             : {
    5091          66 :     TidScan    *node = makeNode(TidScan);
    5092          66 :     Plan       *plan = &node->scan.plan;
    5093             : 
    5094          66 :     plan->targetlist = qptlist;
    5095          66 :     plan->qual = qpqual;
    5096          66 :     plan->lefttree = NULL;
    5097          66 :     plan->righttree = NULL;
    5098          66 :     node->scan.scanrelid = scanrelid;
    5099          66 :     node->tidquals = tidquals;
    5100             : 
    5101          66 :     return node;
    5102             : }
    5103             : 
    5104             : static SubqueryScan *
    5105        1059 : make_subqueryscan(List *qptlist,
    5106             :                   List *qpqual,
    5107             :                   Index scanrelid,
    5108             :                   Plan *subplan)
    5109             : {
    5110        1059 :     SubqueryScan *node = makeNode(SubqueryScan);
    5111        1059 :     Plan       *plan = &node->scan.plan;
    5112             : 
    5113        1059 :     plan->targetlist = qptlist;
    5114        1059 :     plan->qual = qpqual;
    5115        1059 :     plan->lefttree = NULL;
    5116        1059 :     plan->righttree = NULL;
    5117        1059 :     node->scan.scanrelid = scanrelid;
    5118        1059 :     node->subplan = subplan;
    5119             : 
    5120        1059 :     return node;
    5121             : }
    5122             : 
    5123             : static FunctionScan *
    5124        1327 : make_functionscan(List *qptlist,
    5125             :                   List *qpqual,
    5126             :                   Index scanrelid,
    5127             :                   List *functions,
    5128             :                   bool funcordinality)
    5129             : {
    5130        1327 :     FunctionScan *node = makeNode(FunctionScan);
    5131        1327 :     Plan       *plan = &node->scan.plan;
    5132             : 
    5133        1327 :     plan->targetlist = qptlist;
    5134        1327 :     plan->qual = qpqual;
    5135        1327 :     plan->lefttree = NULL;
    5136        1327 :     plan->righttree = NULL;
    5137        1327 :     node->scan.scanrelid = scanrelid;
    5138        1327 :     node->functions = functions;
    5139        1327 :     node->funcordinality = funcordinality;
    5140             : 
    5141        1327 :     return node;
    5142             : }
    5143             : 
    5144             : static TableFuncScan *
    5145          22 : make_tablefuncscan(List *qptlist,
    5146             :                    List *qpqual,
    5147             :                    Index scanrelid,
    5148             :                    TableFunc *tablefunc)
    5149             : {
    5150          22 :     TableFuncScan *node = makeNode(TableFuncScan);
    5151          22 :     Plan       *plan = &node->scan.plan;
    5152             : 
    5153          22 :     plan->targetlist = qptlist;
    5154          22 :     plan->qual = qpqual;
    5155          22 :     plan->lefttree = NULL;
    5156          22 :     plan->righttree = NULL;
    5157          22 :     node->scan.scanrelid = scanrelid;
    5158          22 :     node->tablefunc = tablefunc;
    5159             : 
    5160          22 :     return node;
    5161             : }
    5162             : 
    5163             : static ValuesScan *
    5164         463 : make_valuesscan(List *qptlist,
    5165             :                 List *qpqual,
    5166             :                 Index scanrelid,
    5167             :                 List *values_lists)
    5168             : {
    5169         463 :     ValuesScan *node = makeNode(ValuesScan);
    5170         463 :     Plan       *plan = &node->scan.plan;
    5171             : 
    5172         463 :     plan->targetlist = qptlist;
    5173         463 :     plan->qual = qpqual;
    5174         463 :     plan->lefttree = NULL;
    5175         463 :     plan->righttree = NULL;
    5176         463 :     node->scan.scanrelid = scanrelid;
    5177         463 :     node->values_lists = values_lists;
    5178             : 
    5179         463 :     return node;
    5180             : }
    5181             : 
    5182             : static CteScan *
    5183         162 : make_ctescan(List *qptlist,
    5184             :              List *qpqual,
    5185             :              Index scanrelid,
    5186             :              int ctePlanId,
    5187             :              int cteParam)
    5188             : {
    5189         162 :     CteScan    *node = makeNode(CteScan);
    5190         162 :     Plan       *plan = &node->scan.plan;
    5191             : 
    5192         162 :     plan->targetlist = qptlist;
    5193         162 :     plan->qual = qpqual;
    5194         162 :     plan->lefttree = NULL;
    5195         162 :     plan->righttree = NULL;
    5196         162 :     node->scan.scanrelid = scanrelid;
    5197         162 :     node->ctePlanId = ctePlanId;
    5198         162 :     node->cteParam = cteParam;
    5199             : 
    5200         162 :     return node;
    5201             : }
    5202             : 
    5203             : static NamedTuplestoreScan *
    5204          43 : make_namedtuplestorescan(List *qptlist,
    5205             :                          List *qpqual,
    5206             :                          Index scanrelid,
    5207             :                          char *enrname)
    5208             : {
    5209          43 :     NamedTuplestoreScan *node = makeNode(NamedTuplestoreScan);
    5210          43 :     Plan       *plan = &node->scan.plan;
    5211             : 
    5212             :     /* cost should be inserted by caller */
    5213          43 :     plan->targetlist = qptlist;
    5214          43 :     plan->qual = qpqual;
    5215          43 :     plan->lefttree = NULL;
    5216          43 :     plan->righttree = NULL;
    5217          43 :     node->scan.scanrelid = scanrelid;
    5218          43 :     node->enrname = enrname;
    5219             : 
    5220          43 :     return node;
    5221             : }
    5222             : 
    5223             : static WorkTableScan *
    5224          40 : make_worktablescan(List *qptlist,
    5225             :                    List *qpqual,
    5226             :                    Index scanrelid,
    5227             :                    int wtParam)
    5228             : {
    5229          40 :     WorkTableScan *node = makeNode(WorkTableScan);
    5230          40 :     Plan       *plan = &node->scan.plan;
    5231             : 
    5232          40 :     plan->targetlist = qptlist;
    5233          40 :     plan->qual = qpqual;
    5234          40 :     plan->lefttree = NULL;
    5235          40 :     plan->righttree = NULL;
    5236          40 :     node->scan.scanrelid = scanrelid;
    5237          40 :     node->wtParam = wtParam;
    5238             : 
    5239          40 :     return node;
    5240             : }
    5241             : 
    5242             : ForeignScan *
    5243           0 : make_foreignscan(List *qptlist,
    5244             :                  List *qpqual,
    5245             :                  Index scanrelid,
    5246             :                  List *fdw_exprs,
    5247             :                  List *fdw_private,
    5248             :                  List *fdw_scan_tlist,
    5249             :                  List *fdw_recheck_quals,
    5250             :                  Plan *outer_plan)
    5251             : {
    5252           0 :     ForeignScan *node = makeNode(ForeignScan);
    5253           0 :     Plan       *plan = &node->scan.plan;
    5254             : 
    5255             :     /* cost will be filled in by create_foreignscan_plan */
    5256           0 :     plan->targetlist = qptlist;
    5257           0 :     plan->qual = qpqual;
    5258           0 :     plan->lefttree = outer_plan;
    5259           0 :     plan->righttree = NULL;
    5260           0 :     node->scan.scanrelid = scanrelid;
    5261           0 :     node->operation = CMD_SELECT;
    5262             :     /* fs_server will be filled in by create_foreignscan_plan */
    5263           0 :     node->fs_server = InvalidOid;
    5264           0 :     node->fdw_exprs = fdw_exprs;
    5265           0 :     node->fdw_private = fdw_private;
    5266           0 :     node->fdw_scan_tlist = fdw_scan_tlist;
    5267           0 :     node->fdw_recheck_quals = fdw_recheck_quals;
    5268             :     /* fs_relids will be filled in by create_foreignscan_plan */
    5269           0 :     node->fs_relids = NULL;
    5270             :     /* fsSystemCol will be filled in by create_foreignscan_plan */
    5271           0 :     node->fsSystemCol = false;
    5272             : 
    5273           0 :     return node;
    5274             : }
    5275             : 
    5276             : static Append *
    5277         601 : make_append(List *appendplans, List *tlist, List *partitioned_rels)
    5278             : {
    5279         601 :     Append     *node = makeNode(Append);
    5280         601 :     Plan       *plan = &node->plan;
    5281             : 
    5282         601 :     plan->targetlist = tlist;
    5283         601 :     plan->qual = NIL;
    5284         601 :     plan->lefttree = NULL;
    5285         601 :     plan->righttree = NULL;
    5286         601 :     node->partitioned_rels = partitioned_rels;
    5287         601 :     node->appendplans = appendplans;
    5288             : 
    5289         601 :     return node;
    5290             : }
    5291             : 
    5292             : static RecursiveUnion *
    5293          40 : make_recursive_union(List *tlist,
    5294             :                      Plan *lefttree,
    5295             :                      Plan *righttree,
    5296             :                      int wtParam,
    5297             :                      List *distinctList,
    5298             :                      long numGroups)
    5299             : {
    5300          40 :     RecursiveUnion *node = makeNode(RecursiveUnion);
    5301          40 :     Plan       *plan = &node->plan;
    5302          40 :     int         numCols = list_length(distinctList);
    5303             : 
    5304          40 :     plan->targetlist = tlist;
    5305          40 :     plan->qual = NIL;
    5306          40 :     plan->lefttree = lefttree;
    5307          40 :     plan->righttree = righttree;
    5308          40 :     node->wtParam = wtParam;
    5309             : 
    5310             :     /*
    5311             :      * convert SortGroupClause list into arrays of attr indexes and equality
    5312             :      * operators, as wanted by executor
    5313             :      */
    5314          40 :     node->numCols = numCols;
    5315          40 :     if (numCols > 0)
    5316             :     {
    5317           4 :         int         keyno = 0;
    5318             :         AttrNumber *dupColIdx;
    5319             :         Oid        *dupOperators;
    5320             :         ListCell   *slitem;
    5321             : 
    5322           4 :         dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
    5323           4 :         dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
    5324             : 
    5325          10 :         foreach(slitem, distinctList)
    5326             :         {
    5327           6 :             SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
    5328           6 :             TargetEntry *tle = get_sortgroupclause_tle(sortcl,
    5329             :                                                        plan->targetlist);
    5330             : 
    5331           6 :             dupColIdx[keyno] = tle->resno;
    5332           6 :             dupOperators[keyno] = sortcl->eqop;
    5333           6 :             Assert(OidIsValid(dupOperators[keyno]));
    5334           6 :             keyno++;
    5335             :         }
    5336           4 :         node->dupColIdx = dupColIdx;
    5337           4 :         node->dupOperators = dupOperators;
    5338             :     }
    5339          40 :     node->numGroups = numGroups;
    5340             : 
    5341          40 :     return node;
    5342             : }
    5343             : 
    5344             : static BitmapAnd *
    5345           3 : make_bitmap_and(List *bitmapplans)
    5346             : {
    5347           3 :     BitmapAnd  *node = makeNode(BitmapAnd);
    5348           3 :     Plan       *plan = &node->plan;
    5349             : 
    5350           3 :     plan->targetlist = NIL;
    5351           3 :     plan->qual = NIL;
    5352           3 :     plan->lefttree = NULL;
    5353           3 :     plan->righttree = NULL;
    5354           3 :     node->bitmapplans = bitmapplans;
    5355             : 
    5356           3 :     return node;
    5357             : }
    5358             : 
    5359             : static BitmapOr *
    5360          17 : make_bitmap_or(List *bitmapplans)
    5361             : {
    5362          17 :     BitmapOr   *node = makeNode(BitmapOr);
    5363          17 :     Plan       *plan = &node->plan;
    5364             : 
    5365          17 :     plan->targetlist = NIL;
    5366          17 :     plan->qual = NIL;
    5367          17 :     plan->lefttree = NULL;
    5368          17 :     plan->righttree = NULL;
    5369          17 :     node->bitmapplans = bitmapplans;
    5370             : 
    5371          17 :     return node;
    5372             : }
    5373             : 
    5374             : static NestLoop *
    5375        2186 : make_nestloop(List *tlist,
    5376             :               List *joinclauses,
    5377             :               List *otherclauses,
    5378             :               List *nestParams,
    5379             :               Plan *lefttree,
    5380             :               Plan *righttree,
    5381             :               JoinType jointype,
    5382             :               bool inner_unique)
    5383             : {
    5384        2186 :     NestLoop   *node = makeNode(NestLoop);
    5385        2186 :     Plan       *plan = &node->join.plan;
    5386             : 
    5387        2186 :     plan->targetlist = tlist;
    5388        2186 :     plan->qual = otherclauses;
    5389        2186 :     plan->lefttree = lefttree;
    5390        2186 :     plan->righttree = righttree;
    5391        2186 :     node->join.jointype = jointype;
    5392        2186 :     node->join.inner_unique = inner_unique;
    5393        2186 :     node->join.joinqual = joinclauses;
    5394        2186 :     node->nestParams = nestParams;
    5395             : 
    5396        2186 :     return node;
    5397             : }
    5398             : 
    5399             : static HashJoin *
    5400        1364 : make_hashjoin(List *tlist,
    5401             :               List *joinclauses,
    5402             :               List *otherclauses,
    5403             :               List *hashclauses,
    5404             :               Plan *lefttree,
    5405             :               Plan *righttree,
    5406             :               JoinType jointype,
    5407             :               bool inner_unique)
    5408             : {
    5409        1364 :     HashJoin   *node = makeNode(HashJoin);
    5410        1364 :     Plan       *plan = &node->join.plan;
    5411             : 
    5412        1364 :     plan->targetlist = tlist;
    5413        1364 :     plan->qual = otherclauses;
    5414        1364 :     plan->lefttree = lefttree;
    5415        1364 :     plan->righttree = righttree;
    5416        1364 :     node->hashclauses = hashclauses;
    5417        1364 :     node->join.jointype = jointype;
    5418        1364 :     node->join.inner_unique = inner_unique;
    5419        1364 :     node->join.joinqual = joinclauses;
    5420             : 
    5421        1364 :     return node;
    5422             : }
    5423             : 
    5424             : static Hash *
    5425        1364 : make_hash(Plan *lefttree,
    5426             :           Oid skewTable,
    5427             :           AttrNumber skewColumn,
    5428             :           bool skewInherit)
    5429             : {
    5430        1364 :     Hash       *node = makeNode(Hash);
    5431        1364 :     Plan       *plan = &node->plan;
    5432             : 
    5433        1364 :     plan->targetlist = lefttree->targetlist;
    5434        1364 :     plan->qual = NIL;
    5435        1364 :     plan->lefttree = lefttree;
    5436        1364 :     plan->righttree = NULL;
    5437             : 
    5438        1364 :     node->skewTable = skewTable;
    5439        1364 :     node->skewColumn = skewColumn;
    5440        1364 :     node->skewInherit = skewInherit;
    5441             : 
    5442        1364 :     return node;
    5443             : }
    5444             : 
    5445             : static MergeJoin *
    5446         165 : make_mergejoin(List *tlist,
    5447             :                List *joinclauses,
    5448             :                List *otherclauses,
    5449             :                List *mergeclauses,
    5450             :                Oid *mergefamilies,
    5451             :                Oid *mergecollations,
    5452             :                int *mergestrategies,
    5453             :                bool *mergenullsfirst,
    5454             :                Plan *lefttree,
    5455             :                Plan *righttree,
    5456             :                JoinType jointype,
    5457             :                bool inner_unique,
    5458             :                bool skip_mark_restore)
    5459             : {
    5460         165 :     MergeJoin  *node = makeNode(MergeJoin);
    5461         165 :     Plan       *plan = &node->join.plan;
    5462             : 
    5463         165 :     plan->targetlist = tlist;
    5464         165 :     plan->qual = otherclauses;
    5465         165 :     plan->lefttree = lefttree;
    5466         165 :     plan->righttree = righttree;
    5467         165 :     node->skip_mark_restore = skip_mark_restore;
    5468         165 :     node->mergeclauses = mergeclauses;
    5469         165 :     node->mergeFamilies = mergefamilies;
    5470         165 :     node->mergeCollations = mergecollations;
    5471         165 :     node->mergeStrategies = mergestrategies;
    5472         165 :     node->mergeNullsFirst = mergenullsfirst;
    5473         165 :     node->join.jointype = jointype;
    5474         165 :     node->join.inner_unique = inner_unique;
    5475         165 :     node->join.joinqual = joinclauses;
    5476             : 
    5477         165 :     return node;
    5478             : }
    5479             : 
    5480             : /*
    5481             :  * make_sort --- basic routine to build a Sort plan node
    5482             :  *
    5483             :  * Caller must have built the sortColIdx, sortOperators, collations, and
    5484             :  * nullsFirst arrays already.
    5485             :  */
    5486             : static Sort *
    5487        2820 : make_sort(Plan *lefttree, int numCols,
    5488             :           AttrNumber *sortColIdx, Oid *sortOperators,
    5489             :           Oid *collations, bool *nullsFirst)
    5490             : {
    5491        2820 :     Sort       *node = makeNode(Sort);
    5492        2820 :     Plan       *plan = &node->plan;
    5493             : 
    5494        2820 :     plan->targetlist = lefttree->targetlist;
    5495        2820 :     plan->qual = NIL;
    5496        2820 :     plan->lefttree = lefttree;
    5497        2820 :     plan->righttree = NULL;
    5498        2820 :     node->numCols = numCols;
    5499        2820 :     node->sortColIdx = sortColIdx;
    5500        2820 :     node->sortOperators = sortOperators;
    5501        2820 :     node->collations = collations;
    5502        2820 :     node->nullsFirst = nullsFirst;
    5503             : 
    5504        2820 :     return node;
    5505             : }
    5506             : 
    5507             : /*
    5508             :  * prepare_sort_from_pathkeys
    5509             :  *    Prepare to sort according to given pathkeys
    5510             :  *
    5511             :  * This is used to set up for Sort, MergeAppend, and Gather Merge nodes.  It
    5512             :  * calculates the executor's representation of the sort key information, and
    5513             :  * adjusts the plan targetlist if needed to add resjunk sort columns.
    5514             :  *
    5515             :  * Input parameters:
    5516             :  *    'lefttree' is the plan node which yields input tuples
    5517             :  *    'pathkeys' is the list of pathkeys by which the result is to be sorted
    5518             :  *    'relids' identifies the child relation being sorted, if any
    5519             :  *    'reqColIdx' is NULL or an array of required sort key column numbers
    5520             :  *    'adjust_tlist_in_place' is TRUE if lefttree must be modified in-place
    5521             :  *
    5522             :  * We must convert the pathkey information into arrays of sort key column
    5523             :  * numbers, sort operator OIDs, collation OIDs, and nulls-first flags,
    5524             :  * which is the representation the executor wants.  These are returned into
    5525             :  * the output parameters *p_numsortkeys etc.
    5526             :  *
    5527             :  * When looking for matches to an EquivalenceClass's members, we will only
    5528             :  * consider child EC members if they match 'relids'.  This protects against
    5529             :  * possible incorrect matches to child expressions that contain no Vars.
    5530             :  *
    5531             :  * If reqColIdx isn't NULL then it contains sort key column numbers that
    5532             :  * we should match.  This is used when making child plans for a MergeAppend;
    5533             :  * it's an error if we can't match the columns.
    5534             :  *
    5535             :  * If the pathkeys include expressions that aren't simple Vars, we will
    5536             :  * usually need to add resjunk items to the input plan's targetlist to
    5537             :  * compute these expressions, since a Sort or MergeAppend node itself won't
    5538             :  * do any such calculations.  If the input plan type isn't one that can do
    5539             :  * projections, this means adding a Result node just to do the projection.
    5540             :  * However, the caller can pass adjust_tlist_in_place = TRUE to force the
    5541             :  * lefttree tlist to be modified in-place regardless of whether the node type
    5542             :  * can project --- we use this for fixing the tlist of MergeAppend itself.
    5543             :  *
    5544             :  * Returns the node which is to be the input to the Sort (either lefttree,
    5545             :  * or a Result stacked atop lefttree).
    5546             :  */
    5547             : static Plan *
    5548        3068 : prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys,
    5549             :                            Relids relids,
    5550             :                            const AttrNumber *reqColIdx,
    5551             :                            bool adjust_tlist_in_place,
    5552             :                            int *p_numsortkeys,
    5553             :                            AttrNumber **p_sortColIdx,
    5554             :                            Oid **p_sortOperators,
    5555             :                            Oid **p_collations,
    5556             :                            bool **p_nullsFirst)
    5557             : {
    5558        3068 :     List       *tlist = lefttree->targetlist;
    5559             :     ListCell   *i;
    5560             :     int         numsortkeys;
    5561             :     AttrNumber *sortColIdx;
    5562             :     Oid        *sortOperators;
    5563             :     Oid        *collations;
    5564             :     bool       *nullsFirst;
    5565             : 
    5566             :     /*
    5567             :      * We will need at most list_length(pathkeys) sort columns; possibly less
    5568             :      */
    5569        3068 :     numsortkeys = list_length(pathkeys);
    5570        3068 :     sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
    5571        3068 :     sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5572        3068 :     collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5573        3068 :     nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
    5574             : 
    5575        3068 :     numsortkeys = 0;
    5576             : 
    5577        6958 :     foreach(i, pathkeys)
    5578             :     {
    5579        3890 :         PathKey    *pathkey = (PathKey *) lfirst(i);
    5580        3890 :         EquivalenceClass *ec = pathkey->pk_eclass;
    5581             :         EquivalenceMember *em;
    5582        3890 :         TargetEntry *tle = NULL;
    5583        3890 :         Oid         pk_datatype = InvalidOid;
    5584             :         Oid         sortop;
    5585             :         ListCell   *j;
    5586             : 
    5587        3890 :         if (ec->ec_has_volatile)
    5588             :         {
    5589             :             /*
    5590             :              * If the pathkey's EquivalenceClass is volatile, then it must
    5591             :              * have come from an ORDER BY clause, and we have to match it to
    5592             :              * that same targetlist entry.
    5593             :              */
    5594           8 :             if (ec->ec_sortref == 0) /* can't happen */
    5595           0 :                 elog(ERROR, "volatile EquivalenceClass has no sortref");
    5596           8 :             tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
    5597           8 :             Assert(tle);
    5598           8 :             Assert(list_length(ec->ec_members) == 1);
    5599           8 :             pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
    5600             :         }
    5601        3882 :         else if (reqColIdx != NULL)
    5602             :         {
    5603             :             /*
    5604             :              * If we are given a sort column number to match, only consider
    5605             :              * the single TLE at that position.  It's possible that there is
    5606             :              * no such TLE, in which case fall through and generate a resjunk
    5607             :              * targetentry (we assume this must have happened in the parent
    5608             :              * plan as well).  If there is a TLE but it doesn't match the
    5609             :              * pathkey's EC, we do the same, which is probably the wrong thing
    5610             :              * but we'll leave it to caller to complain about the mismatch.
    5611             :              */
    5612         108 :             tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
    5613         108 :             if (tle)
    5614             :             {
    5615          92 :                 em = find_ec_member_for_tle(ec, tle, relids);
    5616          92 :                 if (em)
    5617             :                 {
    5618             :                     /* found expr at right place in tlist */
    5619          92 :                     pk_datatype = em->em_datatype;
    5620             :                 }
    5621             :                 else
    5622           0 :                     tle = NULL;
    5623             :             }
    5624             :         }
    5625             :         else
    5626             :         {
    5627             :             /*
    5628             :              * Otherwise, we can sort by any non-constant expression listed in
    5629             :              * the pathkey's EquivalenceClass.  For now, we take the first
    5630             :              * tlist item found in the EC. If there's no match, we'll generate
    5631             :              * a resjunk entry using the first EC member that is an expression
    5632             :              * in the input's vars.  (The non-const restriction only matters
    5633             :              * if the EC is below_outer_join; but if it isn't, it won't
    5634             :              * contain consts anyway, else we'd have discarded the pathkey as
    5635             :              * redundant.)
    5636             :              *
    5637             :              * XXX if we have a choice, is there any way of figuring out which
    5638             :              * might be cheapest to execute?  (For example, int4lt is likely
    5639             :              * much cheaper to execute than numericlt, but both might appear
    5640             :              * in the same equivalence class...)  Not clear that we ever will
    5641             :              * have an interesting choice in practice, so it may not matter.
    5642             :              */
    5643        6626 :             foreach(j, tlist)
    5644             :             {
    5645        6613 :                 tle = (TargetEntry *) lfirst(j);
    5646        6613 :                 em = find_ec_member_for_tle(ec, tle, relids);
    5647        6613 :                 if (em)
    5648             :                 {
    5649             :                     /* found expr already in tlist */
    5650        3761 :                     pk_datatype = em->em_datatype;
    5651        3761 :                     break;
    5652             :                 }
    5653        2852 :                 tle = NULL;
    5654             :             }
    5655             :         }
    5656             : 
    5657        3890 :         if (!tle)
    5658             :         {
    5659             :             /*
    5660             :              * No matching tlist item; look for a computable expression. Note
    5661             :              * that we treat Aggrefs as if they were variables; this is
    5662             :              * necessary when attempting to sort the output from an Agg node
    5663             :              * for use in a WindowFunc (since grouping_planner will have
    5664             :              * treated the Aggrefs as variables, too).  Likewise, if we find a
    5665             :              * WindowFunc in a sort expression, treat it as a variable.
    5666             :              */
    5667          29 :             Expr       *sortexpr = NULL;
    5668             : 
    5669          70 :             foreach(j, ec->ec_members)
    5670             :             {
    5671          70 :                 EquivalenceMember *em = (EquivalenceMember *) lfirst(j);
    5672             :                 List       *exprvars;
    5673             :                 ListCell   *k;
    5674             : 
    5675             :                 /*
    5676             :                  * We shouldn't be trying to sort by an equivalence class that
    5677             :                  * contains a constant, so no need to consider such cases any
    5678             :                  * further.
    5679             :                  */
    5680          70 :                 if (em->em_is_const)
    5681           0 :                     continue;
    5682             : 
    5683             :                 /*
    5684             :                  * Ignore child members unless they match the rel being
    5685             :                  * sorted.
    5686             :                  */
    5687         110 :                 if (em->em_is_child &&
    5688          40 :                     !bms_equal(em->em_relids, relids))
    5689          24 :                     continue;
    5690             : 
    5691          46 :                 sortexpr = em->em_expr;
    5692          46 :                 exprvars = pull_var_clause((Node *) sortexpr,
    5693             :                                            PVC_INCLUDE_AGGREGATES |
    5694             :                                            PVC_INCLUDE_WINDOWFUNCS |
    5695             :                                            PVC_INCLUDE_PLACEHOLDERS);
    5696          79 :                 foreach(k, exprvars)
    5697             :                 {
    5698          50 :                     if (!tlist_member_ignore_relabel(lfirst(k), tlist))
    5699          17 :                         break;
    5700             :                 }
    5701          46 :                 list_free(exprvars);
    5702          46 :                 if (!k)
    5703             :                 {
    5704          29 :                     pk_datatype = em->em_datatype;
    5705          29 :                     break;      /* found usable expression */
    5706             :                 }
    5707             :             }
    5708          29 :             if (!j)
    5709           0 :                 elog(ERROR, "could not find pathkey item to sort");
    5710             : 
    5711             :             /*
    5712             :              * Do we need to insert a Result node?
    5713             :              */
    5714          54 :             if (!adjust_tlist_in_place &&
    5715          25 :                 !is_projection_capable_plan(lefttree))
    5716             :             {
    5717             :                 /* copy needed so we don't modify input's tlist below */
    5718           0 :                 tlist = copyObject(tlist);
    5719           0 :                 lefttree = inject_projection_plan(lefttree, tlist,
    5720           0 :                                                   lefttree->parallel_safe);
    5721             :             }
    5722             : 
    5723             :             /* Don't bother testing is_projection_capable_plan again */
    5724          29 :             adjust_tlist_in_place = true;
    5725             : 
    5726             :             /*
    5727             :              * Add resjunk entry to input's tlist
    5728             :              */
    5729          29 :             tle = makeTargetEntry(sortexpr,
    5730          29 :                                   list_length(tlist) + 1,
    5731             :                                   NULL,
    5732             :                                   true);
    5733          29 :             tlist = lappend(tlist, tle);
    5734          29 :             lefttree->targetlist = tlist;    /* just in case NIL before */
    5735             :         }
    5736             : 
    5737             :         /*
    5738             :          * Look up the correct sort operator from the PathKey's slightly
    5739             :          * abstracted representation.
    5740             :          */
    5741        3890 :         sortop = get_opfamily_member(pathkey->pk_opfamily,
    5742             :                                      pk_datatype,
    5743             :                                      pk_datatype,
    5744        3890 :                                      pathkey->pk_strategy);
    5745        3890 :         if (!OidIsValid(sortop))    /* should not happen */
    5746           0 :             elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
    5747             :                  pathkey->pk_strategy, pk_datatype, pk_datatype,
    5748             :                  pathkey->pk_opfamily);
    5749             : 
    5750             :         /* Add the column to the sort arrays */
    5751        3890 :         sortColIdx[numsortkeys] = tle->resno;
    5752        3890 :         sortOperators[numsortkeys] = sortop;
    5753        3890 :         collations[numsortkeys] = ec->ec_collation;
    5754        3890 :         nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
    5755        3890 :         numsortkeys++;
    5756             :     }
    5757             : 
    5758             :     /* Return results */
    5759        3068 :     *p_numsortkeys = numsortkeys;
    5760        3068 :     *p_sortColIdx = sortColIdx;
    5761        3068 :     *p_sortOperators = sortOperators;
    5762        3068 :     *p_collations = collations;
    5763        3068 :     *p_nullsFirst = nullsFirst;
    5764             : 
    5765        3068 :     return lefttree;
    5766             : }
    5767             : 
    5768             : /*
    5769             :  * find_ec_member_for_tle
    5770             :  *      Locate an EquivalenceClass member matching the given TLE, if any
    5771             :  *
    5772             :  * Child EC members are ignored unless they match 'relids'.
    5773             :  */
    5774             : static EquivalenceMember *
    5775        6840 : find_ec_member_for_tle(EquivalenceClass *ec,
    5776             :                        TargetEntry *tle,
    5777             :                        Relids relids)
    5778             : {
    5779             :     Expr       *tlexpr;
    5780             :     ListCell   *lc;
    5781             : 
    5782             :     /* We ignore binary-compatible relabeling on both ends */
    5783        6840 :     tlexpr = tle->expr;
    5784       14054 :     while (tlexpr && IsA(tlexpr, RelabelType))
    5785         374 :         tlexpr = ((RelabelType *) tlexpr)->arg;
    5786             : 
    5787       10639 :     foreach(lc, ec->ec_members)
    5788             :     {
    5789        7740 :         EquivalenceMember *em = (EquivalenceMember *) lfirst(lc);
    5790             :         Expr       *emexpr;
    5791             : 
    5792             :         /*
    5793             :          * We shouldn't be trying to sort by an equivalence class that
    5794             :          * contains a constant, so no need to consider such cases any further.
    5795             :          */
    5796        7740 :         if (em->em_is_const)
    5797           0 :             continue;
    5798             : 
    5799             :         /*
    5800             :          * Ignore child members unless they match the rel being sorted.
    5801             :          */
    5802        8350 :         if (em->em_is_child &&
    5803         610 :             !bms_equal(em->em_relids, relids))
    5804         518 :             continue;
    5805             : 
    5806             :         /* Match if same expression (after stripping relabel) */
    5807        7222 :         emexpr = em->em_expr;
    5808       14736 :         while (emexpr && IsA(emexpr, RelabelType))
    5809         292 :             emexpr = ((RelabelType *) emexpr)->arg;
    5810             : 
    5811        7222 :         if (equal(emexpr, tlexpr))
    5812        3941 :             return em;
    5813             :     }
    5814             : 
    5815        2899 :     return NULL;
    5816             : }
    5817             : 
    5818             : /*
    5819             :  * make_sort_from_pathkeys
    5820             :  *    Create sort plan to sort according to given pathkeys
    5821             :  *
    5822             :  *    'lefttree' is the node which yields input tuples
    5823             :  *    'pathkeys' is the list of pathkeys by which the result is to be sorted
    5824             :  */
    5825             : static Sort *
    5826        2786 : make_sort_from_pathkeys(Plan *lefttree, List *pathkeys)
    5827             : {
    5828             :     int         numsortkeys;
    5829             :     AttrNumber *sortColIdx;
    5830             :     Oid        *sortOperators;
    5831             :     Oid        *collations;
    5832             :     bool       *nullsFirst;
    5833             : 
    5834             :     /* Compute sort column info, and adjust lefttree as needed */
    5835        2786 :     lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
    5836             :                                           NULL,
    5837             :                                           NULL,
    5838             :                                           false,
    5839             :                                           &numsortkeys,
    5840             :                                           &sortColIdx,
    5841             :                                           &sortOperators,
    5842             :                                           &collations,
    5843             :                                           &nullsFirst);
    5844             : 
    5845             :     /* Now build the Sort node */
    5846        2786 :     return make_sort(lefttree, numsortkeys,
    5847             :                      sortColIdx, sortOperators,
    5848             :                      collations, nullsFirst);
    5849             : }
    5850             : 
    5851             : /*
    5852             :  * make_sort_from_sortclauses
    5853             :  *    Create sort plan to sort according to given sortclauses
    5854             :  *
    5855             :  *    'sortcls' is a list of SortGroupClauses
    5856             :  *    'lefttree' is the node which yields input tuples
    5857             :  */
    5858             : Sort *
    5859           0 : make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
    5860             : {
    5861           0 :     List       *sub_tlist = lefttree->targetlist;
    5862             :     ListCell   *l;
    5863             :     int         numsortkeys;
    5864             :     AttrNumber *sortColIdx;
    5865             :     Oid        *sortOperators;
    5866             :     Oid        *collations;
    5867             :     bool       *nullsFirst;
    5868             : 
    5869             :     /* Convert list-ish representation to arrays wanted by executor */
    5870           0 :     numsortkeys = list_length(sortcls);
    5871           0 :     sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
    5872           0 :     sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5873           0 :     collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5874           0 :     nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
    5875             : 
    5876           0 :     numsortkeys = 0;
    5877           0 :     foreach(l, sortcls)
    5878             :     {
    5879           0 :         SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
    5880           0 :         TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
    5881             : 
    5882           0 :         sortColIdx[numsortkeys] = tle->resno;
    5883           0 :         sortOperators[numsortkeys] = sortcl->sortop;
    5884           0 :         collations[numsortkeys] = exprCollation((Node *) tle->expr);
    5885           0 :         nullsFirst[numsortkeys] = sortcl->nulls_first;
    5886           0 :         numsortkeys++;
    5887             :     }
    5888             : 
    5889           0 :     return make_sort(lefttree, numsortkeys,
    5890             :                      sortColIdx, sortOperators,
    5891             :                      collations, nullsFirst);
    5892             : }
    5893             : 
    5894             : /*
    5895             :  * make_sort_from_groupcols
    5896             :  *    Create sort plan to sort based on grouping columns
    5897             :  *
    5898             :  * 'groupcls' is the list of SortGroupClauses
    5899             :  * 'grpColIdx' gives the column numbers to use
    5900             :  *
    5901             :  * This might look like it could be merged with make_sort_from_sortclauses,
    5902             :  * but presently we *must* use the grpColIdx[] array to locate sort columns,
    5903             :  * because the child plan's tlist is not marked with ressortgroupref info
    5904             :  * appropriate to the grouping node.  So, only the sort ordering info
    5905             :  * is used from the SortGroupClause entries.
    5906             :  */
    5907             : static Sort *
    5908          24 : make_sort_from_groupcols(List *groupcls,
    5909             :                          AttrNumber *grpColIdx,
    5910             :                          Plan *lefttree)
    5911             : {
    5912          24 :     List       *sub_tlist = lefttree->targetlist;
    5913             :     ListCell   *l;
    5914             :     int         numsortkeys;
    5915             :     AttrNumber *sortColIdx;
    5916             :     Oid        *sortOperators;
    5917             :     Oid        *collations;
    5918             :     bool       *nullsFirst;
    5919             : 
    5920             :     /* Convert list-ish representation to arrays wanted by executor */
    5921          24 :     numsortkeys = list_length(groupcls);
    5922          24 :     sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
    5923          24 :     sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5924          24 :     collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
    5925          24 :     nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
    5926             : 
    5927          24 :     numsortkeys = 0;
    5928          59 :     foreach(l, groupcls)
    5929             :     {
    5930          35 :         SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
    5931          35 :         TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
    5932             : 
    5933          35 :         if (!tle)
    5934           0 :             elog(ERROR, "could not retrieve tle for sort-from-groupcols");
    5935             : 
    5936          35 :         sortColIdx[numsortkeys] = tle->resno;
    5937          35 :         sortOperators[numsortkeys] = grpcl->sortop;
    5938          35 :         collations[numsortkeys] = exprCollation((Node *) tle->expr);
    5939          35 :         nullsFirst[numsortkeys] = grpcl->nulls_first;
    5940          35 :         numsortkeys++;
    5941             :     }
    5942             : 
    5943          24 :     return make_sort(lefttree, numsortkeys,
    5944             :                      sortColIdx, sortOperators,
    5945             :                      collations, nullsFirst);
    5946             : }
    5947             : 
    5948             : static Material *
    5949         220 : make_material(Plan *lefttree)
    5950             : {
    5951         220 :     Material   *node = makeNode(Material);
    5952         220 :     Plan       *plan = &node->plan;
    5953             : 
    5954         220 :     plan->targetlist = lefttree->targetlist;
    5955         220 :     plan->qual = NIL;
    5956         220 :     plan->lefttree = lefttree;
    5957         220 :     plan->righttree = NULL;
    5958             : 
    5959         220 :     return node;
    5960             : }
    5961             : 
    5962             : /*
    5963             :  * materialize_finished_plan: stick a Material node atop a completed plan
    5964             :  *
    5965             :  * There are a couple of places where we want to attach a Material node
    5966             :  * after completion of create_plan(), without any MaterialPath path.
    5967             :  * Those places should probably be refactored someday to do this on the
    5968             :  * Path representation, but it's not worth the trouble yet.
    5969             :  */
    5970             : Plan *
    5971           6 : materialize_finished_plan(Plan *subplan)
    5972             : {
    5973             :     Plan       *matplan;
    5974             :     Path        matpath;        /* dummy for result of cost_material */
    5975             : 
    5976           6 :     matplan = (Plan *) make_material(subplan);
    5977             : 
    5978             :     /*
    5979             :      * XXX horrid kluge: if there are any initPlans attached to the subplan,
    5980             :      * move them up to the Material node, which is now effectively the top
    5981             :      * plan node in its query level.  This prevents failure in
    5982             :      * SS_finalize_plan(), which see for comments.  We don't bother adjusting
    5983             :      * the subplan's cost estimate for this.
    5984             :      */
    5985           6 :     matplan->initPlan = subplan->initPlan;
    5986           6 :     subplan->initPlan = NIL;
    5987             : 
    5988             :     /* Set cost data */
    5989           6 :     cost_material(&matpath,
    5990             :                   subplan->startup_cost,
    5991             :                   subplan->total_cost,
    5992             :                   subplan->plan_rows,
    5993             :                   subplan->plan_width);
    5994           6 :     matplan->startup_cost = matpath.startup_cost;
    5995           6 :     matplan->total_cost = matpath.total_cost;
    5996           6 :     matplan->plan_rows = subplan->plan_rows;
    5997           6 :     matplan->plan_width = subplan->plan_width;
    5998           6 :     matplan->parallel_aware = false;
    5999           6 :     matplan->parallel_safe = subplan->parallel_safe;
    6000             : 
    6001           6 :     return matplan;
    6002             : }
    6003             : 
    6004             : Agg *
    6005        2503 : make_agg(List *tlist, List *qual,
    6006             :          AggStrategy aggstrategy, AggSplit aggsplit,
    6007             :          int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators,
    6008             :          List *groupingSets, List *chain,
    6009             :          double dNumGroups, Plan *lefttree)
    6010             : {
    6011        2503 :     Agg        *node = makeNode(Agg);
    6012        2503 :     Plan       *plan = &node->plan;
    6013             :     long        numGroups;
    6014             : 
    6015             :     /* Reduce to long, but 'ware overflow! */
    6016        2503 :     numGroups = (long) Min(dNumGroups, (double) LONG_MAX);
    6017             : 
    6018        2503 :     node->aggstrategy = aggstrategy;
    6019        2503 :     node->aggsplit = aggsplit;
    6020        2503 :     node->numCols = numGroupCols;
    6021        2503 :     node->grpColIdx = grpColIdx;
    6022        2503 :     node->grpOperators = grpOperators;
    6023        2503 :     node->numGroups = numGroups;
    6024        2503 :     node->aggParams = NULL;      /* SS_finalize_plan() will fill this */
    6025        2503 :     node->groupingSets = groupingSets;
    6026        2503 :     node->chain = chain;
    6027             : 
    6028        2503 :     plan->qual = qual;
    6029        2503 :     plan->targetlist = tlist;
    6030        2503 :     plan->lefttree = lefttree;
    6031        2503 :     plan->righttree = NULL;
    6032             : 
    6033        2503 :     return node;
    6034             : }
    6035             : 
    6036             : static WindowAgg *
    6037         140 : make_windowagg(List *tlist, Index winref,
    6038             :                int partNumCols, AttrNumber *partColIdx, Oid *partOperators,
    6039             :                int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators,
    6040             :                int frameOptions, Node *startOffset, Node *endOffset,
    6041             :                Plan *lefttree)
    6042             : {
    6043         140 :     WindowAgg  *node = makeNode(WindowAgg);
    6044         140 :     Plan       *plan = &node->plan;
    6045             : 
    6046         140 :     node->winref = winref;
    6047         140 :     node->partNumCols = partNumCols;
    6048         140 :     node->partColIdx = partColIdx;
    6049         140 :     node->partOperators = partOperators;
    6050         140 :     node->ordNumCols = ordNumCols;
    6051         140 :     node->ordColIdx = ordColIdx;
    6052         140 :     node->ordOperators = ordOperators;
    6053         140 :     node->frameOptions = frameOptions;
    6054         140 :     node->startOffset = startOffset;
    6055         140 :     node->endOffset = endOffset;
    6056             : 
    6057         140 :     plan->targetlist = tlist;
    6058         140 :     plan->lefttree = lefttree;
    6059         140 :     plan->righttree = NULL;
    6060             :     /* WindowAgg nodes never have a qual clause */
    6061         140 :     plan->qual = NIL;
    6062             : 
    6063         140 :     return node;
    6064             : }
    6065             : 
    6066             : static Group *
    6067          11 : make_group(List *tlist,
    6068             :            List *qual,
    6069             :            int numGroupCols,
    6070             :            AttrNumber *grpColIdx,
    6071             :            Oid *grpOperators,
    6072             :            Plan *lefttree)
    6073             : {
    6074          11 :     Group      *node = makeNode(Group);
    6075          11 :     Plan       *plan = &node->plan;
    6076             : 
    6077          11 :     node->numCols = numGroupCols;
    6078          11 :     node->grpColIdx = grpColIdx;
    6079          11 :     node->grpOperators = grpOperators;
    6080             : 
    6081          11 :     plan->qual = qual;
    6082          11 :     plan->targetlist = tlist;
    6083          11 :     plan->lefttree = lefttree;
    6084          11 :     plan->righttree = NULL;
    6085             : 
    6086          11 :     return node;
    6087             : }
    6088             : 
    6089             : /*
    6090             :  * distinctList is a list of SortGroupClauses, identifying the targetlist items
    6091             :  * that should be considered by the Unique filter.  The input path must
    6092             :  * already be sorted accordingly.
    6093             :  */
    6094             : static Unique *
    6095           0 : make_unique_from_sortclauses(Plan *lefttree, List *distinctList)
    6096             : {
    6097           0 :     Unique     *node = makeNode(Unique);
    6098           0 :     Plan       *plan = &node->plan;
    6099           0 :     int         numCols = list_length(distinctList);
    6100           0 :     int         keyno = 0;
    6101             :     AttrNumber *uniqColIdx;
    6102             :     Oid        *uniqOperators;
    6103             :     ListCell   *slitem;
    6104             : 
    6105           0 :     plan->targetlist = lefttree->targetlist;
    6106           0 :     plan->qual = NIL;
    6107           0 :     plan->lefttree = lefttree;
    6108           0 :     plan->righttree = NULL;
    6109             : 
    6110             :     /*
    6111             :      * convert SortGroupClause list into arrays of attr indexes and equality
    6112             :      * operators, as wanted by executor
    6113             :      */
    6114           0 :     Assert(numCols > 0);
    6115           0 :     uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
    6116           0 :     uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
    6117             : 
    6118           0 :     foreach(slitem, distinctList)
    6119             :     {
    6120           0 :         SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
    6121           0 :         TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
    6122             : 
    6123           0 :         uniqColIdx[keyno] = tle->resno;
    6124           0 :         uniqOperators[keyno] = sortcl->eqop;
    6125           0 :         Assert(OidIsValid(uniqOperators[keyno]));
    6126           0 :         keyno++;
    6127             :     }
    6128             : 
    6129           0 :     node->numCols = numCols;
    6130           0 :     node->uniqColIdx = uniqColIdx;
    6131           0 :     node->uniqOperators = uniqOperators;
    6132             : 
    6133           0 :     return node;
    6134             : }
    6135             : 
    6136             : /*
    6137             :  * as above, but use pathkeys to identify the sort columns and semantics
    6138             :  */
    6139             : static Unique *
    6140          53 : make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
    6141             : {
    6142          53 :     Unique     *node = makeNode(Unique);
    6143          53 :     Plan       *plan = &node->plan;
    6144          53 :     int         keyno = 0;
    6145             :     AttrNumber *uniqColIdx;
    6146             :     Oid        *uniqOperators;
    6147             :     ListCell   *lc;
    6148             : 
    6149          53 :     plan->targetlist = lefttree->targetlist;
    6150          53 :     plan->qual = NIL;
    6151          53 :     plan->lefttree = lefttree;
    6152          53 :     plan->righttree = NULL;
    6153             : 
    6154             :     /*
    6155             :      * Convert pathkeys list into arrays of attr indexes and equality
    6156             :      * operators, as wanted by executor.  This has a lot in common with
    6157             :      * prepare_sort_from_pathkeys ... maybe unify sometime?
    6158             :      */
    6159          53 :     Assert(numCols >= 0 && numCols <= list_length(pathkeys));
    6160          53 :     uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
    6161          53 :     uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
    6162             : 
    6163         142 :     foreach(lc, pathkeys)
    6164             :     {
    6165          94 :         PathKey    *pathkey = (PathKey *) lfirst(lc);
    6166          94 :         EquivalenceClass *ec = pathkey->pk_eclass;
    6167             :         EquivalenceMember *em;
    6168          94 :         TargetEntry *tle = NULL;
    6169          94 :         Oid         pk_datatype = InvalidOid;
    6170             :         Oid         eqop;
    6171             :         ListCell   *j;
    6172             : 
    6173             :         /* Ignore pathkeys beyond the specified number of columns */
    6174          94 :         if (keyno >= numCols)
    6175           5 :             break;
    6176             : 
    6177          89 :         if (ec->ec_has_volatile)
    6178             :         {
    6179             :             /*
    6180             :              * If the pathkey's EquivalenceClass is volatile, then it must
    6181             :              * have come from an ORDER BY clause, and we have to match it to
    6182             :              * that same targetlist entry.
    6183             :              */
    6184           1 :             if (ec->ec_sortref == 0) /* can't happen */
    6185           0 :                 elog(ERROR, "volatile EquivalenceClass has no sortref");
    6186           1 :             tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
    6187           1 :             Assert(tle);
    6188           1 :             Assert(list_length(ec->ec_members) == 1);
    6189           1 :             pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
    6190             :         }
    6191             :         else
    6192             :         {
    6193             :             /*
    6194             :              * Otherwise, we can use any non-constant expression listed in the
    6195             :              * pathkey's EquivalenceClass.  For now, we take the first tlist
    6196             :              * item found in the EC.
    6197             :              */
    6198         135 :             foreach(j, plan->targetlist)
    6199             :             {
    6200         135 :                 tle = (TargetEntry *) lfirst(j);
    6201         135 :                 em = find_ec_member_for_tle(ec, tle, NULL);
    6202         135 :                 if (em)
    6203             :                 {
    6204             :                     /* found expr already in tlist */
    6205          88 :                     pk_datatype = em->em_datatype;
    6206          88 :                     break;
    6207             :                 }
    6208          47 :                 tle = NULL;
    6209             :             }
    6210             :         }
    6211             : 
    6212          89 :         if (!tle)
    6213           0 :             elog(ERROR, "could not find pathkey item to sort");
    6214             : 
    6215             :         /*
    6216             :          * Look up the correct equality operator from the PathKey's slightly
    6217             :          * abstracted representation.
    6218             :          */
    6219          89 :         eqop = get_opfamily_member(pathkey->pk_opfamily,
    6220             :                                    pk_datatype,
    6221             :                                    pk_datatype,
    6222             :                                    BTEqualStrategyNumber);
    6223          89 :         if (!OidIsValid(eqop))  /* should not happen */
    6224           0 :             elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
    6225             :                  BTEqualStrategyNumber, pk_datatype, pk_datatype,
    6226             :                  pathkey->pk_opfamily);
    6227             : 
    6228          89 :         uniqColIdx[keyno] = tle->resno;
    6229          89 :         uniqOperators[keyno] = eqop;
    6230             : 
    6231          89 :         keyno++;
    6232             :     }
    6233             : 
    6234          53 :     node->numCols = numCols;
    6235          53 :     node->uniqColIdx = uniqColIdx;
    6236          53 :     node->uniqOperators = uniqOperators;
    6237             : 
    6238          53 :     return node;
    6239             : }
    6240             : 
    6241             : static Gather *
    6242          23 : make_gather(List *qptlist,
    6243             :             List *qpqual,
    6244             :             int nworkers,
    6245             :             int rescan_param,
    6246             :             bool single_copy,
    6247             :             Plan *subplan)
    6248             : {
    6249          23 :     Gather     *node = makeNode(Gather);
    6250          23 :     Plan       *plan = &node->plan;
    6251             : 
    6252          23 :     plan->targetlist = qptlist;
    6253          23 :     plan->qual = qpqual;
    6254          23 :     plan->lefttree = subplan;
    6255          23 :     plan->righttree = NULL;
    6256          23 :     node->num_workers = nworkers;
    6257          23 :     node->rescan_param = rescan_param;
    6258          23 :     node->single_copy = single_copy;
    6259          23 :     node->invisible = false;
    6260             : 
    6261          23 :     return node;
    6262             : }
    6263             : 
    6264             : /*
    6265             :  * distinctList is a list of SortGroupClauses, identifying the targetlist
    6266             :  * items that should be considered by the SetOp filter.  The input path must
    6267             :  * already be sorted accordingly.
    6268             :  */
    6269             : static SetOp *
    6270          37 : make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree,
    6271             :            List *distinctList, AttrNumber flagColIdx, int firstFlag,
    6272             :            long numGroups)
    6273             : {
    6274          37 :     SetOp      *node = makeNode(SetOp);
    6275          37 :     Plan       *plan = &node->plan;
    6276          37 :     int         numCols = list_length(distinctList);
    6277          37 :     int         keyno = 0;
    6278             :     AttrNumber *dupColIdx;
    6279             :     Oid        *dupOperators;
    6280             :     ListCell   *slitem;
    6281             : 
    6282          37 :     plan->targetlist = lefttree->targetlist;
    6283          37 :     plan->qual = NIL;
    6284          37 :     plan->lefttree = lefttree;
    6285          37 :     plan->righttree = NULL;
    6286             : 
    6287             :     /*
    6288             :      * convert SortGroupClause list into arrays of attr indexes and equality
    6289             :      * operators, as wanted by executor
    6290             :      */
    6291          37 :     Assert(numCols > 0);
    6292          37 :     dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
    6293          37 :     dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
    6294             : 
    6295          90 :     foreach(slitem, distinctList)
    6296             :     {
    6297          53 :         SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
    6298          53 :         TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
    6299             : 
    6300          53 :         dupColIdx[keyno] = tle->resno;
    6301          53 :         dupOperators[keyno] = sortcl->eqop;
    6302          53 :         Assert(OidIsValid(dupOperators[keyno]));
    6303          53 :         keyno++;
    6304             :     }
    6305             : 
    6306          37 :     node->cmd = cmd;
    6307          37 :     node->strategy = strategy;
    6308          37 :     node->numCols = numCols;
    6309          37 :     node->dupColIdx = dupColIdx;
    6310          37 :     node->dupOperators = dupOperators;
    6311          37 :     node->flagColIdx = flagColIdx;
    6312          37 :     node->firstFlag = firstFlag;
    6313          37 :     node->numGroups = numGroups;
    6314             : 
    6315          37 :     return node;
    6316             : }
    6317             : 
    6318             : /*
    6319             :  * make_lockrows
    6320             :  *    Build a LockRows plan node
    6321             :  */
    6322             : static LockRows *
    6323         328 : make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
    6324             : {
    6325         328 :     LockRows   *node = makeNode(LockRows);
    6326         328 :     Plan       *plan = &node->plan;
    6327             : 
    6328         328 :     plan->targetlist = lefttree->targetlist;
    6329         328 :     plan->qual = NIL;
    6330         328 :     plan->lefttree = lefttree;
    6331         328 :     plan->righttree = NULL;
    6332             : 
    6333         328 :     node->rowMarks = rowMarks;
    6334         328 :     node->epqParam = epqParam;
    6335             : 
    6336         328 :     return node;
    6337             : }
    6338             : 
    6339             : /*
    6340             :  * make_limit
    6341             :  *    Build a Limit plan node
    6342             :  */
    6343             : Limit *
    6344         260 : make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
    6345             : {
    6346         260 :     Limit      *node = makeNode(Limit);
    6347         260 :     Plan       *plan = &node->plan;
    6348             : 
    6349         260 :     plan->targetlist = lefttree->targetlist;
    6350         260 :     plan->qual = NIL;
    6351         260 :     plan->lefttree = lefttree;
    6352         260 :     plan->righttree = NULL;
    6353             : 
    6354         260 :     node->limitOffset = limitOffset;
    6355         260 :     node->limitCount = limitCount;
    6356             : 
    6357         260 :     return node;
    6358             : }
    6359             : 
    6360             : /*
    6361             :  * make_result
    6362             :  *    Build a Result plan node
    6363             :  */
    6364             : static Result *
    6365       12163 : make_result(List *tlist,
    6366             :             Node *resconstantqual,
    6367             :             Plan *subplan)
    6368             : {
    6369       12163 :     Result     *node = makeNode(Result);
    6370       12163 :     Plan       *plan = &node->plan;
    6371             : 
    6372       12163 :     plan->targetlist = tlist;
    6373       12163 :     plan->qual = NIL;
    6374       12163 :     plan->lefttree = subplan;
    6375       12163 :     plan->righttree = NULL;
    6376       12163 :     node->resconstantqual = resconstantqual;
    6377             : 
    6378       12163 :     return node;
    6379             : }
    6380             : 
    6381             : /*
    6382             :  * make_project_set
    6383             :  *    Build a ProjectSet plan node
    6384             :  */
    6385             : static ProjectSet *
    6386         226 : make_project_set(List *tlist,
    6387             :                  Plan *subplan)
    6388             : {
    6389         226 :     ProjectSet *node = makeNode(ProjectSet);
    6390         226 :     Plan       *plan = &node->plan;
    6391             : 
    6392         226 :     plan->targetlist = tlist;
    6393         226 :     plan->qual = NIL;
    6394         226 :     plan->lefttree = subplan;
    6395         226 :     plan->righttree = NULL;
    6396             : 
    6397         226 :     return node;
    6398             : }
    6399             : 
    6400             : /*
    6401             :  * make_modifytable
    6402             :  *    Build a ModifyTable plan node
    6403             :  */
    6404             : static ModifyTable *
    6405        4340 : make_modifytable(PlannerInfo *root,
    6406             :                  CmdType operation, bool canSetTag,
    6407             :                  Index nominalRelation, List *partitioned_rels,
    6408             :                  List *resultRelations, List *subplans,
    6409             :                  List *withCheckOptionLists, List *returningLists,
    6410             :                  List *rowMarks, OnConflictExpr *onconflict, int epqParam)
    6411             : {
    6412        4340 :     ModifyTable *node = makeNode(ModifyTable);
    6413             :     List       *fdw_private_list;
    6414             :     Bitmapset  *direct_modify_plans;
    6415             :     ListCell   *lc;
    6416             :     int         i;
    6417             : 
    6418        4340 :     Assert(list_length(resultRelations) == list_length(subplans));
    6419        4340 :     Assert(withCheckOptionLists == NIL ||
    6420             :            list_length(resultRelations) == list_length(withCheckOptionLists));
    6421        4340 :     Assert(returningLists == NIL ||
    6422             :            list_length(resultRelations) == list_length(returningLists));
    6423             : 
    6424        4340 :     node->plan.lefttree = NULL;
    6425        4340 :     node->plan.righttree = NULL;
    6426        4340 :     node->plan.qual = NIL;
    6427             :     /* setrefs.c will fill in the targetlist, if needed */
    6428        4340 :     node->plan.targetlist = NIL;
    6429             : 
    6430        4340 :     node->operation = operation;
    6431        4340 :     node->canSetTag = canSetTag;
    6432        4340 :     node->nominalRelation = nominalRelation;
    6433        4340 :     node->partitioned_rels = partitioned_rels;
    6434        4340 :     node->resultRelations = resultRelations;
    6435        4340 :     node->resultRelIndex = -1;   /* will be set correctly in setrefs.c */
    6436        4340 :     node->rootResultRelIndex = -1;   /* will be set correctly in setrefs.c */
    6437        4340 :     node->plans = subplans;
    6438        4340 :     if (!onconflict)
    6439             :     {
    6440        4174 :         node->onConflictAction = ONCONFLICT_NONE;
    6441        4174 :         node->onConflictSet = NIL;
    6442        4174 :         node->onConflictWhere = NULL;
    6443        4174 :         node->arbiterIndexes = NIL;
    6444        4174 :         node->exclRelRTI = 0;
    6445        4174 :         node->exclRelTlist = NIL;
    6446             :     }
    6447             :     else
    6448             :     {
    6449         166 :         node->onConflictAction = onconflict->action;
    6450         166 :         node->onConflictSet = onconflict->onConflictSet;
    6451         166 :         node->onConflictWhere = onconflict->onConflictWhere;
    6452             : 
    6453             :         /*
    6454             :          * If a set of unique index inference elements was provided (an
    6455             :          * INSERT...ON CONFLICT "inference specification"), then infer
    6456             :          * appropriate unique indexes (or throw an error if none are
    6457             :          * available).
    6458             :          */
    6459         166 :         node->arbiterIndexes = infer_arbiter_indexes(root);
    6460             : 
    6461         140 :         node->exclRelRTI = onconflict->exclRelIndex;
    6462         140 :         node->exclRelTlist = onconflict->exclRelTlist;
    6463             :     }
    6464        4314 :     node->withCheckOptionLists = withCheckOptionLists;
    6465        4314 :     node->returningLists = returningLists;
    6466        4314 :     node->rowMarks = rowMarks;
    6467        4314 :     node->epqParam = epqParam;
    6468             : 
    6469             :     /*
    6470             :      * For each result relation that is a foreign table, allow the FDW to
    6471             :      * construct private plan data, and accumulate it all into a list.
    6472             :      */
    6473        4314 :     fdw_private_list = NIL;
    6474        4314 :     direct_modify_plans = NULL;
    6475        4314 :     i = 0;
    6476        8744 :     foreach(lc, resultRelations)
    6477             :     {
    6478        4430 :         Index       rti = lfirst_int(lc);
    6479             :         FdwRoutine *fdwroutine;
    6480             :         List       *fdw_private;
    6481             :         bool        direct_modify;
    6482             : 
    6483             :         /*
    6484             :          * If possible, we want to get the FdwRoutine from our RelOptInfo for
    6485             :          * the table.  But sometimes we don't have a RelOptInfo and must get
    6486             :          * it the hard way.  (In INSERT, the target relation is not scanned,
    6487             :          * so it's not a baserel; and there are also corner cases for
    6488             :          * updatable views where the target rel isn't a baserel.)
    6489             :          */
    6490        5883 :         if (rti < root->simple_rel_array_size &&
    6491        1453 :             root->simple_rel_array[rti] != NULL)
    6492         950 :         {
    6493         950 :             RelOptInfo *resultRel = root->simple_rel_array[rti];
    6494             : 
    6495         950 :             fdwroutine = resultRel->fdwroutine;
    6496             :         }
    6497             :         else
    6498             :         {
    6499        3480 :             RangeTblEntry *rte = planner_rt_fetch(rti, root);
    6500             : 
    6501        3480 :             Assert(rte->rtekind == RTE_RELATION);
    6502        3480 :             if (rte->relkind == RELKIND_FOREIGN_TABLE)
    6503           0 :                 fdwroutine = GetFdwRoutineByRelId(rte->relid);
    6504             :             else
    6505        3480 :                 fdwroutine = NULL;
    6506             :         }
    6507             : 
    6508             :         /*
    6509             :          * Try to modify the foreign table directly if (1) the FDW provides
    6510             :          * callback functions needed for that, (2) there are no row-level
    6511             :          * triggers on the foreign table, and (3) there are no WITH CHECK
    6512             :          * OPTIONs from parent views.
    6513             :          */
    6514        4430 :         direct_modify = false;
    6515        4430 :         if (fdwroutine != NULL &&
    6516           0 :             fdwroutine->PlanDirectModify != NULL &&
    6517           0 :             fdwroutine->BeginDirectModify != NULL &&
    6518           0 :             fdwroutine->IterateDirectModify != NULL &&
    6519           0 :             fdwroutine->EndDirectModify != NULL &&
    6520           0 :             withCheckOptionLists == NIL &&
    6521           0 :             !has_row_triggers(root, rti, operation))
    6522           0 :             direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
    6523        4430 :         if (direct_modify)
    6524           0 :             direct_modify_plans = bms_add_member(direct_modify_plans, i);
    6525             : 
    6526        4430 :         if (!direct_modify &&
    6527           0 :             fdwroutine != NULL &&
    6528           0 :             fdwroutine->PlanForeignModify != NULL)
    6529           0 :             fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
    6530             :         else
    6531        4430 :             fdw_private = NIL;
    6532        4430 :         fdw_private_list = lappend(fdw_private_list, fdw_private);
    6533        4430 :         i++;
    6534             :     }
    6535        4314 :     node->fdwPrivLists = fdw_private_list;
    6536        4314 :     node->fdwDirectModifyPlans = direct_modify_plans;
    6537             : 
    6538        4314 :     return node;
    6539             : }
    6540             : 
    6541             : /*
    6542             :  * is_projection_capable_path
    6543             :  *      Check whether a given Path node is able to do projection.
    6544             :  */
    6545             : bool
    6546       28306 : is_projection_capable_path(Path *path)
    6547             : {
    6548             :     /* Most plan types can project, so just list the ones that can't */
    6549       28306 :     switch (path->pathtype)
    6550             :     {
    6551             :         case T_Hash:
    6552             :         case T_Material:
    6553             :         case T_Sort:
    6554             :         case T_Unique:
    6555             :         case T_SetOp:
    6556             :         case T_LockRows:
    6557             :         case T_Limit:
    6558             :         case T_ModifyTable:
    6559             :         case T_MergeAppend:
    6560             :         case T_RecursiveUnion:
    6561         176 :             return false;
    6562             :         case T_Append:
    6563             : 
    6564             :             /*
    6565             :              * Append can't project, but if it's being used to represent a
    6566             :              * dummy path, claim that it can project.  This prevents us from
    6567             :              * converting a rel from dummy to non-dummy status by applying a
    6568             :              * projection to its dummy path.
    6569             :              */
    6570        1521 :             return IS_DUMMY_PATH(path);
    6571             :         case T_ProjectSet:
    6572             : 
    6573             :             /*
    6574             :              * Although ProjectSet certainly projects, say "no" because we
    6575             :              * don't want the planner to randomly replace its tlist with
    6576             :              * something else; the SRFs have to stay at top level.  This might
    6577             :              * get relaxed later.
    6578             :              */
    6579         175 :             return false;
    6580             :         default:
    6581       26434 :             break;
    6582             :     }
    6583       26434 :     return true;
    6584             : }
    6585             : 
    6586             : /*
    6587             :  * is_projection_capable_plan
    6588             :  *      Check whether a given Plan node is able to do projection.
    6589             :  */
    6590             : bool
    6591          30 : is_projection_capable_plan(Plan *plan)
    6592             : {
    6593             :     /* Most plan types can project, so just list the ones that can't */
    6594          30 :     switch (nodeTag(plan))
    6595             :     {
    6596             :         case T_Hash:
    6597             :         case T_Material:
    6598             :         case T_Sort:
    6599             :         case T_Unique:
    6600             :         case T_SetOp:
    6601             :         case T_LockRows:
    6602             :         case T_Limit:
    6603             :         case T_ModifyTable:
    6604             :         case T_Append:
    6605             :         case T_MergeAppend:
    6606             :         case T_RecursiveUnion:
    6607           0 :             return false;
    6608             :         case T_ProjectSet:
    6609             : 
    6610             :             /*
    6611             :              * Although ProjectSet certainly projects, say "no" because we
    6612             :              * don't want the planner to randomly replace its tlist with
    6613             :              * something else; the SRFs have to stay at top level.  This might
    6614             :              * get relaxed later.
    6615             :              */
    6616           0 :             return false;
    6617             :         default:
    6618          30 :             break;
    6619             :     }
    6620          30 :     return true;
    6621             : }

Generated by: LCOV version 1.11