PostgreSQL Source Code  git master
createplan.c File Reference
#include "postgres.h"
#include <math.h>
#include "access/sysattr.h"
#include "catalog/pg_class.h"
#include "foreign/fdwapi.h"
#include "miscadmin.h"
#include "nodes/extensible.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/clauses.h"
#include "optimizer/cost.h"
#include "optimizer/optimizer.h"
#include "optimizer/paramassign.h"
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/placeholder.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "optimizer/prep.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/subselect.h"
#include "optimizer/tlist.h"
#include "parser/parse_clause.h"
#include "parser/parsetree.h"
#include "partitioning/partprune.h"
#include "utils/lsyscache.h"
Include dependency graph for createplan.c:

Go to the source code of this file.

Macros

#define CP_EXACT_TLIST   0x0001 /* Plan must return specified tlist */
 
#define CP_SMALL_TLIST   0x0002 /* Prefer narrower tlists */
 
#define CP_LABEL_TLIST   0x0004 /* tlist must contain sortgrouprefs */
 
#define CP_IGNORE_TLIST   0x0008 /* caller will replace tlist */
 

Functions

static Plancreate_plan_recurse (PlannerInfo *root, Path *best_path, int flags)
 
static Plancreate_scan_plan (PlannerInfo *root, Path *best_path, int flags)
 
static Listbuild_path_tlist (PlannerInfo *root, Path *path)
 
static bool use_physical_tlist (PlannerInfo *root, Path *path, int flags)
 
static Listget_gating_quals (PlannerInfo *root, List *quals)
 
static Plancreate_gating_plan (PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
 
static Plancreate_join_plan (PlannerInfo *root, JoinPath *best_path)
 
static bool mark_async_capable_plan (Plan *plan, Path *path)
 
static Plancreate_append_plan (PlannerInfo *root, AppendPath *best_path, int flags)
 
static Plancreate_merge_append_plan (PlannerInfo *root, MergeAppendPath *best_path, int flags)
 
static Resultcreate_group_result_plan (PlannerInfo *root, GroupResultPath *best_path)
 
static ProjectSetcreate_project_set_plan (PlannerInfo *root, ProjectSetPath *best_path)
 
static Materialcreate_material_plan (PlannerInfo *root, MaterialPath *best_path, int flags)
 
static Memoizecreate_memoize_plan (PlannerInfo *root, MemoizePath *best_path, int flags)
 
static Plancreate_unique_plan (PlannerInfo *root, UniquePath *best_path, int flags)
 
static Gathercreate_gather_plan (PlannerInfo *root, GatherPath *best_path)
 
static Plancreate_projection_plan (PlannerInfo *root, ProjectionPath *best_path, int flags)
 
static Planinject_projection_plan (Plan *subplan, List *tlist, bool parallel_safe)
 
static Sortcreate_sort_plan (PlannerInfo *root, SortPath *best_path, int flags)
 
static IncrementalSortcreate_incrementalsort_plan (PlannerInfo *root, IncrementalSortPath *best_path, int flags)
 
static Groupcreate_group_plan (PlannerInfo *root, GroupPath *best_path)
 
static Uniquecreate_upper_unique_plan (PlannerInfo *root, UpperUniquePath *best_path, int flags)
 
static Aggcreate_agg_plan (PlannerInfo *root, AggPath *best_path)
 
static Plancreate_groupingsets_plan (PlannerInfo *root, GroupingSetsPath *best_path)
 
static Resultcreate_minmaxagg_plan (PlannerInfo *root, MinMaxAggPath *best_path)
 
static WindowAggcreate_windowagg_plan (PlannerInfo *root, WindowAggPath *best_path)
 
static SetOpcreate_setop_plan (PlannerInfo *root, SetOpPath *best_path, int flags)
 
static RecursiveUnioncreate_recursiveunion_plan (PlannerInfo *root, RecursiveUnionPath *best_path)
 
static LockRowscreate_lockrows_plan (PlannerInfo *root, LockRowsPath *best_path, int flags)
 
static ModifyTablecreate_modifytable_plan (PlannerInfo *root, ModifyTablePath *best_path)
 
static Limitcreate_limit_plan (PlannerInfo *root, LimitPath *best_path, int flags)
 
static SeqScancreate_seqscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static SampleScancreate_samplescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static Scancreate_indexscan_plan (PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, bool indexonly)
 
static BitmapHeapScancreate_bitmap_scan_plan (PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses)
 
static Plancreate_bitmap_subplan (PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
 
static void bitmap_subplan_mark_shared (Plan *plan)
 
static TidScancreate_tidscan_plan (PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses)
 
static TidRangeScancreate_tidrangescan_plan (PlannerInfo *root, TidRangePath *best_path, List *tlist, List *scan_clauses)
 
static SubqueryScancreate_subqueryscan_plan (PlannerInfo *root, SubqueryScanPath *best_path, List *tlist, List *scan_clauses)
 
static FunctionScancreate_functionscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static ValuesScancreate_valuesscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static TableFuncScancreate_tablefuncscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static CteScancreate_ctescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static NamedTuplestoreScancreate_namedtuplestorescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static Resultcreate_resultscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static WorkTableScancreate_worktablescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static ForeignScancreate_foreignscan_plan (PlannerInfo *root, ForeignPath *best_path, List *tlist, List *scan_clauses)
 
static CustomScancreate_customscan_plan (PlannerInfo *root, CustomPath *best_path, List *tlist, List *scan_clauses)
 
static NestLoopcreate_nestloop_plan (PlannerInfo *root, NestPath *best_path)
 
static MergeJoincreate_mergejoin_plan (PlannerInfo *root, MergePath *best_path)
 
static HashJoincreate_hashjoin_plan (PlannerInfo *root, HashPath *best_path)
 
static Nodereplace_nestloop_params (PlannerInfo *root, Node *expr)
 
static Nodereplace_nestloop_params_mutator (Node *node, PlannerInfo *root)
 
static void fix_indexqual_references (PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
 
static Listfix_indexorderby_references (PlannerInfo *root, IndexPath *index_path)
 
static Nodefix_indexqual_clause (PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
 
static Nodefix_indexqual_operand (Node *node, IndexOptInfo *index, int indexcol)
 
static Listget_switched_clauses (List *clauses, Relids outerrelids)
 
static Listorder_qual_clauses (PlannerInfo *root, List *clauses)
 
static void copy_generic_path_info (Plan *dest, Path *src)
 
static void copy_plan_costsize (Plan *dest, Plan *src)
 
static void label_sort_with_costsize (PlannerInfo *root, Sort *plan, double limit_tuples)
 
static SeqScanmake_seqscan (List *qptlist, List *qpqual, Index scanrelid)
 
static SampleScanmake_samplescan (List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
 
static IndexScanmake_indexscan (List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig, List *indexorderby, List *indexorderbyorig, List *indexorderbyops, ScanDirection indexscandir)
 
static IndexOnlyScanmake_indexonlyscan (List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *recheckqual, List *indexorderby, List *indextlist, ScanDirection indexscandir)
 
static BitmapIndexScanmake_bitmap_indexscan (Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
 
static BitmapHeapScanmake_bitmap_heapscan (List *qptlist, List *qpqual, Plan *lefttree, List *bitmapqualorig, Index scanrelid)
 
static TidScanmake_tidscan (List *qptlist, List *qpqual, Index scanrelid, List *tidquals)
 
static TidRangeScanmake_tidrangescan (List *qptlist, List *qpqual, Index scanrelid, List *tidrangequals)
 
static SubqueryScanmake_subqueryscan (List *qptlist, List *qpqual, Index scanrelid, Plan *subplan)
 
static FunctionScanmake_functionscan (List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
 
static ValuesScanmake_valuesscan (List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
 
static TableFuncScanmake_tablefuncscan (List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
 
static CteScanmake_ctescan (List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
 
static NamedTuplestoreScanmake_namedtuplestorescan (List *qptlist, List *qpqual, Index scanrelid, char *enrname)
 
static WorkTableScanmake_worktablescan (List *qptlist, List *qpqual, Index scanrelid, int wtParam)
 
static RecursiveUnionmake_recursive_union (List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, long numGroups)
 
static BitmapAndmake_bitmap_and (List *bitmapplans)
 
static BitmapOrmake_bitmap_or (List *bitmapplans)
 
static NestLoopmake_nestloop (List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static HashJoinmake_hashjoin (List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, List *hashoperators, List *hashcollations, List *hashkeys, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static Hashmake_hash (Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
 
static MergeJoinmake_mergejoin (List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, bool skip_mark_restore)
 
static Sortmake_sort (Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static IncrementalSortmake_incrementalsort (Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static Planprepare_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, int *p_numsortkeys, AttrNumber **p_sortColIdx, Oid **p_sortOperators, Oid **p_collations, bool **p_nullsFirst)
 
static Sortmake_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids)
 
static IncrementalSortmake_incrementalsort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
 
static Sortmake_sort_from_groupcols (List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
 
static Materialmake_material (Plan *lefttree)
 
static Memoizemake_memoize (Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids)
 
static WindowAggmake_windowagg (List *tlist, Index winref, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, int frameOptions, Node *startOffset, Node *endOffset, Oid startInRangeFunc, Oid endInRangeFunc, Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree)
 
static Groupmake_group (List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, Plan *lefttree)
 
static Uniquemake_unique_from_sortclauses (Plan *lefttree, List *distinctList)
 
static Uniquemake_unique_from_pathkeys (Plan *lefttree, List *pathkeys, int numCols)
 
static Gathermake_gather (List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)
 
static SetOpmake_setop (SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, List *distinctList, AttrNumber flagColIdx, int firstFlag, long numGroups)
 
static LockRowsmake_lockrows (Plan *lefttree, List *rowMarks, int epqParam)
 
static Resultmake_result (List *tlist, Node *resconstantqual, Plan *subplan)
 
static ProjectSetmake_project_set (List *tlist, Plan *subplan)
 
static ModifyTablemake_modifytable (PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
 
static GatherMergecreate_gather_merge_plan (PlannerInfo *root, GatherMergePath *best_path)
 
Plancreate_plan (PlannerInfo *root, Path *best_path)
 
Planchange_plan_targetlist (Plan *subplan, List *tlist, bool tlist_parallel_safe)
 
static AttrNumberremap_groupColIdx (PlannerInfo *root, List *groupClause)
 
ForeignScanmake_foreignscan (List *qptlist, List *qpqual, Index scanrelid, List *fdw_exprs, List *fdw_private, List *fdw_scan_tlist, List *fdw_recheck_quals, Plan *outer_plan)
 
Sortmake_sort_from_sortclauses (List *sortcls, Plan *lefttree)
 
Planmaterialize_finished_plan (Plan *subplan)
 
Aggmake_agg (List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, List *groupingSets, List *chain, double dNumGroups, Size transitionSpace, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 

Macro Definition Documentation

◆ CP_EXACT_TLIST

#define CP_EXACT_TLIST   0x0001 /* Plan must return specified tlist */

Definition at line 69 of file createplan.c.

◆ CP_IGNORE_TLIST

#define CP_IGNORE_TLIST   0x0008 /* caller will replace tlist */

Definition at line 72 of file createplan.c.

◆ CP_LABEL_TLIST

#define CP_LABEL_TLIST   0x0004 /* tlist must contain sortgrouprefs */

Definition at line 71 of file createplan.c.

◆ CP_SMALL_TLIST

#define CP_SMALL_TLIST   0x0002 /* Prefer narrower tlists */

Definition at line 70 of file createplan.c.

Function Documentation

◆ bitmap_subplan_mark_shared()

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 5473 of file createplan.c.

5474 {
5475  if (IsA(plan, BitmapAnd))
5476  bitmap_subplan_mark_shared(linitial(((BitmapAnd *) plan)->bitmapplans));
5477  else if (IsA(plan, BitmapOr))
5478  {
5479  ((BitmapOr *) plan)->isshared = true;
5480  bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5481  }
5482  else if (IsA(plan, BitmapIndexScan))
5483  ((BitmapIndexScan *) plan)->isshared = true;
5484  else
5485  elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5486 }
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:5473
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define nodeTag(nodeptr)
Definition: nodes.h:133
#define linitial(l)
Definition: pg_list.h:178
#define plan(x)
Definition: pg_regress.c:162

References elog, ERROR, IsA, linitial, nodeTag, and plan.

Referenced by create_bitmap_scan_plan().

◆ build_path_tlist()

static List * build_path_tlist ( PlannerInfo root,
Path path 
)
static

Definition at line 825 of file createplan.c.

826 {
827  List *tlist = NIL;
828  Index *sortgrouprefs = path->pathtarget->sortgrouprefs;
829  int resno = 1;
830  ListCell *v;
831 
832  foreach(v, path->pathtarget->exprs)
833  {
834  Node *node = (Node *) lfirst(v);
835  TargetEntry *tle;
836 
837  /*
838  * If it's a parameterized path, there might be lateral references in
839  * the tlist, which need to be replaced with Params. There's no need
840  * to remake the TargetEntry nodes, so apply this to each list item
841  * separately.
842  */
843  if (path->param_info)
844  node = replace_nestloop_params(root, node);
845 
846  tle = makeTargetEntry((Expr *) node,
847  resno,
848  NULL,
849  false);
850  if (sortgrouprefs)
851  tle->ressortgroupref = sortgrouprefs[resno - 1];
852 
853  tlist = lappend(tlist, tle);
854  resno++;
855  }
856  return tlist;
857 }
unsigned int Index
Definition: c.h:614
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4930
List * lappend(List *list, void *datum)
Definition: list.c:339
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:240
#define lfirst(lc)
Definition: pg_list.h:172
#define NIL
Definition: pg_list.h:68
tree ctl root
Definition: radixtree.h:1886
Definition: pg_list.h:54
Definition: nodes.h:129
Index ressortgroupref
Definition: primnodes.h:2192

References lappend(), lfirst, makeTargetEntry(), NIL, replace_nestloop_params(), TargetEntry::ressortgroupref, and root.

Referenced by create_agg_plan(), create_append_plan(), create_gather_merge_plan(), create_gather_plan(), create_gating_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_hashjoin_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_minmaxagg_plan(), create_nestloop_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_scan_plan(), create_unique_plan(), and create_windowagg_plan().

◆ change_plan_targetlist()

Plan* change_plan_targetlist ( Plan subplan,
List tlist,
bool  tlist_parallel_safe 
)

Definition at line 2147 of file createplan.c.

2148 {
2149  /*
2150  * If the top plan node can't do projections and its existing target list
2151  * isn't already what we need, we need to add a Result node to help it
2152  * along.
2153  */
2154  if (!is_projection_capable_plan(subplan) &&
2155  !tlist_same_exprs(tlist, subplan->targetlist))
2156  subplan = inject_projection_plan(subplan, tlist,
2157  subplan->parallel_safe &&
2158  tlist_parallel_safe);
2159  else
2160  {
2161  /* Else we can just replace the plan node's tlist */
2162  subplan->targetlist = tlist;
2163  subplan->parallel_safe &= tlist_parallel_safe;
2164  }
2165  return subplan;
2166 }
bool is_projection_capable_plan(Plan *plan)
Definition: createplan.c:7252
static Plan * inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
Definition: createplan.c:2115
bool parallel_safe
Definition: plannodes.h:141
List * targetlist
Definition: plannodes.h:152
bool tlist_same_exprs(List *tlist1, List *tlist2)
Definition: tlist.c:218

References inject_projection_plan(), is_projection_capable_plan(), Plan::parallel_safe, Plan::targetlist, and tlist_same_exprs().

Referenced by create_unique_plan(), and postgresGetForeignPlan().

◆ copy_generic_path_info()

static void copy_generic_path_info ( Plan dest,
Path src 
)
static

Definition at line 5404 of file createplan.c.

5405 {
5406  dest->startup_cost = src->startup_cost;
5407  dest->total_cost = src->total_cost;
5408  dest->plan_rows = src->rows;
5409  dest->plan_width = src->pathtarget->width;
5410  dest->parallel_aware = src->parallel_aware;
5411  dest->parallel_safe = src->parallel_safe;
5412 }
Cardinality rows
Definition: pathnodes.h:1660
Cost startup_cost
Definition: pathnodes.h:1661
Cost total_cost
Definition: pathnodes.h:1662
bool parallel_aware
Definition: pathnodes.h:1653
bool parallel_safe
Definition: pathnodes.h:1655

References generate_unaccent_rules::dest, Path::parallel_aware, Path::parallel_safe, Path::rows, Path::startup_cost, and Path::total_cost.

Referenced by create_agg_plan(), create_append_plan(), create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_hashjoin_plan(), create_incrementalsort_plan(), create_indexscan_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_namedtuplestorescan_plan(), create_nestloop_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_resultscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_setop_plan(), create_sort_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidrangescan_plan(), create_tidscan_plan(), create_unique_plan(), create_upper_unique_plan(), create_valuesscan_plan(), create_windowagg_plan(), and create_worktablescan_plan().

◆ copy_plan_costsize()

static void copy_plan_costsize ( Plan dest,
Plan src 
)
static

Definition at line 5419 of file createplan.c.

5420 {
5421  dest->startup_cost = src->startup_cost;
5422  dest->total_cost = src->total_cost;
5423  dest->plan_rows = src->plan_rows;
5424  dest->plan_width = src->plan_width;
5425  /* Assume the inserted node is not parallel-aware. */
5426  dest->parallel_aware = false;
5427  /* Assume the inserted node is parallel-safe, if child plan is. */
5428  dest->parallel_safe = src->parallel_safe;
5429 }
Cost total_cost
Definition: plannodes.h:129
Cost startup_cost
Definition: plannodes.h:128
int plan_width
Definition: plannodes.h:135
Cardinality plan_rows
Definition: plannodes.h:134

References generate_unaccent_rules::dest, Plan::parallel_safe, Plan::plan_rows, Plan::plan_width, Plan::startup_cost, and Plan::total_cost.

Referenced by create_gating_plan(), create_hashjoin_plan(), create_mergejoin_plan(), and inject_projection_plan().

◆ create_agg_plan()

static Agg * create_agg_plan ( PlannerInfo root,
AggPath best_path 
)
static

Definition at line 2303 of file createplan.c.

2304 {
2305  Agg *plan;
2306  Plan *subplan;
2307  List *tlist;
2308  List *quals;
2309 
2310  /*
2311  * Agg can project, so no need to be terribly picky about child tlist, but
2312  * we do need grouping columns to be available
2313  */
2314  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2315 
2316  tlist = build_path_tlist(root, &best_path->path);
2317 
2318  quals = order_qual_clauses(root, best_path->qual);
2319 
2320  plan = make_agg(tlist, quals,
2321  best_path->aggstrategy,
2322  best_path->aggsplit,
2323  list_length(best_path->groupClause),
2325  subplan->targetlist),
2326  extract_grouping_ops(best_path->groupClause),
2328  subplan->targetlist),
2329  NIL,
2330  NIL,
2331  best_path->numGroups,
2332  best_path->transitionSpace,
2333  subplan);
2334 
2335  copy_generic_path_info(&plan->plan, (Path *) best_path);
2336 
2337  return plan;
2338 }
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:5310
Agg * make_agg(List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, List *groupingSets, List *chain, double dNumGroups, Size transitionSpace, Plan *lefttree)
Definition: createplan.c:6588
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5404
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:388
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:825
#define CP_LABEL_TLIST
Definition: createplan.c:71
static int list_length(const List *l)
Definition: pg_list.h:152
Path * subpath
Definition: pathnodes.h:2254
Cardinality numGroups
Definition: pathnodes.h:2257
AggSplit aggsplit
Definition: pathnodes.h:2256
List * groupClause
Definition: pathnodes.h:2259
uint64 transitionSpace
Definition: pathnodes.h:2258
AggStrategy aggstrategy
Definition: pathnodes.h:2255
Path path
Definition: pathnodes.h:2253
List * qual
Definition: pathnodes.h:2260
Definition: plannodes.h:997
Oid * extract_grouping_collations(List *groupClause, List *tlist)
Definition: tlist.c:489
Oid * extract_grouping_ops(List *groupClause)
Definition: tlist.c:463
AttrNumber * extract_grouping_cols(List *groupClause, List *tlist)
Definition: tlist.c:514

References AggPath::aggsplit, AggPath::aggstrategy, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_cols(), extract_grouping_ops(), AggPath::groupClause, list_length(), make_agg(), NIL, AggPath::numGroups, order_qual_clauses(), AggPath::path, plan, AggPath::qual, root, AggPath::subpath, Plan::targetlist, and AggPath::transitionSpace.

Referenced by create_plan_recurse().

◆ create_append_plan()

static Plan * create_append_plan ( PlannerInfo root,
AppendPath best_path,
int  flags 
)
static

Definition at line 1216 of file createplan.c.

1217 {
1218  Append *plan;
1219  List *tlist = build_path_tlist(root, &best_path->path);
1220  int orig_tlist_length = list_length(tlist);
1221  bool tlist_was_changed = false;
1222  List *pathkeys = best_path->path.pathkeys;
1223  List *subplans = NIL;
1224  ListCell *subpaths;
1225  int nasyncplans = 0;
1226  RelOptInfo *rel = best_path->path.parent;
1227  PartitionPruneInfo *partpruneinfo = NULL;
1228  int nodenumsortkeys = 0;
1229  AttrNumber *nodeSortColIdx = NULL;
1230  Oid *nodeSortOperators = NULL;
1231  Oid *nodeCollations = NULL;
1232  bool *nodeNullsFirst = NULL;
1233  bool consider_async = false;
1234 
1235  /*
1236  * The subpaths list could be empty, if every child was proven empty by
1237  * constraint exclusion. In that case generate a dummy plan that returns
1238  * no rows.
1239  *
1240  * Note that an AppendPath with no members is also generated in certain
1241  * cases where there was no appending construct at all, but we know the
1242  * relation is empty (see set_dummy_rel_pathlist and mark_dummy_rel).
1243  */
1244  if (best_path->subpaths == NIL)
1245  {
1246  /* Generate a Result plan with constant-FALSE gating qual */
1247  Plan *plan;
1248 
1249  plan = (Plan *) make_result(tlist,
1250  (Node *) list_make1(makeBoolConst(false,
1251  false)),
1252  NULL);
1253 
1254  copy_generic_path_info(plan, (Path *) best_path);
1255 
1256  return plan;
1257  }
1258 
1259  /*
1260  * Otherwise build an Append plan. Note that if there's just one child,
1261  * the Append is pretty useless; but we wait till setrefs.c to get rid of
1262  * it. Doing so here doesn't work because the varno of the child scan
1263  * plan won't match the parent-rel Vars it'll be asked to emit.
1264  *
1265  * We don't have the actual creation of the Append node split out into a
1266  * separate make_xxx function. This is because we want to run
1267  * prepare_sort_from_pathkeys on it before we do so on the individual
1268  * child plans, to make cross-checking the sort info easier.
1269  */
1270  plan = makeNode(Append);
1271  plan->plan.targetlist = tlist;
1272  plan->plan.qual = NIL;
1273  plan->plan.lefttree = NULL;
1274  plan->plan.righttree = NULL;
1275  plan->apprelids = rel->relids;
1276 
1277  if (pathkeys != NIL)
1278  {
1279  /*
1280  * Compute sort column info, and adjust the Append's tlist as needed.
1281  * Because we pass adjust_tlist_in_place = true, we may ignore the
1282  * function result; it must be the same plan node. However, we then
1283  * need to detect whether any tlist entries were added.
1284  */
1285  (void) prepare_sort_from_pathkeys((Plan *) plan, pathkeys,
1286  best_path->path.parent->relids,
1287  NULL,
1288  true,
1289  &nodenumsortkeys,
1290  &nodeSortColIdx,
1291  &nodeSortOperators,
1292  &nodeCollations,
1293  &nodeNullsFirst);
1294  tlist_was_changed = (orig_tlist_length != list_length(plan->plan.targetlist));
1295  }
1296 
1297  /* If appropriate, consider async append */
1298  consider_async = (enable_async_append && pathkeys == NIL &&
1299  !best_path->path.parallel_safe &&
1300  list_length(best_path->subpaths) > 1);
1301 
1302  /* Build the plan for each child */
1303  foreach(subpaths, best_path->subpaths)
1304  {
1305  Path *subpath = (Path *) lfirst(subpaths);
1306  Plan *subplan;
1307 
1308  /* Must insist that all children return the same tlist */
1310 
1311  /*
1312  * For ordered Appends, we must insert a Sort node if subplan isn't
1313  * sufficiently ordered.
1314  */
1315  if (pathkeys != NIL)
1316  {
1317  int numsortkeys;
1318  AttrNumber *sortColIdx;
1319  Oid *sortOperators;
1320  Oid *collations;
1321  bool *nullsFirst;
1322 
1323  /*
1324  * Compute sort column info, and adjust subplan's tlist as needed.
1325  * We must apply prepare_sort_from_pathkeys even to subplans that
1326  * don't need an explicit sort, to make sure they are returning
1327  * the same sort key columns the Append expects.
1328  */
1329  subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1330  subpath->parent->relids,
1331  nodeSortColIdx,
1332  false,
1333  &numsortkeys,
1334  &sortColIdx,
1335  &sortOperators,
1336  &collations,
1337  &nullsFirst);
1338 
1339  /*
1340  * Check that we got the same sort key information. We just
1341  * Assert that the sortops match, since those depend only on the
1342  * pathkeys; but it seems like a good idea to check the sort
1343  * column numbers explicitly, to ensure the tlists match up.
1344  */
1345  Assert(numsortkeys == nodenumsortkeys);
1346  if (memcmp(sortColIdx, nodeSortColIdx,
1347  numsortkeys * sizeof(AttrNumber)) != 0)
1348  elog(ERROR, "Append child's targetlist doesn't match Append");
1349  Assert(memcmp(sortOperators, nodeSortOperators,
1350  numsortkeys * sizeof(Oid)) == 0);
1351  Assert(memcmp(collations, nodeCollations,
1352  numsortkeys * sizeof(Oid)) == 0);
1353  Assert(memcmp(nullsFirst, nodeNullsFirst,
1354  numsortkeys * sizeof(bool)) == 0);
1355 
1356  /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1357  if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
1358  {
1359  Sort *sort = make_sort(subplan, numsortkeys,
1360  sortColIdx, sortOperators,
1361  collations, nullsFirst);
1362 
1364  subplan = (Plan *) sort;
1365  }
1366  }
1367 
1368  /* If needed, check to see if subplan can be executed asynchronously */
1369  if (consider_async && mark_async_capable_plan(subplan, subpath))
1370  {
1371  Assert(subplan->async_capable);
1372  ++nasyncplans;
1373  }
1374 
1375  subplans = lappend(subplans, subplan);
1376  }
1377 
1378  /*
1379  * If any quals exist, they may be useful to perform further partition
1380  * pruning during execution. Gather information needed by the executor to
1381  * do partition pruning.
1382  */
1384  {
1385  List *prunequal;
1386 
1387  prunequal = extract_actual_clauses(rel->baserestrictinfo, false);
1388 
1389  if (best_path->path.param_info)
1390  {
1391  List *prmquals = best_path->path.param_info->ppi_clauses;
1392 
1393  prmquals = extract_actual_clauses(prmquals, false);
1394  prmquals = (List *) replace_nestloop_params(root,
1395  (Node *) prmquals);
1396 
1397  prunequal = list_concat(prunequal, prmquals);
1398  }
1399 
1400  if (prunequal != NIL)
1401  partpruneinfo =
1403  best_path->subpaths,
1404  prunequal);
1405  }
1406 
1407  plan->appendplans = subplans;
1408  plan->nasyncplans = nasyncplans;
1409  plan->first_partial_plan = best_path->first_partial_path;
1410  plan->part_prune_info = partpruneinfo;
1411 
1412  copy_generic_path_info(&plan->plan, (Path *) best_path);
1413 
1414  /*
1415  * If prepare_sort_from_pathkeys added sort columns, but we were told to
1416  * produce either the exact tlist or a narrow tlist, we should get rid of
1417  * the sort columns again. We must inject a projection node to do so.
1418  */
1419  if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
1420  {
1421  tlist = list_copy_head(plan->plan.targetlist, orig_tlist_length);
1422  return inject_projection_plan((Plan *) plan, tlist,
1423  plan->plan.parallel_safe);
1424  }
1425  else
1426  return (Plan *) plan;
1427 }
Datum sort(PG_FUNCTION_ARGS)
Definition: _int_op.c:195
int16 AttrNumber
Definition: attnum.h:21
#define Assert(condition)
Definition: c.h:858
bool enable_async_append
Definition: costsize.c:154
bool enable_partition_pruning
Definition: costsize.c:152
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6983
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Definition: createplan.c:5441
#define CP_SMALL_TLIST
Definition: createplan.c:70
static Sort * make_sort(Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:6063
#define CP_EXACT_TLIST
Definition: createplan.c:69
static bool mark_async_capable_plan(Plan *plan, Path *path)
Definition: createplan.c:1140
static Plan * prepare_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, int *p_numsortkeys, AttrNumber **p_sortColIdx, Oid **p_sortOperators, Oid **p_collations, bool **p_nullsFirst)
Definition: createplan.c:6159
List * list_copy_head(const List *oldlist, int len)
Definition: list.c:1593
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:310
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:359
#define makeNode(_type_)
Definition: nodes.h:155
PartitionPruneInfo * make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *subpaths, List *prunequal)
Definition: partprune.c:220
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:341
#define list_make1(x1)
Definition: pg_list.h:212
unsigned int Oid
Definition: postgres_ext.h:31
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:494
int first_partial_path
Definition: pathnodes.h:1934
Cardinality limit_tuples
Definition: pathnodes.h:1935
List * subpaths
Definition: pathnodes.h:1932
List * pathkeys
Definition: pathnodes.h:1665
bool async_capable
Definition: plannodes.h:146
List * baserestrictinfo
Definition: pathnodes.h:979
Relids relids
Definition: pathnodes.h:865

References Assert, Plan::async_capable, RelOptInfo::baserestrictinfo, build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, CP_SMALL_TLIST, create_plan_recurse(), elog, enable_async_append, enable_partition_pruning, ERROR, extract_actual_clauses(), AppendPath::first_partial_path, inject_projection_plan(), label_sort_with_costsize(), lappend(), lfirst, AppendPath::limit_tuples, list_concat(), list_copy_head(), list_length(), list_make1, make_partition_pruneinfo(), make_result(), make_sort(), makeBoolConst(), makeNode, mark_async_capable_plan(), NIL, Path::parallel_safe, AppendPath::path, Path::pathkeys, pathkeys_contained_in(), plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, replace_nestloop_params(), root, sort(), subpath(), and AppendPath::subpaths.

Referenced by create_plan_recurse().

◆ create_bitmap_scan_plan()

static BitmapHeapScan * create_bitmap_scan_plan ( PlannerInfo root,
BitmapHeapPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3196 of file createplan.c.

3200 {
3201  Index baserelid = best_path->path.parent->relid;
3202  Plan *bitmapqualplan;
3203  List *bitmapqualorig;
3204  List *indexquals;
3205  List *indexECs;
3206  List *qpqual;
3207  ListCell *l;
3208  BitmapHeapScan *scan_plan;
3209 
3210  /* it should be a base rel... */
3211  Assert(baserelid > 0);
3212  Assert(best_path->path.parent->rtekind == RTE_RELATION);
3213 
3214  /* Process the bitmapqual tree into a Plan tree and qual lists */
3215  bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
3216  &bitmapqualorig, &indexquals,
3217  &indexECs);
3218 
3219  if (best_path->path.parallel_aware)
3220  bitmap_subplan_mark_shared(bitmapqualplan);
3221 
3222  /*
3223  * The qpqual list must contain all restrictions not automatically handled
3224  * by the index, other than pseudoconstant clauses which will be handled
3225  * by a separate gating plan node. All the predicates in the indexquals
3226  * will be checked (either by the index itself, or by
3227  * nodeBitmapHeapscan.c), but if there are any "special" operators
3228  * involved then they must be added to qpqual. The upshot is that qpqual
3229  * must contain scan_clauses minus whatever appears in indexquals.
3230  *
3231  * This loop is similar to the comparable code in create_indexscan_plan(),
3232  * but with some differences because it has to compare the scan clauses to
3233  * stripped (no RestrictInfos) indexquals. See comments there for more
3234  * info.
3235  *
3236  * In normal cases simple equal() checks will be enough to spot duplicate
3237  * clauses, so we try that first. We next see if the scan clause is
3238  * redundant with any top-level indexqual by virtue of being generated
3239  * from the same EC. After that, try predicate_implied_by().
3240  *
3241  * Unlike create_indexscan_plan(), the predicate_implied_by() test here is
3242  * useful for getting rid of qpquals that are implied by index predicates,
3243  * because the predicate conditions are included in the "indexquals"
3244  * returned by create_bitmap_subplan(). Bitmap scans have to do it that
3245  * way because predicate conditions need to be rechecked if the scan
3246  * becomes lossy, so they have to be included in bitmapqualorig.
3247  */
3248  qpqual = NIL;
3249  foreach(l, scan_clauses)
3250  {
3251  RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
3252  Node *clause = (Node *) rinfo->clause;
3253 
3254  if (rinfo->pseudoconstant)
3255  continue; /* we may drop pseudoconstants here */
3256  if (list_member(indexquals, clause))
3257  continue; /* simple duplicate */
3258  if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
3259  continue; /* derived from same EquivalenceClass */
3260  if (!contain_mutable_functions(clause) &&
3261  predicate_implied_by(list_make1(clause), indexquals, false))
3262  continue; /* provably implied by indexquals */
3263  qpqual = lappend(qpqual, rinfo);
3264  }
3265 
3266  /* Sort clauses into best execution order */
3267  qpqual = order_qual_clauses(root, qpqual);
3268 
3269  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3270  qpqual = extract_actual_clauses(qpqual, false);
3271 
3272  /*
3273  * When dealing with special operators, we will at this point have
3274  * duplicate clauses in qpqual and bitmapqualorig. We may as well drop
3275  * 'em from bitmapqualorig, since there's no point in making the tests
3276  * twice.
3277  */
3278  bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
3279 
3280  /*
3281  * We have to replace any outer-relation variables with nestloop params in
3282  * the qpqual and bitmapqualorig expressions. (This was already done for
3283  * expressions attached to plan nodes in the bitmapqualplan tree.)
3284  */
3285  if (best_path->path.param_info)
3286  {
3287  qpqual = (List *)
3288  replace_nestloop_params(root, (Node *) qpqual);
3289  bitmapqualorig = (List *)
3290  replace_nestloop_params(root, (Node *) bitmapqualorig);
3291  }
3292 
3293  /* Finally ready to build the plan node */
3294  scan_plan = make_bitmap_heapscan(tlist,
3295  qpqual,
3296  bitmapqualplan,
3297  bitmapqualorig,
3298  baserelid);
3299 
3300  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3301 
3302  return scan_plan;
3303 }
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:370
static Plan * create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
Definition: createplan.c:3326
static BitmapHeapScan * make_bitmap_heapscan(List *qptlist, List *qpqual, Plan *lefttree, List *bitmapqualorig, Index scanrelid)
Definition: createplan.c:5620
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:77
List * list_difference_ptr(const List *list1, const List *list2)
Definition: list.c:1263
bool list_member_ptr(const List *list, const void *datum)
Definition: list.c:682
bool list_member(const List *list, const void *datum)
Definition: list.c:661
@ RTE_RELATION
Definition: parsenodes.h:1028
#define lfirst_node(type, lc)
Definition: pg_list.h:176
bool predicate_implied_by(List *predicate_list, List *clause_list, bool weak)
Definition: predtest.c:152
Path * bitmapqual
Definition: pathnodes.h:1785
Expr * clause
Definition: pathnodes.h:2564

References Assert, bitmap_subplan_mark_shared(), BitmapHeapPath::bitmapqual, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), create_bitmap_subplan(), extract_actual_clauses(), if(), lappend(), lfirst_node, list_difference_ptr(), list_make1, list_member(), list_member_ptr(), make_bitmap_heapscan(), NIL, order_qual_clauses(), Path::parallel_aware, BitmapHeapPath::path, predicate_implied_by(), replace_nestloop_params(), root, RTE_RELATION, and BitmapHeapScan::scan.

Referenced by create_scan_plan().

◆ create_bitmap_subplan()

static Plan * create_bitmap_subplan ( PlannerInfo root,
Path bitmapqual,
List **  qual,
List **  indexqual,
List **  indexECs 
)
static

Definition at line 3326 of file createplan.c.

3328 {
3329  Plan *plan;
3330 
3331  if (IsA(bitmapqual, BitmapAndPath))
3332  {
3333  BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
3334  List *subplans = NIL;
3335  List *subquals = NIL;
3336  List *subindexquals = NIL;
3337  List *subindexECs = NIL;
3338  ListCell *l;
3339 
3340  /*
3341  * There may well be redundant quals among the subplans, since a
3342  * top-level WHERE qual might have gotten used to form several
3343  * different index quals. We don't try exceedingly hard to eliminate
3344  * redundancies, but we do eliminate obvious duplicates by using
3345  * list_concat_unique.
3346  */
3347  foreach(l, apath->bitmapquals)
3348  {
3349  Plan *subplan;
3350  List *subqual;
3351  List *subindexqual;
3352  List *subindexEC;
3353 
3354  subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3355  &subqual, &subindexqual,
3356  &subindexEC);
3357  subplans = lappend(subplans, subplan);
3358  subquals = list_concat_unique(subquals, subqual);
3359  subindexquals = list_concat_unique(subindexquals, subindexqual);
3360  /* Duplicates in indexECs aren't worth getting rid of */
3361  subindexECs = list_concat(subindexECs, subindexEC);
3362  }
3363  plan = (Plan *) make_bitmap_and(subplans);
3364  plan->startup_cost = apath->path.startup_cost;
3365  plan->total_cost = apath->path.total_cost;
3366  plan->plan_rows =
3367  clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
3368  plan->plan_width = 0; /* meaningless */
3369  plan->parallel_aware = false;
3370  plan->parallel_safe = apath->path.parallel_safe;
3371  *qual = subquals;
3372  *indexqual = subindexquals;
3373  *indexECs = subindexECs;
3374  }
3375  else if (IsA(bitmapqual, BitmapOrPath))
3376  {
3377  BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
3378  List *subplans = NIL;
3379  List *subquals = NIL;
3380  List *subindexquals = NIL;
3381  bool const_true_subqual = false;
3382  bool const_true_subindexqual = false;
3383  ListCell *l;
3384 
3385  /*
3386  * Here, we only detect qual-free subplans. A qual-free subplan would
3387  * cause us to generate "... OR true ..." which we may as well reduce
3388  * to just "true". We do not try to eliminate redundant subclauses
3389  * because (a) it's not as likely as in the AND case, and (b) we might
3390  * well be working with hundreds or even thousands of OR conditions,
3391  * perhaps from a long IN list. The performance of list_append_unique
3392  * would be unacceptable.
3393  */
3394  foreach(l, opath->bitmapquals)
3395  {
3396  Plan *subplan;
3397  List *subqual;
3398  List *subindexqual;
3399  List *subindexEC;
3400 
3401  subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3402  &subqual, &subindexqual,
3403  &subindexEC);
3404  subplans = lappend(subplans, subplan);
3405  if (subqual == NIL)
3406  const_true_subqual = true;
3407  else if (!const_true_subqual)
3408  subquals = lappend(subquals,
3409  make_ands_explicit(subqual));
3410  if (subindexqual == NIL)
3411  const_true_subindexqual = true;
3412  else if (!const_true_subindexqual)
3413  subindexquals = lappend(subindexquals,
3414  make_ands_explicit(subindexqual));
3415  }
3416 
3417  /*
3418  * In the presence of ScalarArrayOpExpr quals, we might have built
3419  * BitmapOrPaths with just one subpath; don't add an OR step.
3420  */
3421  if (list_length(subplans) == 1)
3422  {
3423  plan = (Plan *) linitial(subplans);
3424  }
3425  else
3426  {
3427  plan = (Plan *) make_bitmap_or(subplans);
3428  plan->startup_cost = opath->path.startup_cost;
3429  plan->total_cost = opath->path.total_cost;
3430  plan->plan_rows =
3431  clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
3432  plan->plan_width = 0; /* meaningless */
3433  plan->parallel_aware = false;
3434  plan->parallel_safe = opath->path.parallel_safe;
3435  }
3436 
3437  /*
3438  * If there were constant-TRUE subquals, the OR reduces to constant
3439  * TRUE. Also, avoid generating one-element ORs, which could happen
3440  * due to redundancy elimination or ScalarArrayOpExpr quals.
3441  */
3442  if (const_true_subqual)
3443  *qual = NIL;
3444  else if (list_length(subquals) <= 1)
3445  *qual = subquals;
3446  else
3447  *qual = list_make1(make_orclause(subquals));
3448  if (const_true_subindexqual)
3449  *indexqual = NIL;
3450  else if (list_length(subindexquals) <= 1)
3451  *indexqual = subindexquals;
3452  else
3453  *indexqual = list_make1(make_orclause(subindexquals));
3454  *indexECs = NIL;
3455  }
3456  else if (IsA(bitmapqual, IndexPath))
3457  {
3458  IndexPath *ipath = (IndexPath *) bitmapqual;
3459  IndexScan *iscan;
3460  List *subquals;
3461  List *subindexquals;
3462  List *subindexECs;
3463  ListCell *l;
3464 
3465  /* Use the regular indexscan plan build machinery... */
3466  iscan = castNode(IndexScan,
3467  create_indexscan_plan(root, ipath,
3468  NIL, NIL, false));
3469  /* then convert to a bitmap indexscan */
3471  iscan->indexid,
3472  iscan->indexqual,
3473  iscan->indexqualorig);
3474  /* and set its cost/width fields appropriately */
3475  plan->startup_cost = 0.0;
3476  plan->total_cost = ipath->indextotalcost;
3477  plan->plan_rows =
3478  clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
3479  plan->plan_width = 0; /* meaningless */
3480  plan->parallel_aware = false;
3481  plan->parallel_safe = ipath->path.parallel_safe;
3482  /* Extract original index clauses, actual index quals, relevant ECs */
3483  subquals = NIL;
3484  subindexquals = NIL;
3485  subindexECs = NIL;
3486  foreach(l, ipath->indexclauses)
3487  {
3488  IndexClause *iclause = (IndexClause *) lfirst(l);
3489  RestrictInfo *rinfo = iclause->rinfo;
3490 
3491  Assert(!rinfo->pseudoconstant);
3492  subquals = lappend(subquals, rinfo->clause);
3493  subindexquals = list_concat(subindexquals,
3494  get_actual_clauses(iclause->indexquals));
3495  if (rinfo->parent_ec)
3496  subindexECs = lappend(subindexECs, rinfo->parent_ec);
3497  }
3498  /* We can add any index predicate conditions, too */
3499  foreach(l, ipath->indexinfo->indpred)
3500  {
3501  Expr *pred = (Expr *) lfirst(l);
3502 
3503  /*
3504  * We know that the index predicate must have been implied by the
3505  * query condition as a whole, but it may or may not be implied by
3506  * the conditions that got pushed into the bitmapqual. Avoid
3507  * generating redundant conditions.
3508  */
3509  if (!predicate_implied_by(list_make1(pred), subquals, false))
3510  {
3511  subquals = lappend(subquals, pred);
3512  subindexquals = lappend(subindexquals, pred);
3513  }
3514  }
3515  *qual = subquals;
3516  *indexqual = subindexquals;
3517  *indexECs = subindexECs;
3518  }
3519  else
3520  {
3521  elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
3522  plan = NULL; /* keep compiler quiet */
3523  }
3524 
3525  return plan;
3526 }
double clamp_row_est(double nrows)
Definition: costsize.c:202
static BitmapOr * make_bitmap_or(List *bitmapplans)
Definition: createplan.c:5928
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
Definition: createplan.c:5599
static BitmapAnd * make_bitmap_and(List *bitmapplans)
Definition: createplan.c:5913
static Scan * create_indexscan_plan(PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, bool indexonly)
Definition: createplan.c:3000
List * list_concat_unique(List *list1, const List *list2)
Definition: list.c:1405
Expr * make_ands_explicit(List *andclauses)
Definition: makefuncs.c:726
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:670
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:469
Selectivity bitmapselectivity
Definition: pathnodes.h:1798
List * bitmapquals
Definition: pathnodes.h:1797
Selectivity bitmapselectivity
Definition: pathnodes.h:1811
List * bitmapquals
Definition: pathnodes.h:1810
List * indexquals
Definition: pathnodes.h:1759
struct RestrictInfo * rinfo
Definition: pathnodes.h:1758
List * indpred
Definition: pathnodes.h:1165
List * indexclauses
Definition: pathnodes.h:1711
Path path
Definition: pathnodes.h:1709
Selectivity indexselectivity
Definition: pathnodes.h:1716
Cost indextotalcost
Definition: pathnodes.h:1715
IndexOptInfo * indexinfo
Definition: pathnodes.h:1710
Scan scan
Definition: plannodes.h:451
List * indexqualorig
Definition: plannodes.h:454
Oid indexid
Definition: plannodes.h:452
List * indexqual
Definition: plannodes.h:453
Index scanrelid
Definition: plannodes.h:389

References Assert, BitmapAndPath::bitmapquals, BitmapOrPath::bitmapquals, BitmapAndPath::bitmapselectivity, BitmapOrPath::bitmapselectivity, castNode, clamp_row_est(), RestrictInfo::clause, create_indexscan_plan(), elog, ERROR, get_actual_clauses(), IndexPath::indexclauses, IndexScan::indexid, IndexPath::indexinfo, IndexScan::indexqual, IndexScan::indexqualorig, IndexClause::indexquals, IndexPath::indexselectivity, IndexPath::indextotalcost, IndexOptInfo::indpred, IsA, lappend(), lfirst, linitial, list_concat(), list_concat_unique(), list_length(), list_make1, make_ands_explicit(), make_bitmap_and(), make_bitmap_indexscan(), make_bitmap_or(), make_orclause(), NIL, nodeTag, Path::parallel_safe, IndexPath::path, BitmapAndPath::path, BitmapOrPath::path, plan, predicate_implied_by(), IndexClause::rinfo, root, IndexScan::scan, Scan::scanrelid, Path::startup_cost, and Path::total_cost.

Referenced by create_bitmap_scan_plan().

◆ create_ctescan_plan()

static CteScan * create_ctescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3885 of file createplan.c.

3887 {
3888  CteScan *scan_plan;
3889  Index scan_relid = best_path->parent->relid;
3890  RangeTblEntry *rte;
3891  SubPlan *ctesplan = NULL;
3892  int plan_id;
3893  int cte_param_id;
3894  PlannerInfo *cteroot;
3895  Index levelsup;
3896  int ndx;
3897  ListCell *lc;
3898 
3899  Assert(scan_relid > 0);
3900  rte = planner_rt_fetch(scan_relid, root);
3901  Assert(rte->rtekind == RTE_CTE);
3902  Assert(!rte->self_reference);
3903 
3904  /*
3905  * Find the referenced CTE, and locate the SubPlan previously made for it.
3906  */
3907  levelsup = rte->ctelevelsup;
3908  cteroot = root;
3909  while (levelsup-- > 0)
3910  {
3911  cteroot = cteroot->parent_root;
3912  if (!cteroot) /* shouldn't happen */
3913  elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3914  }
3915 
3916  /*
3917  * Note: cte_plan_ids can be shorter than cteList, if we are still working
3918  * on planning the CTEs (ie, this is a side-reference from another CTE).
3919  * So we mustn't use forboth here.
3920  */
3921  ndx = 0;
3922  foreach(lc, cteroot->parse->cteList)
3923  {
3924  CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
3925 
3926  if (strcmp(cte->ctename, rte->ctename) == 0)
3927  break;
3928  ndx++;
3929  }
3930  if (lc == NULL) /* shouldn't happen */
3931  elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
3932  if (ndx >= list_length(cteroot->cte_plan_ids))
3933  elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3934  plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
3935  if (plan_id <= 0)
3936  elog(ERROR, "no plan was made for CTE \"%s\"", rte->ctename);
3937  foreach(lc, cteroot->init_plans)
3938  {
3939  ctesplan = (SubPlan *) lfirst(lc);
3940  if (ctesplan->plan_id == plan_id)
3941  break;
3942  }
3943  if (lc == NULL) /* shouldn't happen */
3944  elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3945 
3946  /*
3947  * We need the CTE param ID, which is the sole member of the SubPlan's
3948  * setParam list.
3949  */
3950  cte_param_id = linitial_int(ctesplan->setParam);
3951 
3952  /* Sort clauses into best execution order */
3953  scan_clauses = order_qual_clauses(root, scan_clauses);
3954 
3955  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3956  scan_clauses = extract_actual_clauses(scan_clauses, false);
3957 
3958  /* Replace any outer-relation variables with nestloop params */
3959  if (best_path->param_info)
3960  {
3961  scan_clauses = (List *)
3962  replace_nestloop_params(root, (Node *) scan_clauses);
3963  }
3964 
3965  scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
3966  plan_id, cte_param_id);
3967 
3968  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3969 
3970  return scan_plan;
3971 }
static CteScan * make_ctescan(List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
Definition: createplan.c:5757
@ RTE_CTE
Definition: parsenodes.h:1034
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:564
#define linitial_int(l)
Definition: pg_list.h:179
static int list_nth_int(const List *list, int n)
Definition: pg_list.h:310
Scan scan
Definition: plannodes.h:642
List * cte_plan_ids
Definition: pathnodes.h:305
List * init_plans
Definition: pathnodes.h:299
Query * parse
Definition: pathnodes.h:202
List * cteList
Definition: parsenodes.h:166
char * ctename
Definition: parsenodes.h:1206
Index ctelevelsup
Definition: parsenodes.h:1208
RTEKind rtekind
Definition: parsenodes.h:1057
int plan_id
Definition: primnodes.h:1070
List * setParam
Definition: primnodes.h:1088

References Assert, copy_generic_path_info(), PlannerInfo::cte_plan_ids, RangeTblEntry::ctelevelsup, Query::cteList, RangeTblEntry::ctename, CommonTableExpr::ctename, elog, ERROR, extract_actual_clauses(), PlannerInfo::init_plans, lfirst, linitial_int, list_length(), list_nth_int(), make_ctescan(), order_qual_clauses(), PlannerInfo::parse, SubPlan::plan_id, planner_rt_fetch, replace_nestloop_params(), root, RTE_CTE, RangeTblEntry::rtekind, CteScan::scan, and SubPlan::setParam.

Referenced by create_scan_plan().

◆ create_customscan_plan()

static CustomScan * create_customscan_plan ( PlannerInfo root,
CustomPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 4271 of file createplan.c.

4273 {
4274  CustomScan *cplan;
4275  RelOptInfo *rel = best_path->path.parent;
4276  List *custom_plans = NIL;
4277  ListCell *lc;
4278 
4279  /* Recursively transform child paths. */
4280  foreach(lc, best_path->custom_paths)
4281  {
4283  CP_EXACT_TLIST);
4284 
4285  custom_plans = lappend(custom_plans, plan);
4286  }
4287 
4288  /*
4289  * Sort clauses into the best execution order, although custom-scan
4290  * provider can reorder them again.
4291  */
4292  scan_clauses = order_qual_clauses(root, scan_clauses);
4293 
4294  /*
4295  * Invoke custom plan provider to create the Plan node represented by the
4296  * CustomPath.
4297  */
4298  cplan = castNode(CustomScan,
4299  best_path->methods->PlanCustomPath(root,
4300  rel,
4301  best_path,
4302  tlist,
4303  scan_clauses,
4304  custom_plans));
4305 
4306  /*
4307  * Copy cost data from Path to Plan; no need to make custom-plan providers
4308  * do this
4309  */
4310  copy_generic_path_info(&cplan->scan.plan, &best_path->path);
4311 
4312  /* Likewise, copy the relids that are represented by this custom scan */
4313  cplan->custom_relids = best_path->path.parent->relids;
4314 
4315  /*
4316  * Replace any outer-relation variables with nestloop params in the qual
4317  * and custom_exprs expressions. We do this last so that the custom-plan
4318  * provider doesn't have to be involved. (Note that parts of custom_exprs
4319  * could have come from join clauses, so doing this beforehand on the
4320  * scan_clauses wouldn't work.) We assume custom_scan_tlist contains no
4321  * such variables.
4322  */
4323  if (best_path->path.param_info)
4324  {
4325  cplan->scan.plan.qual = (List *)
4326  replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
4327  cplan->custom_exprs = (List *)
4329  }
4330 
4331  return cplan;
4332 }
struct Plan *(* PlanCustomPath)(PlannerInfo *root, RelOptInfo *rel, struct CustomPath *best_path, List *tlist, List *clauses, List *custom_plans)
Definition: extensible.h:97
const struct CustomPathMethods * methods
Definition: pathnodes.h:1911
List * custom_paths
Definition: pathnodes.h:1908
Scan scan
Definition: plannodes.h:741
Bitmapset * custom_relids
Definition: plannodes.h:748
List * custom_exprs
Definition: plannodes.h:745

References castNode, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), CustomScan::custom_exprs, CustomPath::custom_paths, CustomScan::custom_relids, lappend(), lfirst, CustomPath::methods, NIL, order_qual_clauses(), CustomPath::path, plan, CustomPathMethods::PlanCustomPath, replace_nestloop_params(), root, and CustomScan::scan.

Referenced by create_scan_plan().

◆ create_foreignscan_plan()

static ForeignScan * create_foreignscan_plan ( PlannerInfo root,
ForeignPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 4116 of file createplan.c.

4118 {
4119  ForeignScan *scan_plan;
4120  RelOptInfo *rel = best_path->path.parent;
4121  Index scan_relid = rel->relid;
4122  Oid rel_oid = InvalidOid;
4123  Plan *outer_plan = NULL;
4124 
4125  Assert(rel->fdwroutine != NULL);
4126 
4127  /* transform the child path if any */
4128  if (best_path->fdw_outerpath)
4129  outer_plan = create_plan_recurse(root, best_path->fdw_outerpath,
4130  CP_EXACT_TLIST);
4131 
4132  /*
4133  * If we're scanning a base relation, fetch its OID. (Irrelevant if
4134  * scanning a join relation.)
4135  */
4136  if (scan_relid > 0)
4137  {
4138  RangeTblEntry *rte;
4139 
4140  Assert(rel->rtekind == RTE_RELATION);
4141  rte = planner_rt_fetch(scan_relid, root);
4142  Assert(rte->rtekind == RTE_RELATION);
4143  rel_oid = rte->relid;
4144  }
4145 
4146  /*
4147  * Sort clauses into best execution order. We do this first since the FDW
4148  * might have more info than we do and wish to adjust the ordering.
4149  */
4150  scan_clauses = order_qual_clauses(root, scan_clauses);
4151 
4152  /*
4153  * Let the FDW perform its processing on the restriction clauses and
4154  * generate the plan node. Note that the FDW might remove restriction
4155  * clauses that it intends to execute remotely, or even add more (if it
4156  * has selected some join clauses for remote use but also wants them
4157  * rechecked locally).
4158  */
4159  scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid,
4160  best_path,
4161  tlist, scan_clauses,
4162  outer_plan);
4163 
4164  /* Copy cost data from Path to Plan; no need to make FDW do this */
4165  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
4166 
4167  /* Copy user OID to access as; likewise no need to make FDW do this */
4168  scan_plan->checkAsUser = rel->userid;
4169 
4170  /* Copy foreign server OID; likewise, no need to make FDW do this */
4171  scan_plan->fs_server = rel->serverid;
4172 
4173  /*
4174  * Likewise, copy the relids that are represented by this foreign scan. An
4175  * upper rel doesn't have relids set, but it covers all the relations
4176  * participating in the underlying scan/join, so use root->all_query_rels.
4177  */
4178  if (rel->reloptkind == RELOPT_UPPER_REL)
4179  scan_plan->fs_relids = root->all_query_rels;
4180  else
4181  scan_plan->fs_relids = best_path->path.parent->relids;
4182 
4183  /*
4184  * Join relid sets include relevant outer joins, but FDWs may need to know
4185  * which are the included base rels. That's a bit tedious to get without
4186  * access to the plan-time data structures, so compute it here.
4187  */
4188  scan_plan->fs_base_relids = bms_difference(scan_plan->fs_relids,
4189  root->outer_join_rels);
4190 
4191  /*
4192  * If this is a foreign join, and to make it valid to push down we had to
4193  * assume that the current user is the same as some user explicitly named
4194  * in the query, mark the finished plan as depending on the current user.
4195  */
4196  if (rel->useridiscurrent)
4197  root->glob->dependsOnRole = true;
4198 
4199  /*
4200  * Replace any outer-relation variables with nestloop params in the qual,
4201  * fdw_exprs and fdw_recheck_quals expressions. We do this last so that
4202  * the FDW doesn't have to be involved. (Note that parts of fdw_exprs or
4203  * fdw_recheck_quals could have come from join clauses, so doing this
4204  * beforehand on the scan_clauses wouldn't work.) We assume
4205  * fdw_scan_tlist contains no such variables.
4206  */
4207  if (best_path->path.param_info)
4208  {
4209  scan_plan->scan.plan.qual = (List *)
4210  replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
4211  scan_plan->fdw_exprs = (List *)
4212  replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
4213  scan_plan->fdw_recheck_quals = (List *)
4215  (Node *) scan_plan->fdw_recheck_quals);
4216  }
4217 
4218  /*
4219  * If rel is a base relation, detect whether any system columns are
4220  * requested from the rel. (If rel is a join relation, rel->relid will be
4221  * 0, but there can be no Var with relid 0 in the rel's targetlist or the
4222  * restriction clauses, so we skip this in that case. Note that any such
4223  * columns in base relations that were joined are assumed to be contained
4224  * in fdw_scan_tlist.) This is a bit of a kluge and might go away
4225  * someday, so we intentionally leave it out of the API presented to FDWs.
4226  */
4227  scan_plan->fsSystemCol = false;
4228  if (scan_relid > 0)
4229  {
4230  Bitmapset *attrs_used = NULL;
4231  ListCell *lc;
4232  int i;
4233 
4234  /*
4235  * First, examine all the attributes needed for joins or final output.
4236  * Note: we must look at rel's targetlist, not the attr_needed data,
4237  * because attr_needed isn't computed for inheritance child rels.
4238  */
4239  pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used);
4240 
4241  /* Add all the attributes used by restriction clauses. */
4242  foreach(lc, rel->baserestrictinfo)
4243  {
4244  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
4245 
4246  pull_varattnos((Node *) rinfo->clause, scan_relid, &attrs_used);
4247  }
4248 
4249  /* Now, are any system columns requested from rel? */
4250  for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
4251  {
4253  {
4254  scan_plan->fsSystemCol = true;
4255  break;
4256  }
4257  }
4258 
4259  bms_free(attrs_used);
4260  }
4261 
4262  return scan_plan;
4263 }
void bms_free(Bitmapset *a)
Definition: bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:346
int i
Definition: isn.c:73
@ RELOPT_UPPER_REL
Definition: pathnodes.h:825
#define InvalidOid
Definition: postgres_ext.h:36
Path * fdw_outerpath
Definition: pathnodes.h:1870
Oid checkAsUser
Definition: plannodes.h:712
Oid fs_server
Definition: plannodes.h:714
List * fdw_exprs
Definition: plannodes.h:715
bool fsSystemCol
Definition: plannodes.h:721
Bitmapset * fs_relids
Definition: plannodes.h:719
Bitmapset * fs_base_relids
Definition: plannodes.h:720
List * fdw_recheck_quals
Definition: plannodes.h:718
List * exprs
Definition: pathnodes.h:1533
bool useridiscurrent
Definition: pathnodes.h:962
struct PathTarget * reltarget
Definition: pathnodes.h:887
Index relid
Definition: pathnodes.h:912
RelOptKind reloptkind
Definition: pathnodes.h:859
Oid userid
Definition: pathnodes.h:960
Oid serverid
Definition: pathnodes.h:958
RTEKind rtekind
Definition: pathnodes.h:916
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:291

References Assert, RelOptInfo::baserestrictinfo, bms_difference(), bms_free(), bms_is_member(), ForeignScan::checkAsUser, RestrictInfo::clause, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), PathTarget::exprs, ForeignScan::fdw_exprs, ForeignPath::fdw_outerpath, ForeignScan::fdw_recheck_quals, FirstLowInvalidHeapAttributeNumber, ForeignScan::fs_base_relids, ForeignScan::fs_relids, ForeignScan::fs_server, ForeignScan::fsSystemCol, i, InvalidOid, lfirst, order_qual_clauses(), ForeignPath::path, planner_rt_fetch, pull_varattnos(), RangeTblEntry::relid, RelOptInfo::relid, RELOPT_UPPER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, replace_nestloop_params(), root, RTE_RELATION, RangeTblEntry::rtekind, RelOptInfo::rtekind, ForeignScan::scan, RelOptInfo::serverid, RelOptInfo::userid, and RelOptInfo::useridiscurrent.

Referenced by create_scan_plan().

◆ create_functionscan_plan()

static FunctionScan * create_functionscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3755 of file createplan.c.

3757 {
3758  FunctionScan *scan_plan;
3759  Index scan_relid = best_path->parent->relid;
3760  RangeTblEntry *rte;
3761  List *functions;
3762 
3763  /* it should be a function base rel... */
3764  Assert(scan_relid > 0);
3765  rte = planner_rt_fetch(scan_relid, root);
3766  Assert(rte->rtekind == RTE_FUNCTION);
3767  functions = rte->functions;
3768 
3769  /* Sort clauses into best execution order */
3770  scan_clauses = order_qual_clauses(root, scan_clauses);
3771 
3772  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3773  scan_clauses = extract_actual_clauses(scan_clauses, false);
3774 
3775  /* Replace any outer-relation variables with nestloop params */
3776  if (best_path->param_info)
3777  {
3778  scan_clauses = (List *)
3779  replace_nestloop_params(root, (Node *) scan_clauses);
3780  /* The function expressions could contain nestloop params, too */
3782  }
3783 
3784  scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3785  functions, rte->funcordinality);
3786 
3787  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3788 
3789  return scan_plan;
3790 }
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5698
@ RTE_FUNCTION
Definition: parsenodes.h:1031
static const struct fns functions
Definition: regcomp.c:356
bool funcordinality
Definition: parsenodes.h:1189
List * functions
Definition: parsenodes.h:1187

References Assert, copy_generic_path_info(), extract_actual_clauses(), RangeTblEntry::funcordinality, functions, RangeTblEntry::functions, make_functionscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_FUNCTION, RangeTblEntry::rtekind, and FunctionScan::scan.

Referenced by create_scan_plan().

◆ create_gather_merge_plan()

static GatherMerge * create_gather_merge_plan ( PlannerInfo root,
GatherMergePath best_path 
)
static

Definition at line 1957 of file createplan.c.

1958 {
1959  GatherMerge *gm_plan;
1960  Plan *subplan;
1961  List *pathkeys = best_path->path.pathkeys;
1962  List *tlist = build_path_tlist(root, &best_path->path);
1963 
1964  /* As with Gather, project away columns in the workers. */
1965  subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1966 
1967  /* Create a shell for a GatherMerge plan. */
1968  gm_plan = makeNode(GatherMerge);
1969  gm_plan->plan.targetlist = tlist;
1970  gm_plan->num_workers = best_path->num_workers;
1971  copy_generic_path_info(&gm_plan->plan, &best_path->path);
1972 
1973  /* Assign the rescan Param. */
1975 
1976  /* Gather Merge is pointless with no pathkeys; use Gather instead. */
1977  Assert(pathkeys != NIL);
1978 
1979  /* Compute sort column info, and adjust subplan's tlist as needed */
1980  subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1981  best_path->subpath->parent->relids,
1982  gm_plan->sortColIdx,
1983  false,
1984  &gm_plan->numCols,
1985  &gm_plan->sortColIdx,
1986  &gm_plan->sortOperators,
1987  &gm_plan->collations,
1988  &gm_plan->nullsFirst);
1989 
1990  /*
1991  * All gather merge paths should have already guaranteed the necessary
1992  * sort order. See create_gather_merge_path.
1993  */
1994  Assert(pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys));
1995 
1996  /* Now insert the subplan under GatherMerge. */
1997  gm_plan->plan.lefttree = subplan;
1998 
1999  /* use parallel mode for parallel plans. */
2000  root->glob->parallelModeNeeded = true;
2001 
2002  return gm_plan;
2003 }
int assign_special_exec_param(PlannerInfo *root)
Definition: paramassign.c:664
int rescan_param
Definition: plannodes.h:1163
int num_workers
Definition: plannodes.h:1160
struct Plan * lefttree
Definition: plannodes.h:154

References Assert, assign_special_exec_param(), build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), Plan::lefttree, makeNode, NIL, GatherMergePath::num_workers, GatherMerge::num_workers, GatherMerge::numCols, GatherMergePath::path, Path::pathkeys, pathkeys_contained_in(), GatherMerge::plan, prepare_sort_from_pathkeys(), GatherMerge::rescan_param, root, GatherMergePath::subpath, and Plan::targetlist.

Referenced by create_plan_recurse().

◆ create_gather_plan()

static Gather * create_gather_plan ( PlannerInfo root,
GatherPath best_path 
)
static

Definition at line 1919 of file createplan.c.

1920 {
1921  Gather *gather_plan;
1922  Plan *subplan;
1923  List *tlist;
1924 
1925  /*
1926  * Push projection down to the child node. That way, the projection work
1927  * is parallelized, and there can be no system columns in the result (they
1928  * can't travel through a tuple queue because it uses MinimalTuple
1929  * representation).
1930  */
1931  subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1932 
1933  tlist = build_path_tlist(root, &best_path->path);
1934 
1935  gather_plan = make_gather(tlist,
1936  NIL,
1937  best_path->num_workers,
1939  best_path->single_copy,
1940  subplan);
1941 
1942  copy_generic_path_info(&gather_plan->plan, &best_path->path);
1943 
1944  /* use parallel mode for parallel plans. */
1945  root->glob->parallelModeNeeded = true;
1946 
1947  return gather_plan;
1948 }
static Gather * make_gather(List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)
Definition: createplan.c:6849
bool single_copy
Definition: pathnodes.h:2043
Path * subpath
Definition: pathnodes.h:2042
int num_workers
Definition: pathnodes.h:2044
Plan plan
Definition: plannodes.h:1142

References assign_special_exec_param(), build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), make_gather(), NIL, GatherPath::num_workers, GatherPath::path, Gather::plan, root, GatherPath::single_copy, and GatherPath::subpath.

Referenced by create_plan_recurse().

◆ create_gating_plan()

static Plan * create_gating_plan ( PlannerInfo root,
Path path,
Plan plan,
List gating_quals 
)
static

Definition at line 1022 of file createplan.c.

1024 {
1025  Plan *gplan;
1026  Plan *splan;
1027 
1028  Assert(gating_quals);
1029 
1030  /*
1031  * We might have a trivial Result plan already. Stacking one Result atop
1032  * another is silly, so if that applies, just discard the input plan.
1033  * (We're assuming its targetlist is uninteresting; it should be either
1034  * the same as the result of build_path_tlist, or a simplified version.)
1035  */
1036  splan = plan;
1037  if (IsA(plan, Result))
1038  {
1039  Result *rplan = (Result *) plan;
1040 
1041  if (rplan->plan.lefttree == NULL &&
1042  rplan->resconstantqual == NULL)
1043  splan = NULL;
1044  }
1045 
1046  /*
1047  * Since we need a Result node anyway, always return the path's requested
1048  * tlist; that's never a wrong choice, even if the parent node didn't ask
1049  * for CP_EXACT_TLIST.
1050  */
1051  gplan = (Plan *) make_result(build_path_tlist(root, path),
1052  (Node *) gating_quals,
1053  splan);
1054 
1055  /*
1056  * Notice that we don't change cost or size estimates when doing gating.
1057  * The costs of qual eval were already included in the subplan's cost.
1058  * Leaving the size alone amounts to assuming that the gating qual will
1059  * succeed, which is the conservative estimate for planning upper queries.
1060  * We certainly don't want to assume the output size is zero (unless the
1061  * gating qual is actually constant FALSE, and that case is dealt with in
1062  * clausesel.c). Interpolating between the two cases is silly, because it
1063  * doesn't reflect what will really happen at runtime, and besides which
1064  * in most cases we have only a very bad idea of the probability of the
1065  * gating qual being true.
1066  */
1067  copy_plan_costsize(gplan, plan);
1068 
1069  /* Gating quals could be unsafe, so better use the Path's safety flag */
1070  gplan->parallel_safe = path->parallel_safe;
1071 
1072  return gplan;
1073 }
static void copy_plan_costsize(Plan *dest, Plan *src)
Definition: createplan.c:5419
static SPIPlanPtr splan
Definition: regress.c:269
Node * resconstantqual
Definition: plannodes.h:199
Plan plan
Definition: plannodes.h:198

References Assert, build_path_tlist(), copy_plan_costsize(), IsA, Plan::lefttree, make_result(), Path::parallel_safe, Plan::parallel_safe, Result::plan, plan, Result::resconstantqual, root, and splan.

Referenced by create_join_plan(), and create_scan_plan().

◆ create_group_plan()

static Group * create_group_plan ( PlannerInfo root,
GroupPath best_path 
)
static

Definition at line 2236 of file createplan.c.

2237 {
2238  Group *plan;
2239  Plan *subplan;
2240  List *tlist;
2241  List *quals;
2242 
2243  /*
2244  * Group can project, so no need to be terribly picky about child tlist,
2245  * but we do need grouping columns to be available
2246  */
2247  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2248 
2249  tlist = build_path_tlist(root, &best_path->path);
2250 
2251  quals = order_qual_clauses(root, best_path->qual);
2252 
2253  plan = make_group(tlist,
2254  quals,
2255  list_length(best_path->groupClause),
2257  subplan->targetlist),
2258  extract_grouping_ops(best_path->groupClause),
2260  subplan->targetlist),
2261  subplan);
2262 
2263  copy_generic_path_info(&plan->plan, (Path *) best_path);
2264 
2265  return plan;
2266 }
static Group * make_group(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, Plan *lefttree)
Definition: createplan.c:6664
List * qual
Definition: pathnodes.h:2228
List * groupClause
Definition: pathnodes.h:2227
Path * subpath
Definition: pathnodes.h:2226
Path path
Definition: pathnodes.h:2225

References build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_cols(), extract_grouping_ops(), GroupPath::groupClause, list_length(), make_group(), order_qual_clauses(), GroupPath::path, plan, GroupPath::qual, root, GroupPath::subpath, and Plan::targetlist.

Referenced by create_plan_recurse().

◆ create_group_result_plan()

static Result * create_group_result_plan ( PlannerInfo root,
GroupResultPath best_path 
)
static

Definition at line 1587 of file createplan.c.

1588 {
1589  Result *plan;
1590  List *tlist;
1591  List *quals;
1592 
1593  tlist = build_path_tlist(root, &best_path->path);
1594 
1595  /* best_path->quals is just bare clauses */
1596  quals = order_qual_clauses(root, best_path->quals);
1597 
1598  plan = make_result(tlist, (Node *) quals, NULL);
1599 
1600  copy_generic_path_info(&plan->plan, (Path *) best_path);
1601 
1602  return plan;
1603 }

References build_path_tlist(), copy_generic_path_info(), make_result(), order_qual_clauses(), GroupResultPath::path, plan, GroupResultPath::quals, and root.

Referenced by create_plan_recurse().

◆ create_groupingsets_plan()

static Plan * create_groupingsets_plan ( PlannerInfo root,
GroupingSetsPath best_path 
)
static

Definition at line 2387 of file createplan.c.

2388 {
2389  Agg *plan;
2390  Plan *subplan;
2391  List *rollups = best_path->rollups;
2392  AttrNumber *grouping_map;
2393  int maxref;
2394  List *chain;
2395  ListCell *lc;
2396 
2397  /* Shouldn't get here without grouping sets */
2398  Assert(root->parse->groupingSets);
2399  Assert(rollups != NIL);
2400 
2401  /*
2402  * Agg can project, so no need to be terribly picky about child tlist, but
2403  * we do need grouping columns to be available
2404  */
2405  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2406 
2407  /*
2408  * Compute the mapping from tleSortGroupRef to column index in the child's
2409  * tlist. First, identify max SortGroupRef in groupClause, for array
2410  * sizing.
2411  */
2412  maxref = 0;
2413  foreach(lc, root->processed_groupClause)
2414  {
2415  SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
2416 
2417  if (gc->tleSortGroupRef > maxref)
2418  maxref = gc->tleSortGroupRef;
2419  }
2420 
2421  grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
2422 
2423  /* Now look up the column numbers in the child's tlist */
2424  foreach(lc, root->processed_groupClause)
2425  {
2426  SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
2427  TargetEntry *tle = get_sortgroupclause_tle(gc, subplan->targetlist);
2428 
2429  grouping_map[gc->tleSortGroupRef] = tle->resno;
2430  }
2431 
2432  /*
2433  * During setrefs.c, we'll need the grouping_map to fix up the cols lists
2434  * in GroupingFunc nodes. Save it for setrefs.c to use.
2435  */
2436  Assert(root->grouping_map == NULL);
2437  root->grouping_map = grouping_map;
2438 
2439  /*
2440  * Generate the side nodes that describe the other sort and group
2441  * operations besides the top one. Note that we don't worry about putting
2442  * accurate cost estimates in the side nodes; only the topmost Agg node's
2443  * costs will be shown by EXPLAIN.
2444  */
2445  chain = NIL;
2446  if (list_length(rollups) > 1)
2447  {
2448  bool is_first_sort = ((RollupData *) linitial(rollups))->is_hashed;
2449 
2450  for_each_from(lc, rollups, 1)
2451  {
2452  RollupData *rollup = lfirst(lc);
2453  AttrNumber *new_grpColIdx;
2454  Plan *sort_plan = NULL;
2455  Plan *agg_plan;
2456  AggStrategy strat;
2457 
2458  new_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2459 
2460  if (!rollup->is_hashed && !is_first_sort)
2461  {
2462  sort_plan = (Plan *)
2464  new_grpColIdx,
2465  subplan);
2466  }
2467 
2468  if (!rollup->is_hashed)
2469  is_first_sort = false;
2470 
2471  if (rollup->is_hashed)
2472  strat = AGG_HASHED;
2473  else if (linitial(rollup->gsets) == NIL)
2474  strat = AGG_PLAIN;
2475  else
2476  strat = AGG_SORTED;
2477 
2478  agg_plan = (Plan *) make_agg(NIL,
2479  NIL,
2480  strat,
2482  list_length((List *) linitial(rollup->gsets)),
2483  new_grpColIdx,
2486  rollup->gsets,
2487  NIL,
2488  rollup->numGroups,
2489  best_path->transitionSpace,
2490  sort_plan);
2491 
2492  /*
2493  * Remove stuff we don't need to avoid bloating debug output.
2494  */
2495  if (sort_plan)
2496  {
2497  sort_plan->targetlist = NIL;
2498  sort_plan->lefttree = NULL;
2499  }
2500 
2501  chain = lappend(chain, agg_plan);
2502  }
2503  }
2504 
2505  /*
2506  * Now make the real Agg node
2507  */
2508  {
2509  RollupData *rollup = linitial(rollups);
2510  AttrNumber *top_grpColIdx;
2511  int numGroupCols;
2512 
2513  top_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2514 
2515  numGroupCols = list_length((List *) linitial(rollup->gsets));
2516 
2517  plan = make_agg(build_path_tlist(root, &best_path->path),
2518  best_path->qual,
2519  best_path->aggstrategy,
2521  numGroupCols,
2522  top_grpColIdx,
2525  rollup->gsets,
2526  chain,
2527  rollup->numGroups,
2528  best_path->transitionSpace,
2529  subplan);
2530 
2531  /* Copy cost data from Path to Plan */
2532  copy_generic_path_info(&plan->plan, &best_path->path);
2533  }
2534 
2535  return (Plan *) plan;
2536 }
static AttrNumber * remap_groupColIdx(PlannerInfo *root, List *groupClause)
Definition: createplan.c:2349
static Sort * make_sort_from_groupcols(List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
Definition: createplan.c:6459
void * palloc0(Size size)
Definition: mcxt.c:1347
AggStrategy
Definition: nodes.h:353
@ AGG_SORTED
Definition: nodes.h:355
@ AGG_HASHED
Definition: nodes.h:356
@ AGG_PLAIN
Definition: nodes.h:354
@ AGGSPLIT_SIMPLE
Definition: nodes.h:377
#define for_each_from(cell, lst, N)
Definition: pg_list.h:414
uint64 transitionSpace
Definition: pathnodes.h:2300
AggStrategy aggstrategy
Definition: pathnodes.h:2297
Cardinality numGroups
Definition: pathnodes.h:2284
List * groupClause
Definition: pathnodes.h:2281
List * gsets
Definition: pathnodes.h:2282
bool is_hashed
Definition: pathnodes.h:2286
Index tleSortGroupRef
Definition: parsenodes.h:1442
AttrNumber resno
Definition: primnodes.h:2188
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:367

References AGG_HASHED, AGG_PLAIN, AGG_SORTED, AGGSPLIT_SIMPLE, GroupingSetsPath::aggstrategy, Assert, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_ops(), for_each_from, get_sortgroupclause_tle(), RollupData::groupClause, RollupData::gsets, RollupData::is_hashed, lappend(), Plan::lefttree, lfirst, linitial, list_length(), make_agg(), make_sort_from_groupcols(), NIL, RollupData::numGroups, palloc0(), GroupingSetsPath::path, plan, GroupingSetsPath::qual, remap_groupColIdx(), TargetEntry::resno, GroupingSetsPath::rollups, root, GroupingSetsPath::subpath, Plan::targetlist, SortGroupClause::tleSortGroupRef, and GroupingSetsPath::transitionSpace.

Referenced by create_plan_recurse().

◆ create_hashjoin_plan()

static HashJoin * create_hashjoin_plan ( PlannerInfo root,
HashPath best_path 
)
static

Definition at line 4741 of file createplan.c.

4743 {
4744  HashJoin *join_plan;
4745  Hash *hash_plan;
4746  Plan *outer_plan;
4747  Plan *inner_plan;
4748  List *tlist = build_path_tlist(root, &best_path->jpath.path);
4749  List *joinclauses;
4750  List *otherclauses;
4751  List *hashclauses;
4752  List *hashoperators = NIL;
4753  List *hashcollations = NIL;
4754  List *inner_hashkeys = NIL;
4755  List *outer_hashkeys = NIL;
4756  Oid skewTable = InvalidOid;
4757  AttrNumber skewColumn = InvalidAttrNumber;
4758  bool skewInherit = false;
4759  ListCell *lc;
4760 
4761  /*
4762  * HashJoin can project, so we don't have to demand exact tlists from the
4763  * inputs. However, it's best to request a small tlist from the inner
4764  * side, so that we aren't storing more data than necessary. Likewise, if
4765  * we anticipate batching, request a small tlist from the outer side so
4766  * that we don't put extra data in the outer batch files.
4767  */
4768  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4769  (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
4770 
4771  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4772  CP_SMALL_TLIST);
4773 
4774  /* Sort join qual clauses into best execution order */
4775  joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4776  /* There's no point in sorting the hash clauses ... */
4777 
4778  /* Get the join qual clauses (in plain expression form) */
4779  /* Any pseudoconstant clauses are ignored here */
4780  if (IS_OUTER_JOIN(best_path->jpath.jointype))
4781  {
4782  extract_actual_join_clauses(joinclauses,
4783  best_path->jpath.path.parent->relids,
4784  &joinclauses, &otherclauses);
4785  }
4786  else
4787  {
4788  /* We can treat all clauses alike for an inner join */
4789  joinclauses = extract_actual_clauses(joinclauses, false);
4790  otherclauses = NIL;
4791  }
4792 
4793  /*
4794  * Remove the hashclauses from the list of join qual clauses, leaving the
4795  * list of quals that must be checked as qpquals.
4796  */
4797  hashclauses = get_actual_clauses(best_path->path_hashclauses);
4798  joinclauses = list_difference(joinclauses, hashclauses);
4799 
4800  /*
4801  * Replace any outer-relation variables with nestloop params. There
4802  * should not be any in the hashclauses.
4803  */
4804  if (best_path->jpath.path.param_info)
4805  {
4806  joinclauses = (List *)
4807  replace_nestloop_params(root, (Node *) joinclauses);
4808  otherclauses = (List *)
4809  replace_nestloop_params(root, (Node *) otherclauses);
4810  }
4811 
4812  /*
4813  * Rearrange hashclauses, if needed, so that the outer variable is always
4814  * on the left.
4815  */
4816  hashclauses = get_switched_clauses(best_path->path_hashclauses,
4817  best_path->jpath.outerjoinpath->parent->relids);
4818 
4819  /*
4820  * If there is a single join clause and we can identify the outer variable
4821  * as a simple column reference, supply its identity for possible use in
4822  * skew optimization. (Note: in principle we could do skew optimization
4823  * with multiple join clauses, but we'd have to be able to determine the
4824  * most common combinations of outer values, which we don't currently have
4825  * enough stats for.)
4826  */
4827  if (list_length(hashclauses) == 1)
4828  {
4829  OpExpr *clause = (OpExpr *) linitial(hashclauses);
4830  Node *node;
4831 
4832  Assert(is_opclause(clause));
4833  node = (Node *) linitial(clause->args);
4834  if (IsA(node, RelabelType))
4835  node = (Node *) ((RelabelType *) node)->arg;
4836  if (IsA(node, Var))
4837  {
4838  Var *var = (Var *) node;
4839  RangeTblEntry *rte;
4840 
4841  rte = root->simple_rte_array[var->varno];
4842  if (rte->rtekind == RTE_RELATION)
4843  {
4844  skewTable = rte->relid;
4845  skewColumn = var->varattno;
4846  skewInherit = rte->inh;
4847  }
4848  }
4849  }
4850 
4851  /*
4852  * Collect hash related information. The hashed expressions are
4853  * deconstructed into outer/inner expressions, so they can be computed
4854  * separately (inner expressions are used to build the hashtable via Hash,
4855  * outer expressions to perform lookups of tuples from HashJoin's outer
4856  * plan in the hashtable). Also collect operator information necessary to
4857  * build the hashtable.
4858  */
4859  foreach(lc, hashclauses)
4860  {
4861  OpExpr *hclause = lfirst_node(OpExpr, lc);
4862 
4863  hashoperators = lappend_oid(hashoperators, hclause->opno);
4864  hashcollations = lappend_oid(hashcollations, hclause->inputcollid);
4865  outer_hashkeys = lappend(outer_hashkeys, linitial(hclause->args));
4866  inner_hashkeys = lappend(inner_hashkeys, lsecond(hclause->args));
4867  }
4868 
4869  /*
4870  * Build the hash node and hash join node.
4871  */
4872  hash_plan = make_hash(inner_plan,
4873  inner_hashkeys,
4874  skewTable,
4875  skewColumn,
4876  skewInherit);
4877 
4878  /*
4879  * Set Hash node's startup & total costs equal to total cost of input
4880  * plan; this only affects EXPLAIN display not decisions.
4881  */
4882  copy_plan_costsize(&hash_plan->plan, inner_plan);
4883  hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
4884 
4885  /*
4886  * If parallel-aware, the executor will also need an estimate of the total
4887  * number of rows expected from all participants so that it can size the
4888  * shared hash table.
4889  */
4890  if (best_path->jpath.path.parallel_aware)
4891  {
4892  hash_plan->plan.parallel_aware = true;
4893  hash_plan->rows_total = best_path->inner_rows_total;
4894  }
4895 
4896  join_plan = make_hashjoin(tlist,
4897  joinclauses,
4898  otherclauses,
4899  hashclauses,
4900  hashoperators,
4901  hashcollations,
4902  outer_hashkeys,
4903  outer_plan,
4904  (Plan *) hash_plan,
4905  best_path->jpath.jointype,
4906  best_path->jpath.inner_unique);
4907 
4908  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4909 
4910  return join_plan;
4911 }
#define InvalidAttrNumber
Definition: attnum.h:23
static HashJoin * make_hashjoin(List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, List *hashoperators, List *hashcollations, List *hashkeys, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
Definition: createplan.c:5968
static List * get_switched_clauses(List *clauses, Relids outerrelids)
Definition: createplan.c:5233
static Hash * make_hash(Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
Definition: createplan.c:5999
List * lappend_oid(List *list, Oid datum)
Definition: list.c:375
List * list_difference(const List *list1, const List *list2)
Definition: list.c:1237
static bool is_opclause(const void *clause)
Definition: nodeFuncs.h:74
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:338
#define lsecond(l)
Definition: pg_list.h:183
void extract_actual_join_clauses(List *restrictinfo_list, Relids joinrelids, List **joinquals, List **otherquals)
Definition: restrictinfo.c:522
Join join
Definition: plannodes.h:864
List * path_hashclauses
Definition: pathnodes.h:2152
Cardinality inner_rows_total
Definition: pathnodes.h:2154
int num_batches
Definition: pathnodes.h:2153
JoinPath jpath
Definition: pathnodes.h:2151
Cardinality rows_total
Definition: plannodes.h:1210
Plan plan
Definition: plannodes.h:1199
Path * outerjoinpath
Definition: pathnodes.h:2074
Path * innerjoinpath
Definition: pathnodes.h:2075
JoinType jointype
Definition: pathnodes.h:2069
bool inner_unique
Definition: pathnodes.h:2071
List * joinrestrictinfo
Definition: pathnodes.h:2077
Oid opno
Definition: primnodes.h:818
List * args
Definition: primnodes.h:836
bool parallel_aware
Definition: plannodes.h:140
Definition: primnodes.h:248
AttrNumber varattno
Definition: primnodes.h:260
int varno
Definition: primnodes.h:255

References OpExpr::args, Assert, build_path_tlist(), copy_generic_path_info(), copy_plan_costsize(), CP_SMALL_TLIST, create_plan_recurse(), extract_actual_clauses(), extract_actual_join_clauses(), get_actual_clauses(), get_switched_clauses(), RangeTblEntry::inh, HashPath::inner_rows_total, JoinPath::inner_unique, JoinPath::innerjoinpath, InvalidAttrNumber, InvalidOid, is_opclause(), IS_OUTER_JOIN, IsA, HashJoin::join, JoinPath::joinrestrictinfo, JoinPath::jointype, HashPath::jpath, lappend(), lappend_oid(), lfirst_node, linitial, list_difference(), list_length(), lsecond, make_hash(), make_hashjoin(), NIL, HashPath::num_batches, OpExpr::opno, order_qual_clauses(), JoinPath::outerjoinpath, Plan::parallel_aware, HashPath::path_hashclauses, Hash::plan, RangeTblEntry::relid, replace_nestloop_params(), root, Hash::rows_total, RTE_RELATION, RangeTblEntry::rtekind, Plan::startup_cost, Plan::total_cost, Var::varattno, and Var::varno.

Referenced by create_join_plan().

◆ create_incrementalsort_plan()

static IncrementalSort * create_incrementalsort_plan ( PlannerInfo root,
IncrementalSortPath best_path,
int  flags 
)
static

Definition at line 2209 of file createplan.c.

2211 {
2213  Plan *subplan;
2214 
2215  /* See comments in create_sort_plan() above */
2216  subplan = create_plan_recurse(root, best_path->spath.subpath,
2217  flags | CP_SMALL_TLIST);
2219  best_path->spath.path.pathkeys,
2220  IS_OTHER_REL(best_path->spath.subpath->parent) ?
2221  best_path->spath.path.parent->relids : NULL,
2222  best_path->nPresortedCols);
2223 
2224  copy_generic_path_info(&plan->sort.plan, (Path *) best_path);
2225 
2226  return plan;
2227 }
static IncrementalSort * make_incrementalsort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
Definition: createplan.c:6376
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:848
Path path
Definition: pathnodes.h:2199
Path * subpath
Definition: pathnodes.h:2200

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), IS_OTHER_REL, make_incrementalsort_from_pathkeys(), IncrementalSortPath::nPresortedCols, SortPath::path, Path::pathkeys, plan, root, IncrementalSortPath::spath, and SortPath::subpath.

Referenced by create_plan_recurse().

◆ create_indexscan_plan()

static Scan * create_indexscan_plan ( PlannerInfo root,
IndexPath best_path,
List tlist,
List scan_clauses,
bool  indexonly 
)
static

Definition at line 3000 of file createplan.c.

3005 {
3006  Scan *scan_plan;
3007  List *indexclauses = best_path->indexclauses;
3008  List *indexorderbys = best_path->indexorderbys;
3009  Index baserelid = best_path->path.parent->relid;
3010  IndexOptInfo *indexinfo = best_path->indexinfo;
3011  Oid indexoid = indexinfo->indexoid;
3012  List *qpqual;
3013  List *stripped_indexquals;
3014  List *fixed_indexquals;
3015  List *fixed_indexorderbys;
3016  List *indexorderbyops = NIL;
3017  ListCell *l;
3018 
3019  /* it should be a base rel... */
3020  Assert(baserelid > 0);
3021  Assert(best_path->path.parent->rtekind == RTE_RELATION);
3022  /* check the scan direction is valid */
3023  Assert(best_path->indexscandir == ForwardScanDirection ||
3024  best_path->indexscandir == BackwardScanDirection);
3025 
3026  /*
3027  * Extract the index qual expressions (stripped of RestrictInfos) from the
3028  * IndexClauses list, and prepare a copy with index Vars substituted for
3029  * table Vars. (This step also does replace_nestloop_params on the
3030  * fixed_indexquals.)
3031  */
3032  fix_indexqual_references(root, best_path,
3033  &stripped_indexquals,
3034  &fixed_indexquals);
3035 
3036  /*
3037  * Likewise fix up index attr references in the ORDER BY expressions.
3038  */
3039  fixed_indexorderbys = fix_indexorderby_references(root, best_path);
3040 
3041  /*
3042  * The qpqual list must contain all restrictions not automatically handled
3043  * by the index, other than pseudoconstant clauses which will be handled
3044  * by a separate gating plan node. All the predicates in the indexquals
3045  * will be checked (either by the index itself, or by nodeIndexscan.c),
3046  * but if there are any "special" operators involved then they must be
3047  * included in qpqual. The upshot is that qpqual must contain
3048  * scan_clauses minus whatever appears in indexquals.
3049  *
3050  * is_redundant_with_indexclauses() detects cases where a scan clause is
3051  * present in the indexclauses list or is generated from the same
3052  * EquivalenceClass as some indexclause, and is therefore redundant with
3053  * it, though not equal. (The latter happens when indxpath.c prefers a
3054  * different derived equality than what generate_join_implied_equalities
3055  * picked for a parameterized scan's ppi_clauses.) Note that it will not
3056  * match to lossy index clauses, which is critical because we have to
3057  * include the original clause in qpqual in that case.
3058  *
3059  * In some situations (particularly with OR'd index conditions) we may
3060  * have scan_clauses that are not equal to, but are logically implied by,
3061  * the index quals; so we also try a predicate_implied_by() check to see
3062  * if we can discard quals that way. (predicate_implied_by assumes its
3063  * first input contains only immutable functions, so we have to check
3064  * that.)
3065  *
3066  * Note: if you change this bit of code you should also look at
3067  * extract_nonindex_conditions() in costsize.c.
3068  */
3069  qpqual = NIL;
3070  foreach(l, scan_clauses)
3071  {
3072  RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
3073 
3074  if (rinfo->pseudoconstant)
3075  continue; /* we may drop pseudoconstants here */
3076  if (is_redundant_with_indexclauses(rinfo, indexclauses))
3077  continue; /* dup or derived from same EquivalenceClass */
3078  if (!contain_mutable_functions((Node *) rinfo->clause) &&
3079  predicate_implied_by(list_make1(rinfo->clause), stripped_indexquals,
3080  false))
3081  continue; /* provably implied by indexquals */
3082  qpqual = lappend(qpqual, rinfo);
3083  }
3084 
3085  /* Sort clauses into best execution order */
3086  qpqual = order_qual_clauses(root, qpqual);
3087 
3088  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3089  qpqual = extract_actual_clauses(qpqual, false);
3090 
3091  /*
3092  * We have to replace any outer-relation variables with nestloop params in
3093  * the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
3094  * annoying to have to do this separately from the processing in
3095  * fix_indexqual_references --- rethink this when generalizing the inner
3096  * indexscan support. But note we can't really do this earlier because
3097  * it'd break the comparisons to predicates above ... (or would it? Those
3098  * wouldn't have outer refs)
3099  */
3100  if (best_path->path.param_info)
3101  {
3102  stripped_indexquals = (List *)
3103  replace_nestloop_params(root, (Node *) stripped_indexquals);
3104  qpqual = (List *)
3105  replace_nestloop_params(root, (Node *) qpqual);
3106  indexorderbys = (List *)
3107  replace_nestloop_params(root, (Node *) indexorderbys);
3108  }
3109 
3110  /*
3111  * If there are ORDER BY expressions, look up the sort operators for their
3112  * result datatypes.
3113  */
3114  if (indexorderbys)
3115  {
3116  ListCell *pathkeyCell,
3117  *exprCell;
3118 
3119  /*
3120  * PathKey contains OID of the btree opfamily we're sorting by, but
3121  * that's not quite enough because we need the expression's datatype
3122  * to look up the sort operator in the operator family.
3123  */
3124  Assert(list_length(best_path->path.pathkeys) == list_length(indexorderbys));
3125  forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
3126  {
3127  PathKey *pathkey = (PathKey *) lfirst(pathkeyCell);
3128  Node *expr = (Node *) lfirst(exprCell);
3129  Oid exprtype = exprType(expr);
3130  Oid sortop;
3131 
3132  /* Get sort operator from opfamily */
3133  sortop = get_opfamily_member(pathkey->pk_opfamily,
3134  exprtype,
3135  exprtype,
3136  pathkey->pk_strategy);
3137  if (!OidIsValid(sortop))
3138  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
3139  pathkey->pk_strategy, exprtype, exprtype, pathkey->pk_opfamily);
3140  indexorderbyops = lappend_oid(indexorderbyops, sortop);
3141  }
3142  }
3143 
3144  /*
3145  * For an index-only scan, we must mark indextlist entries as resjunk if
3146  * they are columns that the index AM can't return; this cues setrefs.c to
3147  * not generate references to those columns.
3148  */
3149  if (indexonly)
3150  {
3151  int i = 0;
3152 
3153  foreach(l, indexinfo->indextlist)
3154  {
3155  TargetEntry *indextle = (TargetEntry *) lfirst(l);
3156 
3157  indextle->resjunk = !indexinfo->canreturn[i];
3158  i++;
3159  }
3160  }
3161 
3162  /* Finally ready to build the plan node */
3163  if (indexonly)
3164  scan_plan = (Scan *) make_indexonlyscan(tlist,
3165  qpqual,
3166  baserelid,
3167  indexoid,
3168  fixed_indexquals,
3169  stripped_indexquals,
3170  fixed_indexorderbys,
3171  indexinfo->indextlist,
3172  best_path->indexscandir);
3173  else
3174  scan_plan = (Scan *) make_indexscan(tlist,
3175  qpqual,
3176  baserelid,
3177  indexoid,
3178  fixed_indexquals,
3179  stripped_indexquals,
3180  fixed_indexorderbys,
3181  indexorderbys,
3182  indexorderbyops,
3183  best_path->indexscandir);
3184 
3185  copy_generic_path_info(&scan_plan->plan, &best_path->path);
3186 
3187  return scan_plan;
3188 }
#define OidIsValid(objectId)
Definition: c.h:775
static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
Definition: createplan.c:5017
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:5058
static IndexOnlyScan * make_indexonlyscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *recheckqual, List *indexorderby, List *indextlist, ScanDirection indexscandir)
Definition: createplan.c:5570
static IndexScan * make_indexscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig, List *indexorderby, List *indexorderbyorig, List *indexorderbyops, ScanDirection indexscandir)
Definition: createplan.c:5539
bool is_redundant_with_indexclauses(RestrictInfo *rinfo, List *indexclauses)
Definition: equivclass.c:3297
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:166
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
@ BackwardScanDirection
Definition: sdir.h:26
@ ForwardScanDirection
Definition: sdir.h:28
List * indextlist
Definition: pathnodes.h:1168
ScanDirection indexscandir
Definition: pathnodes.h:1714
List * indexorderbys
Definition: pathnodes.h:1712
int pk_strategy
Definition: pathnodes.h:1470
Oid pk_opfamily
Definition: pathnodes.h:1469

References Assert, BackwardScanDirection, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), elog, ERROR, exprType(), extract_actual_clauses(), fix_indexorderby_references(), fix_indexqual_references(), forboth, ForwardScanDirection, get_opfamily_member(), i, IndexPath::indexclauses, IndexPath::indexinfo, IndexOptInfo::indexoid, IndexPath::indexorderbys, IndexPath::indexscandir, IndexOptInfo::indextlist, is_redundant_with_indexclauses(), lappend(), lappend_oid(), lfirst, lfirst_node, list_length(), list_make1, make_indexonlyscan(), make_indexscan(), NIL, OidIsValid, order_qual_clauses(), IndexPath::path, Path::pathkeys, PathKey::pk_opfamily, PathKey::pk_strategy, predicate_implied_by(), replace_nestloop_params(), root, and RTE_RELATION.

Referenced by create_bitmap_subplan(), and create_scan_plan().

◆ create_join_plan()

static Plan * create_join_plan ( PlannerInfo root,
JoinPath best_path 
)
static

Definition at line 1081 of file createplan.c.

1082 {
1083  Plan *plan;
1084  List *gating_clauses;
1085 
1086  switch (best_path->path.pathtype)
1087  {
1088  case T_MergeJoin:
1090  (MergePath *) best_path);
1091  break;
1092  case T_HashJoin:
1094  (HashPath *) best_path);
1095  break;
1096  case T_NestLoop:
1098  (NestPath *) best_path);
1099  break;
1100  default:
1101  elog(ERROR, "unrecognized node type: %d",
1102  (int) best_path->path.pathtype);
1103  plan = NULL; /* keep compiler quiet */
1104  break;
1105  }
1106 
1107  /*
1108  * If there are any pseudoconstant clauses attached to this node, insert a
1109  * gating Result node that evaluates the pseudoconstants as one-time
1110  * quals.
1111  */
1112  gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
1113  if (gating_clauses)
1114  plan = create_gating_plan(root, (Path *) best_path, plan,
1115  gating_clauses);
1116 
1117 #ifdef NOT_USED
1118 
1119  /*
1120  * * Expensive function pullups may have pulled local predicates * into
1121  * this path node. Put them in the qpqual of the plan node. * JMH,
1122  * 6/15/92
1123  */
1124  if (get_loc_restrictinfo(best_path) != NIL)
1125  set_qpqual((Plan) plan,
1126  list_concat(get_qpqual((Plan) plan),
1127  get_actual_clauses(get_loc_restrictinfo(best_path))));
1128 #endif
1129 
1130  return plan;
1131 }
static HashJoin * create_hashjoin_plan(PlannerInfo *root, HashPath *best_path)
Definition: createplan.c:4741
static MergeJoin * create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
Definition: createplan.c:4434
static Plan * create_gating_plan(PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
Definition: createplan.c:1022
static List * get_gating_quals(PlannerInfo *root, List *quals)
Definition: createplan.c:1002
static NestLoop * create_nestloop_plan(PlannerInfo *root, NestPath *best_path)
Definition: createplan.c:4342

References create_gating_plan(), create_hashjoin_plan(), create_mergejoin_plan(), create_nestloop_plan(), elog, ERROR, get_actual_clauses(), get_gating_quals(), JoinPath::joinrestrictinfo, list_concat(), NIL, plan, and root.

Referenced by create_plan_recurse().

◆ create_limit_plan()

static Limit * create_limit_plan ( PlannerInfo root,
LimitPath best_path,
int  flags 
)
static

Definition at line 2850 of file createplan.c.

2851 {
2852  Limit *plan;
2853  Plan *subplan;
2854  int numUniqkeys = 0;
2855  AttrNumber *uniqColIdx = NULL;
2856  Oid *uniqOperators = NULL;
2857  Oid *uniqCollations = NULL;
2858 
2859  /* Limit doesn't project, so tlist requirements pass through */
2860  subplan = create_plan_recurse(root, best_path->subpath, flags);
2861 
2862  /* Extract information necessary for comparing rows for WITH TIES. */
2863  if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
2864  {
2865  Query *parse = root->parse;
2866  ListCell *l;
2867 
2868  numUniqkeys = list_length(parse->sortClause);
2869  uniqColIdx = (AttrNumber *) palloc(numUniqkeys * sizeof(AttrNumber));
2870  uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2871  uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2872 
2873  numUniqkeys = 0;
2874  foreach(l, parse->sortClause)
2875  {
2876  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
2877  TargetEntry *tle = get_sortgroupclause_tle(sortcl, parse->targetList);
2878 
2879  uniqColIdx[numUniqkeys] = tle->resno;
2880  uniqOperators[numUniqkeys] = sortcl->eqop;
2881  uniqCollations[numUniqkeys] = exprCollation((Node *) tle->expr);
2882  numUniqkeys++;
2883  }
2884  }
2885 
2886  plan = make_limit(subplan,
2887  best_path->limitOffset,
2888  best_path->limitCount,
2889  best_path->limitOption,
2890  numUniqkeys, uniqColIdx, uniqOperators, uniqCollations);
2891 
2892  copy_generic_path_info(&plan->plan, (Path *) best_path);
2893 
2894  return plan;
2895 }
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
Definition: createplan.c:6955
void * palloc(Size size)
Definition: mcxt.c:1317
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:432
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:715
Path * subpath
Definition: pathnodes.h:2401
LimitOption limitOption
Definition: pathnodes.h:2404
Node * limitOffset
Definition: pathnodes.h:2402
Node * limitCount
Definition: pathnodes.h:2403
Expr * expr
Definition: primnodes.h:2186

References copy_generic_path_info(), create_plan_recurse(), SortGroupClause::eqop, TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, LIMIT_OPTION_WITH_TIES, LimitPath::limitCount, LimitPath::limitOffset, LimitPath::limitOption, list_length(), make_limit(), palloc(), parse(), plan, TargetEntry::resno, root, and LimitPath::subpath.

Referenced by create_plan_recurse().

◆ create_lockrows_plan()

static LockRows * create_lockrows_plan ( PlannerInfo root,
LockRowsPath best_path,
int  flags 
)
static

Definition at line 2786 of file createplan.c.

2788 {
2789  LockRows *plan;
2790  Plan *subplan;
2791 
2792  /* LockRows doesn't project, so tlist requirements pass through */
2793  subplan = create_plan_recurse(root, best_path->subpath, flags);
2794 
2795  plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2796 
2797  copy_generic_path_info(&plan->plan, (Path *) best_path);
2798 
2799  return plan;
2800 }
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:6934
Path * subpath
Definition: pathnodes.h:2361
List * rowMarks
Definition: pathnodes.h:2362

References copy_generic_path_info(), create_plan_recurse(), LockRowsPath::epqParam, make_lockrows(), plan, root, LockRowsPath::rowMarks, and LockRowsPath::subpath.

Referenced by create_plan_recurse().

◆ create_material_plan()

static Material * create_material_plan ( PlannerInfo root,
MaterialPath best_path,
int  flags 
)
static

Definition at line 1638 of file createplan.c.

1639 {
1640  Material *plan;
1641  Plan *subplan;
1642 
1643  /*
1644  * We don't want any excess columns in the materialized tuples, so request
1645  * a smaller tlist. Otherwise, since Material doesn't project, tlist
1646  * requirements pass through.
1647  */
1648  subplan = create_plan_recurse(root, best_path->subpath,
1649  flags | CP_SMALL_TLIST);
1650 
1651  plan = make_material(subplan);
1652 
1653  copy_generic_path_info(&plan->plan, (Path *) best_path);
1654 
1655  return plan;
1656 }
static Material * make_material(Plan *lefttree)
Definition: createplan.c:6500
Path * subpath
Definition: pathnodes.h:1982

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), make_material(), plan, root, and MaterialPath::subpath.

Referenced by create_plan_recurse().

◆ create_memoize_plan()

static Memoize * create_memoize_plan ( PlannerInfo root,
MemoizePath best_path,
int  flags 
)
static

Definition at line 1666 of file createplan.c.

1667 {
1668  Memoize *plan;
1669  Bitmapset *keyparamids;
1670  Plan *subplan;
1671  Oid *operators;
1672  Oid *collations;
1673  List *param_exprs = NIL;
1674  ListCell *lc;
1675  ListCell *lc2;
1676  int nkeys;
1677  int i;
1678 
1679  subplan = create_plan_recurse(root, best_path->subpath,
1680  flags | CP_SMALL_TLIST);
1681 
1682  param_exprs = (List *) replace_nestloop_params(root, (Node *)
1683  best_path->param_exprs);
1684 
1685  nkeys = list_length(param_exprs);
1686  Assert(nkeys > 0);
1687  operators = palloc(nkeys * sizeof(Oid));
1688  collations = palloc(nkeys * sizeof(Oid));
1689 
1690  i = 0;
1691  forboth(lc, param_exprs, lc2, best_path->hash_operators)
1692  {
1693  Expr *param_expr = (Expr *) lfirst(lc);
1694  Oid opno = lfirst_oid(lc2);
1695 
1696  operators[i] = opno;
1697  collations[i] = exprCollation((Node *) param_expr);
1698  i++;
1699  }
1700 
1701  keyparamids = pull_paramids((Expr *) param_exprs);
1702 
1703  plan = make_memoize(subplan, operators, collations, param_exprs,
1704  best_path->singlerow, best_path->binary_mode,
1705  best_path->est_entries, keyparamids);
1706 
1707  copy_generic_path_info(&plan->plan, (Path *) best_path);
1708 
1709  return plan;
1710 }
Bitmapset * pull_paramids(Expr *expr)
Definition: clauses.c:5406
static Memoize * make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids)
Definition: createplan.c:6563
#define lfirst_oid(lc)
Definition: pg_list.h:174
bool singlerow
Definition: pathnodes.h:1996
List * hash_operators
Definition: pathnodes.h:1994
uint32 est_entries
Definition: pathnodes.h:2001
bool binary_mode
Definition: pathnodes.h:1998
Path * subpath
Definition: pathnodes.h:1993
List * param_exprs
Definition: pathnodes.h:1995

References Assert, MemoizePath::binary_mode, copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), MemoizePath::est_entries, exprCollation(), forboth, MemoizePath::hash_operators, i, lfirst, lfirst_oid, list_length(), make_memoize(), NIL, palloc(), MemoizePath::param_exprs, plan, pull_paramids(), replace_nestloop_params(), root, MemoizePath::singlerow, and MemoizePath::subpath.

Referenced by create_plan_recurse().

◆ create_merge_append_plan()

static Plan * create_merge_append_plan ( PlannerInfo root,
MergeAppendPath best_path,
int  flags 
)
static

Definition at line 1437 of file createplan.c.

1439 {
1440  MergeAppend *node = makeNode(MergeAppend);
1441  Plan *plan = &node->plan;
1442  List *tlist = build_path_tlist(root, &best_path->path);
1443  int orig_tlist_length = list_length(tlist);
1444  bool tlist_was_changed;
1445  List *pathkeys = best_path->path.pathkeys;
1446  List *subplans = NIL;
1447  ListCell *subpaths;
1448  RelOptInfo *rel = best_path->path.parent;
1449  PartitionPruneInfo *partpruneinfo = NULL;
1450 
1451  /*
1452  * We don't have the actual creation of the MergeAppend node split out
1453  * into a separate make_xxx function. This is because we want to run
1454  * prepare_sort_from_pathkeys on it before we do so on the individual
1455  * child plans, to make cross-checking the sort info easier.
1456  */
1457  copy_generic_path_info(plan, (Path *) best_path);
1458  plan->targetlist = tlist;
1459  plan->qual = NIL;
1460  plan->lefttree = NULL;
1461  plan->righttree = NULL;
1462  node->apprelids = rel->relids;
1463 
1464  /*
1465  * Compute sort column info, and adjust MergeAppend's tlist as needed.
1466  * Because we pass adjust_tlist_in_place = true, we may ignore the
1467  * function result; it must be the same plan node. However, we then need
1468  * to detect whether any tlist entries were added.
1469  */
1470  (void) prepare_sort_from_pathkeys(plan, pathkeys,
1471  best_path->path.parent->relids,
1472  NULL,
1473  true,
1474  &node->numCols,
1475  &node->sortColIdx,
1476  &node->sortOperators,
1477  &node->collations,
1478  &node->nullsFirst);
1479  tlist_was_changed = (orig_tlist_length != list_length(plan->targetlist));
1480 
1481  /*
1482  * Now prepare the child plans. We must apply prepare_sort_from_pathkeys
1483  * even to subplans that don't need an explicit sort, to make sure they
1484  * are returning the same sort key columns the MergeAppend expects.
1485  */
1486  foreach(subpaths, best_path->subpaths)
1487  {
1488  Path *subpath = (Path *) lfirst(subpaths);
1489  Plan *subplan;
1490  int numsortkeys;
1491  AttrNumber *sortColIdx;
1492  Oid *sortOperators;
1493  Oid *collations;
1494  bool *nullsFirst;
1495 
1496  /* Build the child plan */
1497  /* Must insist that all children return the same tlist */
1499 
1500  /* Compute sort column info, and adjust subplan's tlist as needed */
1501  subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1502  subpath->parent->relids,
1503  node->sortColIdx,
1504  false,
1505  &numsortkeys,
1506  &sortColIdx,
1507  &sortOperators,
1508  &collations,
1509  &nullsFirst);
1510 
1511  /*
1512  * Check that we got the same sort key information. We just Assert
1513  * that the sortops match, since those depend only on the pathkeys;
1514  * but it seems like a good idea to check the sort column numbers
1515  * explicitly, to ensure the tlists really do match up.
1516  */
1517  Assert(numsortkeys == node->numCols);
1518  if (memcmp(sortColIdx, node->sortColIdx,
1519  numsortkeys * sizeof(AttrNumber)) != 0)
1520  elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
1521  Assert(memcmp(sortOperators, node->sortOperators,
1522  numsortkeys * sizeof(Oid)) == 0);
1523  Assert(memcmp(collations, node->collations,
1524  numsortkeys * sizeof(Oid)) == 0);
1525  Assert(memcmp(nullsFirst, node->nullsFirst,
1526  numsortkeys * sizeof(bool)) == 0);
1527 
1528  /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1529  if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
1530  {
1531  Sort *sort = make_sort(subplan, numsortkeys,
1532  sortColIdx, sortOperators,
1533  collations, nullsFirst);
1534 
1536  subplan = (Plan *) sort;
1537  }
1538 
1539  subplans = lappend(subplans, subplan);
1540  }
1541 
1542  /*
1543  * If any quals exist, they may be useful to perform further partition
1544  * pruning during execution. Gather information needed by the executor to
1545  * do partition pruning.
1546  */
1548  {
1549  List *prunequal;
1550 
1551  prunequal = extract_actual_clauses(rel->baserestrictinfo, false);
1552 
1553  /* We don't currently generate any parameterized MergeAppend paths */
1554  Assert(best_path->path.param_info == NULL);
1555 
1556  if (prunequal != NIL)
1557  partpruneinfo = make_partition_pruneinfo(root, rel,
1558  best_path->subpaths,
1559  prunequal);
1560  }
1561 
1562  node->mergeplans = subplans;
1563  node->part_prune_info = partpruneinfo;
1564 
1565  /*
1566  * If prepare_sort_from_pathkeys added sort columns, but we were told to
1567  * produce either the exact tlist or a narrow tlist, we should get rid of
1568  * the sort columns again. We must inject a projection node to do so.
1569  */
1570  if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
1571  {
1572  tlist = list_copy_head(plan->targetlist, orig_tlist_length);
1573  return inject_projection_plan(plan, tlist, plan->parallel_safe);
1574  }
1575  else
1576  return plan;
1577 }
Cardinality limit_tuples
Definition: pathnodes.h:1957
struct PartitionPruneInfo * part_prune_info
Definition: plannodes.h:314
Bitmapset * apprelids
Definition: plannodes.h:292
List * mergeplans
Definition: plannodes.h:294

References MergeAppend::apprelids, Assert, RelOptInfo::baserestrictinfo, build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, CP_SMALL_TLIST, create_plan_recurse(), elog, enable_partition_pruning, ERROR, extract_actual_clauses(), inject_projection_plan(), label_sort_with_costsize(), lappend(), lfirst, MergeAppendPath::limit_tuples, list_copy_head(), list_length(), make_partition_pruneinfo(), make_sort(), makeNode, MergeAppend::mergeplans, NIL, MergeAppend::numCols, MergeAppend::part_prune_info, MergeAppendPath::path, Path::pathkeys, pathkeys_contained_in(), MergeAppend::plan, plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, root, sort(), subpath(), and MergeAppendPath::subpaths.

Referenced by create_plan_recurse().

◆ create_mergejoin_plan()

static MergeJoin * create_mergejoin_plan ( PlannerInfo root,
MergePath best_path 
)
static

Definition at line 4434 of file createplan.c.

4436 {
4437  MergeJoin *join_plan;
4438  Plan *outer_plan;
4439  Plan *inner_plan;
4440  List *tlist = build_path_tlist(root, &best_path->jpath.path);
4441  List *joinclauses;
4442  List *otherclauses;
4443  List *mergeclauses;
4444  List *outerpathkeys;
4445  List *innerpathkeys;
4446  int nClauses;
4447  Oid *mergefamilies;
4448  Oid *mergecollations;
4449  int *mergestrategies;
4450  bool *mergenullsfirst;
4451  PathKey *opathkey;
4452  EquivalenceClass *opeclass;
4453  int i;
4454  ListCell *lc;
4455  ListCell *lop;
4456  ListCell *lip;
4457  Path *outer_path = best_path->jpath.outerjoinpath;
4458  Path *inner_path = best_path->jpath.innerjoinpath;
4459 
4460  /*
4461  * MergeJoin can project, so we don't have to demand exact tlists from the
4462  * inputs. However, if we're intending to sort an input's result, it's
4463  * best to request a small tlist so we aren't sorting more data than
4464  * necessary.
4465  */
4466  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4467  (best_path->outersortkeys != NIL) ? CP_SMALL_TLIST : 0);
4468 
4469  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4470  (best_path->innersortkeys != NIL) ? CP_SMALL_TLIST : 0);
4471 
4472  /* Sort join qual clauses into best execution order */
4473  /* NB: do NOT reorder the mergeclauses */
4474  joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4475 
4476  /* Get the join qual clauses (in plain expression form) */
4477  /* Any pseudoconstant clauses are ignored here */
4478  if (IS_OUTER_JOIN(best_path->jpath.jointype))
4479  {
4480  extract_actual_join_clauses(joinclauses,
4481  best_path->jpath.path.parent->relids,
4482  &joinclauses, &otherclauses);
4483  }
4484  else
4485  {
4486  /* We can treat all clauses alike for an inner join */
4487  joinclauses = extract_actual_clauses(joinclauses, false);
4488  otherclauses = NIL;
4489  }
4490 
4491  /*
4492  * Remove the mergeclauses from the list of join qual clauses, leaving the
4493  * list of quals that must be checked as qpquals.
4494  */
4495  mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
4496  joinclauses = list_difference(joinclauses, mergeclauses);
4497 
4498  /*
4499  * Replace any outer-relation variables with nestloop params. There
4500  * should not be any in the mergeclauses.
4501  */
4502  if (best_path->jpath.path.param_info)
4503  {
4504  joinclauses = (List *)
4505  replace_nestloop_params(root, (Node *) joinclauses);
4506  otherclauses = (List *)
4507  replace_nestloop_params(root, (Node *) otherclauses);
4508  }
4509 
4510  /*
4511  * Rearrange mergeclauses, if needed, so that the outer variable is always
4512  * on the left; mark the mergeclause restrictinfos with correct
4513  * outer_is_left status.
4514  */
4515  mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
4516  best_path->jpath.outerjoinpath->parent->relids);
4517 
4518  /*
4519  * Create explicit sort nodes for the outer and inner paths if necessary.
4520  */
4521  if (best_path->outersortkeys)
4522  {
4523  Relids outer_relids = outer_path->parent->relids;
4524  Sort *sort = make_sort_from_pathkeys(outer_plan,
4525  best_path->outersortkeys,
4526  outer_relids);
4527 
4529  outer_plan = (Plan *) sort;
4530  outerpathkeys = best_path->outersortkeys;
4531  }
4532  else
4533  outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
4534 
4535  if (best_path->innersortkeys)
4536  {
4537  Relids inner_relids = inner_path->parent->relids;
4538  Sort *sort = make_sort_from_pathkeys(inner_plan,
4539  best_path->innersortkeys,
4540  inner_relids);
4541 
4543  inner_plan = (Plan *) sort;
4544  innerpathkeys = best_path->innersortkeys;
4545  }
4546  else
4547  innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
4548 
4549  /*
4550  * If specified, add a materialize node to shield the inner plan from the
4551  * need to handle mark/restore.
4552  */
4553  if (best_path->materialize_inner)
4554  {
4555  Plan *matplan = (Plan *) make_material(inner_plan);
4556 
4557  /*
4558  * We assume the materialize will not spill to disk, and therefore
4559  * charge just cpu_operator_cost per tuple. (Keep this estimate in
4560  * sync with final_cost_mergejoin.)
4561  */
4562  copy_plan_costsize(matplan, inner_plan);
4563  matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
4564 
4565  inner_plan = matplan;
4566  }
4567 
4568  /*
4569  * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
4570  * executor. The information is in the pathkeys for the two inputs, but
4571  * we need to be careful about the possibility of mergeclauses sharing a
4572  * pathkey, as well as the possibility that the inner pathkeys are not in
4573  * an order matching the mergeclauses.
4574  */
4575  nClauses = list_length(mergeclauses);
4576  Assert(nClauses == list_length(best_path->path_mergeclauses));
4577  mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
4578  mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
4579  mergestrategies = (int *) palloc(nClauses * sizeof(int));
4580  mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
4581 
4582  opathkey = NULL;
4583  opeclass = NULL;
4584  lop = list_head(outerpathkeys);
4585  lip = list_head(innerpathkeys);
4586  i = 0;
4587  foreach(lc, best_path->path_mergeclauses)
4588  {
4589  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
4590  EquivalenceClass *oeclass;
4591  EquivalenceClass *ieclass;
4592  PathKey *ipathkey = NULL;
4593  EquivalenceClass *ipeclass = NULL;
4594  bool first_inner_match = false;
4595 
4596  /* fetch outer/inner eclass from mergeclause */
4597  if (rinfo->outer_is_left)
4598  {
4599  oeclass = rinfo->left_ec;
4600  ieclass = rinfo->right_ec;
4601  }
4602  else
4603  {
4604  oeclass = rinfo->right_ec;
4605  ieclass = rinfo->left_ec;
4606  }
4607  Assert(oeclass != NULL);
4608  Assert(ieclass != NULL);
4609 
4610  /*
4611  * We must identify the pathkey elements associated with this clause
4612  * by matching the eclasses (which should give a unique match, since
4613  * the pathkey lists should be canonical). In typical cases the merge
4614  * clauses are one-to-one with the pathkeys, but when dealing with
4615  * partially redundant query conditions, things are more complicated.
4616  *
4617  * lop and lip reference the first as-yet-unmatched pathkey elements.
4618  * If they're NULL then all pathkey elements have been matched.
4619  *
4620  * The ordering of the outer pathkeys should match the mergeclauses,
4621  * by construction (see find_mergeclauses_for_outer_pathkeys()). There
4622  * could be more than one mergeclause for the same outer pathkey, but
4623  * no pathkey may be entirely skipped over.
4624  */
4625  if (oeclass != opeclass) /* multiple matches are not interesting */
4626  {
4627  /* doesn't match the current opathkey, so must match the next */
4628  if (lop == NULL)
4629  elog(ERROR, "outer pathkeys do not match mergeclauses");
4630  opathkey = (PathKey *) lfirst(lop);
4631  opeclass = opathkey->pk_eclass;
4632  lop = lnext(outerpathkeys, lop);
4633  if (oeclass != opeclass)
4634  elog(ERROR, "outer pathkeys do not match mergeclauses");
4635  }
4636 
4637  /*
4638  * The inner pathkeys likewise should not have skipped-over keys, but
4639  * it's possible for a mergeclause to reference some earlier inner
4640  * pathkey if we had redundant pathkeys. For example we might have
4641  * mergeclauses like "o.a = i.x AND o.b = i.y AND o.c = i.x". The
4642  * implied inner ordering is then "ORDER BY x, y, x", but the pathkey
4643  * mechanism drops the second sort by x as redundant, and this code
4644  * must cope.
4645  *
4646  * It's also possible for the implied inner-rel ordering to be like
4647  * "ORDER BY x, y, x DESC". We still drop the second instance of x as
4648  * redundant; but this means that the sort ordering of a redundant
4649  * inner pathkey should not be considered significant. So we must
4650  * detect whether this is the first clause matching an inner pathkey.
4651  */
4652  if (lip)
4653  {
4654  ipathkey = (PathKey *) lfirst(lip);
4655  ipeclass = ipathkey->pk_eclass;
4656  if (ieclass == ipeclass)
4657  {
4658  /* successful first match to this inner pathkey */
4659  lip = lnext(innerpathkeys, lip);
4660  first_inner_match = true;
4661  }
4662  }
4663  if (!first_inner_match)
4664  {
4665  /* redundant clause ... must match something before lip */
4666  ListCell *l2;
4667 
4668  foreach(l2, innerpathkeys)
4669  {
4670  if (l2 == lip)
4671  break;
4672  ipathkey = (PathKey *) lfirst(l2);
4673  ipeclass = ipathkey->pk_eclass;
4674  if (ieclass == ipeclass)
4675  break;
4676  }
4677  if (ieclass != ipeclass)
4678  elog(ERROR, "inner pathkeys do not match mergeclauses");
4679  }
4680 
4681  /*
4682  * The pathkeys should always match each other as to opfamily and
4683  * collation (which affect equality), but if we're considering a
4684  * redundant inner pathkey, its sort ordering might not match. In
4685  * such cases we may ignore the inner pathkey's sort ordering and use
4686  * the outer's. (In effect, we're lying to the executor about the
4687  * sort direction of this inner column, but it does not matter since
4688  * the run-time row comparisons would only reach this column when
4689  * there's equality for the earlier column containing the same eclass.
4690  * There could be only one value in this column for the range of inner
4691  * rows having a given value in the earlier column, so it does not
4692  * matter which way we imagine this column to be ordered.) But a
4693  * non-redundant inner pathkey had better match outer's ordering too.
4694  */
4695  if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
4696  opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
4697  elog(ERROR, "left and right pathkeys do not match in mergejoin");
4698  if (first_inner_match &&
4699  (opathkey->pk_strategy != ipathkey->pk_strategy ||
4700  opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
4701  elog(ERROR, "left and right pathkeys do not match in mergejoin");
4702 
4703  /* OK, save info for executor */
4704  mergefamilies[i] = opathkey->pk_opfamily;
4705  mergecollations[i] = opathkey->pk_eclass->ec_collation;
4706  mergestrategies[i] = opathkey->pk_strategy;
4707  mergenullsfirst[i] = opathkey->pk_nulls_first;
4708  i++;
4709  }
4710 
4711  /*
4712  * Note: it is not an error if we have additional pathkey elements (i.e.,
4713  * lop or lip isn't NULL here). The input paths might be better-sorted
4714  * than we need for the current mergejoin.
4715  */
4716 
4717  /*
4718  * Now we can build the mergejoin node.
4719  */
4720  join_plan = make_mergejoin(tlist,
4721  joinclauses,
4722  otherclauses,
4723  mergeclauses,
4724  mergefamilies,
4725  mergecollations,
4726  mergestrategies,
4727  mergenullsfirst,
4728  outer_plan,
4729  inner_plan,
4730  best_path->jpath.jointype,
4731  best_path->jpath.inner_unique,
4732  best_path->skip_mark_restore);
4733 
4734  /* Costs of sort and material steps are included in path cost already */
4735  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4736 
4737  return join_plan;
4738 }
double cpu_operator_cost
Definition: costsize.c:123
static Sort * make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
Definition: createplan.c:6341
static MergeJoin * make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, bool skip_mark_restore)
Definition: createplan.c:6022
static ListCell * list_head(const List *l)
Definition: pg_list.h:128
static ListCell * lnext(const List *l, const ListCell *c)
Definition: pg_list.h:343
Join join
Definition: plannodes.h:835
List * outersortkeys
Definition: pathnodes.h:2134
bool skip_mark_restore
Definition: pathnodes.h:2136
List * innersortkeys
Definition: pathnodes.h:2135
JoinPath jpath
Definition: pathnodes.h:2132
bool materialize_inner
Definition: pathnodes.h:2137
List * path_mergeclauses
Definition: pathnodes.h:2133
bool pk_nulls_first
Definition: pathnodes.h:1471

References Assert, build_path_tlist(), copy_generic_path_info(), copy_plan_costsize(), CP_SMALL_TLIST, cpu_operator_cost, create_plan_recurse(), elog, ERROR, extract_actual_clauses(), extract_actual_join_clauses(), get_actual_clauses(), get_switched_clauses(), i, JoinPath::inner_unique, JoinPath::innerjoinpath, MergePath::innersortkeys, IS_OUTER_JOIN, MergeJoin::join, JoinPath::joinrestrictinfo, JoinPath::jointype, MergePath::jpath, label_sort_with_costsize(), lfirst, lfirst_node, list_difference(), list_head(), list_length(), lnext(), make_material(), make_mergejoin(), make_sort_from_pathkeys(), MergePath::materialize_inner, NIL, order_qual_clauses(), JoinPath::outerjoinpath, MergePath::outersortkeys, palloc(), MergePath::path_mergeclauses, Path::pathkeys, PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, Plan::plan_rows, replace_nestloop_params(), root, MergePath::skip_mark_restore, sort(), and Plan::total_cost.

Referenced by create_join_plan().

◆ create_minmaxagg_plan()

static Result * create_minmaxagg_plan ( PlannerInfo root,
MinMaxAggPath best_path 
)
static

Definition at line 2545 of file createplan.c.

2546 {
2547  Result *plan;
2548  List *tlist;
2549  ListCell *lc;
2550 
2551  /* Prepare an InitPlan for each aggregate's subquery. */
2552  foreach(lc, best_path->mmaggregates)
2553  {
2554  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2555  PlannerInfo *subroot = mminfo->subroot;
2556  Query *subparse = subroot->parse;
2557  Plan *plan;
2558 
2559  /*
2560  * Generate the plan for the subquery. We already have a Path, but we
2561  * have to convert it to a Plan and attach a LIMIT node above it.
2562  * Since we are entering a different planner context (subroot),
2563  * recurse to create_plan not create_plan_recurse.
2564  */
2565  plan = create_plan(subroot, mminfo->path);
2566 
2567  plan = (Plan *) make_limit(plan,
2568  subparse->limitOffset,
2569  subparse->limitCount,
2570  subparse->limitOption,
2571  0, NULL, NULL, NULL);
2572 
2573  /* Must apply correct cost/width data to Limit node */
2574  plan->startup_cost = mminfo->path->startup_cost;
2575  plan->total_cost = mminfo->pathcost;
2576  plan->plan_rows = 1;
2577  plan->plan_width = mminfo->path->pathtarget->width;
2578  plan->parallel_aware = false;
2579  plan->parallel_safe = mminfo->path->parallel_safe;
2580 
2581  /* Convert the plan into an InitPlan in the outer query. */
2582  SS_make_initplan_from_plan(root, subroot, plan, mminfo->param);
2583  }
2584 
2585  /* Generate the output plan --- basically just a Result */
2586  tlist = build_path_tlist(root, &best_path->path);
2587 
2588  plan = make_result(tlist, (Node *) best_path->quals, NULL);
2589 
2590  copy_generic_path_info(&plan->plan, (Path *) best_path);
2591 
2592  /*
2593  * During setrefs.c, we'll need to replace references to the Agg nodes
2594  * with InitPlan output params. (We can't just do that locally in the
2595  * MinMaxAgg node, because path nodes above here may have Agg references
2596  * as well.) Save the mmaggregates list to tell setrefs.c to do that.
2597  */
2598  Assert(root->minmax_aggs == NIL);
2599  root->minmax_aggs = best_path->mmaggregates;
2600 
2601  return plan;
2602 }
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:337
Param * param
Definition: pathnodes.h:3133
List * quals
Definition: pathnodes.h:2310
List * mmaggregates
Definition: pathnodes.h:2309
Node * limitCount
Definition: parsenodes.h:214
Node * limitOffset
Definition: parsenodes.h:213
LimitOption limitOption
Definition: parsenodes.h:215
void SS_make_initplan_from_plan(PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
Definition: subselect.c:3017

References Assert, build_path_tlist(), copy_generic_path_info(), create_plan(), lfirst, Query::limitCount, Query::limitOffset, Query::limitOption, make_limit(), make_result(), MinMaxAggPath::mmaggregates, NIL, Path::parallel_safe, MinMaxAggInfo::param, PlannerInfo::parse, MinMaxAggPath::path, MinMaxAggInfo::path, MinMaxAggInfo::pathcost, plan, MinMaxAggPath::quals, root, SS_make_initplan_from_plan(), and Path::startup_cost.

Referenced by create_plan_recurse().

◆ create_modifytable_plan()

static ModifyTable * create_modifytable_plan ( PlannerInfo root,
ModifyTablePath best_path 
)
static

Definition at line 2809 of file createplan.c.

2810 {
2811  ModifyTable *plan;
2812  Path *subpath = best_path->subpath;
2813  Plan *subplan;
2814 
2815  /* Subplan must produce exactly the specified tlist */
2817 
2818  /* Transfer resname/resjunk labeling, too, to keep executor happy */
2819  apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2820 
2822  subplan,
2823  best_path->operation,
2824  best_path->canSetTag,
2825  best_path->nominalRelation,
2826  best_path->rootRelation,
2827  best_path->partColsUpdated,
2828  best_path->resultRelations,
2829  best_path->updateColnosLists,
2830  best_path->withCheckOptionLists,
2831  best_path->returningLists,
2832  best_path->rowMarks,
2833  best_path->onconflict,
2834  best_path->mergeActionLists,
2835  best_path->mergeJoinConditions,
2836  best_path->epqParam);
2837 
2838  copy_generic_path_info(&plan->plan, &best_path->path);
2839 
2840  return plan;
2841 }
static ModifyTable * make_modifytable(PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
Definition: createplan.c:7023
bool partColsUpdated
Definition: pathnodes.h:2381
List * returningLists
Definition: pathnodes.h:2385
List * resultRelations
Definition: pathnodes.h:2382
List * withCheckOptionLists
Definition: pathnodes.h:2384
List * mergeJoinConditions
Definition: pathnodes.h:2391
List * updateColnosLists
Definition: pathnodes.h:2383
OnConflictExpr * onconflict
Definition: pathnodes.h:2387
CmdType operation
Definition: pathnodes.h:2377
Index rootRelation
Definition: pathnodes.h:2380
Index nominalRelation
Definition: pathnodes.h:2379
List * mergeActionLists
Definition: pathnodes.h:2389
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:318

References apply_tlist_labeling(), ModifyTablePath::canSetTag, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), ModifyTablePath::epqParam, make_modifytable(), ModifyTablePath::mergeActionLists, ModifyTablePath::mergeJoinConditions, ModifyTablePath::nominalRelation, ModifyTablePath::onconflict, ModifyTablePath::operation, ModifyTablePath::partColsUpdated, ModifyTablePath::path, plan, ModifyTablePath::resultRelations, ModifyTablePath::returningLists, root, ModifyTablePath::rootRelation, ModifyTablePath::rowMarks, subpath(), ModifyTablePath::subpath, Plan::targetlist, ModifyTablePath::updateColnosLists, and ModifyTablePath::withCheckOptionLists.

Referenced by create_plan_recurse().

◆ create_namedtuplestorescan_plan()

static NamedTuplestoreScan * create_namedtuplestorescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3980 of file createplan.c.

3982 {
3983  NamedTuplestoreScan *scan_plan;
3984  Index scan_relid = best_path->parent->relid;
3985  RangeTblEntry *rte;
3986 
3987  Assert(scan_relid > 0);
3988  rte = planner_rt_fetch(scan_relid, root);
3990 
3991  /* Sort clauses into best execution order */
3992  scan_clauses = order_qual_clauses(root, scan_clauses);
3993 
3994  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3995  scan_clauses = extract_actual_clauses(scan_clauses, false);
3996 
3997  /* Replace any outer-relation variables with nestloop params */
3998  if (best_path->param_info)
3999  {
4000  scan_clauses = (List *)
4001  replace_nestloop_params(root, (Node *) scan_clauses);
4002  }
4003 
4004  scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
4005  rte->enrname);
4006 
4007  copy_generic_path_info(&scan_plan->scan.plan, best_path);
4008 
4009  return scan_plan;
4010 }
static NamedTuplestoreScan * make_namedtuplestorescan(List *qptlist, List *qpqual, Index scanrelid, char *enrname)
Definition: createplan.c:5778
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1035
char * enrname
Definition: parsenodes.h:1241

References Assert, copy_generic_path_info(), RangeTblEntry::enrname, extract_actual_clauses(), make_namedtuplestorescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_NAMEDTUPLESTORE, RangeTblEntry::rtekind, and NamedTuplestoreScan::scan.

Referenced by create_scan_plan().

◆ create_nestloop_plan()

static NestLoop * create_nestloop_plan ( PlannerInfo root,
NestPath best_path 
)
static

Definition at line 4342 of file createplan.c.

4344 {
4345  NestLoop *join_plan;
4346  Plan *outer_plan;
4347  Plan *inner_plan;
4348  List *tlist = build_path_tlist(root, &best_path->jpath.path);
4349  List *joinrestrictclauses = best_path->jpath.joinrestrictinfo;
4350  List *joinclauses;
4351  List *otherclauses;
4352  Relids outerrelids;
4353  List *nestParams;
4354  Relids saveOuterRels = root->curOuterRels;
4355 
4356  /*
4357  * If the inner path is parameterized by the topmost parent of the outer
4358  * rel rather than the outer rel itself, fix that. (Nothing happens here
4359  * if it is not so parameterized.)
4360  */
4361  best_path->jpath.innerjoinpath =
4363  best_path->jpath.innerjoinpath,
4364  best_path->jpath.outerjoinpath->parent);
4365 
4366  /*
4367  * Failure here probably means that reparameterize_path_by_child() is not
4368  * in sync with path_is_reparameterizable_by_child().
4369  */
4370  Assert(best_path->jpath.innerjoinpath != NULL);
4371 
4372  /* NestLoop can project, so no need to be picky about child tlists */
4373  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath, 0);
4374 
4375  /* For a nestloop, include outer relids in curOuterRels for inner side */
4376  root->curOuterRels = bms_union(root->curOuterRels,
4377  best_path->jpath.outerjoinpath->parent->relids);
4378 
4379  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath, 0);
4380 
4381  /* Restore curOuterRels */
4382  bms_free(root->curOuterRels);
4383  root->curOuterRels = saveOuterRels;
4384 
4385  /* Sort join qual clauses into best execution order */
4386  joinrestrictclauses = order_qual_clauses(root, joinrestrictclauses);
4387 
4388  /* Get the join qual clauses (in plain expression form) */
4389  /* Any pseudoconstant clauses are ignored here */
4390  if (IS_OUTER_JOIN(best_path->jpath.jointype))
4391  {
4392  extract_actual_join_clauses(joinrestrictclauses,
4393  best_path->jpath.path.parent->relids,
4394  &joinclauses, &otherclauses);
4395  }
4396  else
4397  {
4398  /* We can treat all clauses alike for an inner join */
4399  joinclauses = extract_actual_clauses(joinrestrictclauses, false);
4400  otherclauses = NIL;
4401  }
4402 
4403  /* Replace any outer-relation variables with nestloop params */
4404  if (best_path->jpath.path.param_info)
4405  {
4406  joinclauses = (List *)
4407  replace_nestloop_params(root, (Node *) joinclauses);
4408  otherclauses = (List *)
4409  replace_nestloop_params(root, (Node *) otherclauses);
4410  }
4411 
4412  /*
4413  * Identify any nestloop parameters that should be supplied by this join
4414  * node, and remove them from root->curOuterParams.
4415  */
4416  outerrelids = best_path->jpath.outerjoinpath->parent->relids;
4417  nestParams = identify_current_nestloop_params(root, outerrelids);
4418 
4419  join_plan = make_nestloop(tlist,
4420  joinclauses,
4421  otherclauses,
4422  nestParams,
4423  outer_plan,
4424  inner_plan,
4425  best_path->jpath.jointype,
4426  best_path->jpath.inner_unique);
4427 
4428  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4429 
4430  return join_plan;
4431 }
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:251
static NestLoop * make_nestloop(List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
Definition: createplan.c:5943
List * identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids)
Definition: paramassign.c:582
Path * reparameterize_path_by_child(PlannerInfo *root, Path *path, RelOptInfo *child_rel)
Definition: pathnode.c:4103
Join join
Definition: plannodes.h:809
JoinPath jpath
Definition: pathnodes.h:2092

References Assert, bms_free(), bms_union(), build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), extract_actual_clauses(), extract_actual_join_clauses(), identify_current_nestloop_params(), JoinPath::inner_unique, JoinPath::innerjoinpath, IS_OUTER_JOIN, NestLoop::join, JoinPath::joinrestrictinfo, JoinPath::jointype, NestPath::jpath, make_nestloop(), NIL, order_qual_clauses(), JoinPath::outerjoinpath, reparameterize_path_by_child(), replace_nestloop_params(), and root.

Referenced by create_join_plan().

◆ create_plan()

Plan* create_plan ( PlannerInfo root,
Path best_path 
)

Definition at line 337 of file createplan.c.

338 {
339  Plan *plan;
340 
341  /* plan_params should not be in use in current query level */
342  Assert(root->plan_params == NIL);
343 
344  /* Initialize this module's workspace in PlannerInfo */
345  root->curOuterRels = NULL;
346  root->curOuterParams = NIL;
347 
348  /* Recursively process the path tree, demanding the correct tlist result */
350 
351  /*
352  * Make sure the topmost plan node's targetlist exposes the original
353  * column names and other decorative info. Targetlists generated within
354  * the planner don't bother with that stuff, but we must have it on the
355  * top-level tlist seen at execution time. However, ModifyTable plan
356  * nodes don't have a tlist matching the querytree targetlist.
357  */
358  if (!IsA(plan, ModifyTable))
359  apply_tlist_labeling(plan->targetlist, root->processed_tlist);
360 
361  /*
362  * Attach any initPlans created in this query level to the topmost plan
363  * node. (In principle the initplans could go in any plan node at or
364  * above where they're referenced, but there seems no reason to put them
365  * any lower than the topmost node for the query level. Also, see
366  * comments for SS_finalize_plan before you try to change this.)
367  */
369 
370  /* Check we successfully assigned all NestLoopParams to plan nodes */
371  if (root->curOuterParams != NIL)
372  elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
373 
374  /*
375  * Reset plan_params to ensure param IDs used for nestloop params are not
376  * re-used later
377  */
378  root->plan_params = NIL;
379 
380  return plan;
381 }
void SS_attach_initplans(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2239

References apply_tlist_labeling(), Assert, CP_EXACT_TLIST, create_plan_recurse(), elog, ERROR, IsA, NIL, plan, root, and SS_attach_initplans().

Referenced by create_minmaxagg_plan(), create_subqueryscan_plan(), make_subplan(), SS_process_ctes(), and standard_planner().

◆ create_plan_recurse()

static Plan * create_plan_recurse ( PlannerInfo root,
Path best_path,
int  flags 
)
static

Definition at line 388 of file createplan.c.

389 {
390  Plan *plan;
391 
392  /* Guard against stack overflow due to overly complex plans */
394 
395  switch (best_path->pathtype)
396  {
397  case T_SeqScan:
398  case T_SampleScan:
399  case T_IndexScan:
400  case T_IndexOnlyScan:
401  case T_BitmapHeapScan:
402  case T_TidScan:
403  case T_TidRangeScan:
404  case T_SubqueryScan:
405  case T_FunctionScan:
406  case T_TableFuncScan:
407  case T_ValuesScan:
408  case T_CteScan:
409  case T_WorkTableScan:
410  case T_NamedTuplestoreScan:
411  case T_ForeignScan:
412  case T_CustomScan:
413  plan = create_scan_plan(root, best_path, flags);
414  break;
415  case T_HashJoin:
416  case T_MergeJoin:
417  case T_NestLoop:
419  (JoinPath *) best_path);
420  break;
421  case T_Append:
423  (AppendPath *) best_path,
424  flags);
425  break;
426  case T_MergeAppend:
428  (MergeAppendPath *) best_path,
429  flags);
430  break;
431  case T_Result:
432  if (IsA(best_path, ProjectionPath))
433  {
435  (ProjectionPath *) best_path,
436  flags);
437  }
438  else if (IsA(best_path, MinMaxAggPath))
439  {
441  (MinMaxAggPath *) best_path);
442  }
443  else if (IsA(best_path, GroupResultPath))
444  {
446  (GroupResultPath *) best_path);
447  }
448  else
449  {
450  /* Simple RTE_RESULT base relation */
451  Assert(IsA(best_path, Path));
452  plan = create_scan_plan(root, best_path, flags);
453  }
454  break;
455  case T_ProjectSet:
457  (ProjectSetPath *) best_path);
458  break;
459  case T_Material:
461  (MaterialPath *) best_path,
462  flags);
463  break;
464  case T_Memoize:
466  (MemoizePath *) best_path,
467  flags);
468  break;
469  case T_Unique:
470  if (IsA(best_path, UpperUniquePath))
471  {
473  (UpperUniquePath *) best_path,
474  flags);
475  }
476  else
477  {
478  Assert(IsA(best_path, UniquePath));
480  (UniquePath *) best_path,
481  flags);
482  }
483  break;
484  case T_Gather:
486  (GatherPath *) best_path);
487  break;
488  case T_Sort:
490  (SortPath *) best_path,
491  flags);
492  break;
493  case T_IncrementalSort:
495  (IncrementalSortPath *) best_path,
496  flags);
497  break;
498  case T_Group:
500  (GroupPath *) best_path);
501  break;
502  case T_Agg:
503  if (IsA(best_path, GroupingSetsPath))
505  (GroupingSetsPath *) best_path);
506  else
507  {
508  Assert(IsA(best_path, AggPath));
510  (AggPath *) best_path);
511  }
512  break;
513  case T_WindowAgg:
515  (WindowAggPath *) best_path);
516  break;
517  case T_SetOp:
519  (SetOpPath *) best_path,
520  flags);
521  break;
522  case T_RecursiveUnion:
524  (RecursiveUnionPath *) best_path);
525  break;
526  case T_LockRows:
528  (LockRowsPath *) best_path,
529  flags);
530  break;
531  case T_ModifyTable:
533  (ModifyTablePath *) best_path);
534  break;
535  case T_Limit:
537  (LimitPath *) best_path,
538  flags);
539  break;
540  case T_GatherMerge:
542  (GatherMergePath *) best_path);
543  break;
544  default:
545  elog(ERROR, "unrecognized node type: %d",
546  (int) best_path->pathtype);
547  plan = NULL; /* keep compiler quiet */
548  break;
549  }
550 
551  return plan;
552 }
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
Definition: createplan.c:1081
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, int flags)
Definition: createplan.c:1437
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
Definition: createplan.c:1957
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
Definition: createplan.c:1216
static Result * create_group_result_plan(PlannerInfo *root, GroupResultPath *best_path)
Definition: createplan.c:1587
static Limit * create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
Definition: createplan.c:2850
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
Definition: createplan.c:2303
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
Definition: createplan.c:2714
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
Definition: createplan.c:2175
static Unique * create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
Definition: createplan.c:2275
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
Definition: createplan.c:1919
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
Definition: createplan.c:1612
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
Definition: createplan.c:2236
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
Definition: createplan.c:2809
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
Definition: createplan.c:2545
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
Definition: createplan.c:2786
static Material * create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
Definition: createplan.c:1638
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:559
static IncrementalSort * create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path, int flags)
Definition: createplan.c:2209
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
Definition: createplan.c:2013
static Memoize * create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
Definition: createplan.c:1666
static WindowAgg * create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
Definition: createplan.c:2611
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
Definition: createplan.c:2387
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
Definition: createplan.c:2750
static Plan * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
Definition: createplan.c:1720
void check_stack_depth(void)
Definition: postgres.c:3530
NodeTag pathtype
Definition: pathnodes.h:1626

References Assert, check_stack_depth(), create_agg_plan(), create_append_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_incrementalsort_plan(), create_join_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_scan_plan(), create_setop_plan(), create_sort_plan(), create_unique_plan(), create_upper_unique_plan(), create_windowagg_plan(), elog, ERROR, IsA, Path::pathtype, plan, and root.

Referenced by create_agg_plan(), create_append_plan(), create_customscan_plan(), create_foreignscan_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_groupingsets_plan(), create_hashjoin_plan(), create_incrementalsort_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_modifytable_plan(), create_nestloop_plan(), create_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_setop_plan(), create_sort_plan(), create_unique_plan(), create_upper_unique_plan(), and create_windowagg_plan().

◆ create_project_set_plan()

static ProjectSet * create_project_set_plan ( PlannerInfo root,
ProjectSetPath best_path 
)
static

Definition at line 1612 of file createplan.c.

1613 {
1614  ProjectSet *plan;
1615  Plan *subplan;
1616  List *tlist;
1617 
1618  /* Since we intend to project, we don't need to constrain child tlist */
1619  subplan = create_plan_recurse(root, best_path->subpath, 0);
1620 
1621  tlist = build_path_tlist(root, &best_path->path);
1622 
1623  plan = make_project_set(tlist, subplan);
1624 
1625  copy_generic_path_info(&plan->plan, (Path *) best_path);
1626 
1627  return plan;
1628 }
static ProjectSet * make_project_set(List *tlist, Plan *subplan)
Definition: createplan.c:7004
Path * subpath
Definition: pathnodes.h:2186

References build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), make_project_set(), ProjectSetPath::path, plan, root, and ProjectSetPath::subpath.

Referenced by create_plan_recurse().

◆ create_projection_plan()

static Plan * create_projection_plan ( PlannerInfo root,
ProjectionPath best_path,
int  flags 
)
static

Definition at line 2013 of file createplan.c.

2014 {
2015  Plan *plan;
2016  Plan *subplan;
2017  List *tlist;
2018  bool needs_result_node = false;
2019 
2020  /*
2021  * Convert our subpath to a Plan and determine whether we need a Result
2022  * node.
2023  *
2024  * In most cases where we don't need to project, creation_projection_path
2025  * will have set dummypp, but not always. First, some createplan.c
2026  * routines change the tlists of their nodes. (An example is that
2027  * create_merge_append_plan might add resjunk sort columns to a
2028  * MergeAppend.) Second, create_projection_path has no way of knowing
2029  * what path node will be placed on top of the projection path and
2030  * therefore can't predict whether it will require an exact tlist. For
2031  * both of these reasons, we have to recheck here.
2032  */
2033  if (use_physical_tlist(root, &best_path->path, flags))
2034  {
2035  /*
2036  * Our caller doesn't really care what tlist we return, so we don't
2037  * actually need to project. However, we may still need to ensure
2038  * proper sortgroupref labels, if the caller cares about those.
2039  */
2040  subplan = create_plan_recurse(root, best_path->subpath, 0);
2041  tlist = subplan->targetlist;
2042  if (flags & CP_LABEL_TLIST)
2044  best_path->path.pathtarget);
2045  }
2046  else if (is_projection_capable_path(best_path->subpath))
2047  {
2048  /*
2049  * Our caller requires that we return the exact tlist, but no separate
2050  * result node is needed because the subpath is projection-capable.
2051  * Tell create_plan_recurse that we're going to ignore the tlist it
2052  * produces.
2053  */
2054  subplan = create_plan_recurse(root, best_path->subpath,
2055  CP_IGNORE_TLIST);
2057  tlist = build_path_tlist(root, &best_path->path);
2058  }
2059  else
2060  {
2061  /*
2062  * It looks like we need a result node, unless by good fortune the
2063  * requested tlist is exactly the one the child wants to produce.
2064  */
2065  subplan = create_plan_recurse(root, best_path->subpath, 0);
2066  tlist = build_path_tlist(root, &best_path->path);
2067  needs_result_node = !tlist_same_exprs(tlist, subplan->targetlist);
2068  }
2069 
2070  /*
2071  * If we make a different decision about whether to include a Result node
2072  * than create_projection_path did, we'll have made slightly wrong cost
2073  * estimates; but label the plan with the cost estimates we actually used,
2074  * not "corrected" ones. (XXX this could be cleaned up if we moved more
2075  * of the sortcolumn setup logic into Path creation, but that would add
2076  * expense to creating Paths we might end up not using.)
2077  */
2078  if (!needs_result_node)
2079  {
2080  /* Don't need a separate Result, just assign tlist to subplan */
2081  plan = subplan;
2082  plan->targetlist = tlist;
2083 
2084  /* Label plan with the estimated costs we actually used */
2085  plan->startup_cost = best_path->path.startup_cost;
2086  plan->total_cost = best_path->path.total_cost;
2087  plan->plan_rows = best_path->path.rows;
2088  plan->plan_width = best_path->path.pathtarget->width;
2089  plan->parallel_safe = best_path->path.parallel_safe;
2090  /* ... but don't change subplan's parallel_aware flag */
2091  }
2092  else
2093  {
2094  /* We need a Result node */
2095  plan = (Plan *) make_result(tlist, NULL, subplan);
2096 
2097  copy_generic_path_info(plan, (Path *) best_path);
2098  }
2099 
2100  return plan;
2101 }
static bool use_physical_tlist(PlannerInfo *root, Path *path, int flags)
Definition: createplan.c:865
bool is_projection_capable_path(Path *path)
Definition: createplan.c:7202
#define CP_IGNORE_TLIST
Definition: createplan.c:72
Path * subpath
Definition: pathnodes.h:2174
void apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
Definition: tlist.c:774

References apply_pathtarget_labeling_to_tlist(), Assert, build_path_tlist(), copy_generic_path_info(), CP_IGNORE_TLIST, CP_LABEL_TLIST, create_plan_recurse(), is_projection_capable_path(), is_projection_capable_plan(), make_result(), Path::parallel_safe, ProjectionPath::path, plan, root, Path::rows, Path::startup_cost, ProjectionPath::subpath, Plan::targetlist, tlist_same_exprs(), Path::total_cost, and use_physical_tlist().

Referenced by create_plan_recurse().

◆ create_recursiveunion_plan()

static RecursiveUnion * create_recursiveunion_plan ( PlannerInfo root,
RecursiveUnionPath best_path 
)
static

Definition at line 2750 of file createplan.c.

2751 {
2753  Plan *leftplan;
2754  Plan *rightplan;
2755  List *tlist;
2756  long numGroups;
2757 
2758  /* Need both children to produce same tlist, so force it */
2759  leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
2760  rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
2761 
2762  tlist = build_path_tlist(root, &best_path->path);
2763 
2764  /* Convert numGroups to long int --- but 'ware overflow! */
2765  numGroups = clamp_cardinality_to_long(best_path->numGroups);
2766 
2767  plan = make_recursive_union(tlist,
2768  leftplan,
2769  rightplan,
2770  best_path->wtParam,
2771  best_path->distinctList,
2772  numGroups);
2773 
2774  copy_generic_path_info(&plan->plan, (Path *) best_path);
2775 
2776  return plan;
2777 }
long clamp_cardinality_to_long(Cardinality x)
Definition: costsize.c:254
static RecursiveUnion * make_recursive_union(List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, long numGroups)
Definition: createplan.c:5857
Cardinality numGroups
Definition: pathnodes.h:2352

References build_path_tlist(), clamp_cardinality_to_long(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), RecursiveUnionPath::distinctList, RecursiveUnionPath::leftpath, make_recursive_union(), RecursiveUnionPath::numGroups, RecursiveUnionPath::path, plan, RecursiveUnionPath::rightpath, root, and RecursiveUnionPath::wtParam.

Referenced by create_plan_recurse().

◆ create_resultscan_plan()

static Result * create_resultscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 4019 of file createplan.c.

4021 {
4022  Result *scan_plan;
4023  Index scan_relid = best_path->parent->relid;
4025 
4026  Assert(scan_relid > 0);
4027  rte = planner_rt_fetch(scan_relid, root);
4028  Assert(rte->rtekind == RTE_RESULT);
4029 
4030  /* Sort clauses into best execution order */
4031  scan_clauses = order_qual_clauses(root, scan_clauses);
4032 
4033  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
4034  scan_clauses = extract_actual_clauses(scan_clauses, false);
4035 
4036  /* Replace any outer-relation variables with nestloop params */
4037  if (best_path->param_info)
4038  {
4039  scan_clauses = (List *)
4040  replace_nestloop_params(root, (Node *) scan_clauses);
4041  }
4042 
4043  scan_plan = make_result(tlist, (Node *) scan_clauses, NULL);
4044 
4045  copy_generic_path_info(&scan_plan->plan, best_path);
4046 
4047  return scan_plan;
4048 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:182
@ RTE_RESULT
Definition: parsenodes.h:1036

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_result(), order_qual_clauses(), PG_USED_FOR_ASSERTS_ONLY, Result::plan, planner_rt_fetch, replace_nestloop_params(), root, and RTE_RESULT.

Referenced by create_scan_plan().

◆ create_samplescan_plan()

static SampleScan * create_samplescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 2949 of file createplan.c.

2951 {
2952  SampleScan *scan_plan;
2953  Index scan_relid = best_path->parent->relid;
2954  RangeTblEntry *rte;
2955  TableSampleClause *tsc;
2956 
2957  /* it should be a base rel with a tablesample clause... */
2958  Assert(scan_relid > 0);
2959  rte = planner_rt_fetch(scan_relid, root);
2960  Assert(rte->rtekind == RTE_RELATION);
2961  tsc = rte->tablesample;
2962  Assert(tsc != NULL);
2963 
2964  /* Sort clauses into best execution order */
2965  scan_clauses = order_qual_clauses(root, scan_clauses);
2966 
2967  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2968  scan_clauses = extract_actual_clauses(scan_clauses, false);
2969 
2970  /* Replace any outer-relation variables with nestloop params */
2971  if (best_path->param_info)
2972  {
2973  scan_clauses = (List *)
2974  replace_nestloop_params(root, (Node *) scan_clauses);
2975  tsc = (TableSampleClause *)
2976  replace_nestloop_params(root, (Node *) tsc);
2977  }
2978 
2979  scan_plan = make_samplescan(tlist,
2980  scan_clauses,
2981  scan_relid,
2982  tsc);
2983 
2984  copy_generic_path_info(&scan_plan->scan.plan, best_path);
2985 
2986  return scan_plan;
2987 }
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:5520
struct TableSampleClause * tablesample
Definition: parsenodes.h:1108
Scan scan
Definition: plannodes.h:407

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_samplescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_RELATION, RangeTblEntry::rtekind, SampleScan::scan, and RangeTblEntry::tablesample.

Referenced by create_scan_plan().

◆ create_scan_plan()

static Plan * create_scan_plan ( PlannerInfo root,
Path best_path,
int  flags 
)
static

Definition at line 559 of file createplan.c.

560 {
561  RelOptInfo *rel = best_path->parent;
562  List *scan_clauses;
563  List *gating_clauses;
564  List *tlist;
565  Plan *plan;
566 
567  /*
568  * Extract the relevant restriction clauses from the parent relation. The
569  * executor must apply all these restrictions during the scan, except for
570  * pseudoconstants which we'll take care of below.
571  *
572  * If this is a plain indexscan or index-only scan, we need not consider
573  * restriction clauses that are implied by the index's predicate, so use
574  * indrestrictinfo not baserestrictinfo. Note that we can't do that for
575  * bitmap indexscans, since there's not necessarily a single index
576  * involved; but it doesn't matter since create_bitmap_scan_plan() will be
577  * able to get rid of such clauses anyway via predicate proof.
578  */
579  switch (best_path->pathtype)
580  {
581  case T_IndexScan:
582  case T_IndexOnlyScan:
583  scan_clauses = castNode(IndexPath, best_path)->indexinfo->indrestrictinfo;
584  break;
585  default:
586  scan_clauses = rel->baserestrictinfo;
587  break;
588  }
589 
590  /*
591  * If this is a parameterized scan, we also need to enforce all the join
592  * clauses available from the outer relation(s).
593  *
594  * For paranoia's sake, don't modify the stored baserestrictinfo list.
595  */
596  if (best_path->param_info)
597  scan_clauses = list_concat_copy(scan_clauses,
598  best_path->param_info->ppi_clauses);
599 
600  /*
601  * Detect whether we have any pseudoconstant quals to deal with. Then, if
602  * we'll need a gating Result node, it will be able to project, so there
603  * are no requirements on the child's tlist.
604  *
605  * If this replaces a join, it must be a foreign scan or a custom scan,
606  * and the FDW or the custom scan provider would have stored in the best
607  * path the list of RestrictInfo nodes to apply to the join; check against
608  * that list in that case.
609  */
610  if (IS_JOIN_REL(rel))
611  {
612  List *join_clauses;
613 
614  Assert(best_path->pathtype == T_ForeignScan ||
615  best_path->pathtype == T_CustomScan);
616  if (best_path->pathtype == T_ForeignScan)
617  join_clauses = ((ForeignPath *) best_path)->fdw_restrictinfo;
618  else
619  join_clauses = ((CustomPath *) best_path)->custom_restrictinfo;
620 
621  gating_clauses = get_gating_quals(root, join_clauses);
622  }
623  else
624  gating_clauses = get_gating_quals(root, scan_clauses);
625  if (gating_clauses)
626  flags = 0;
627 
628  /*
629  * For table scans, rather than using the relation targetlist (which is
630  * only those Vars actually needed by the query), we prefer to generate a
631  * tlist containing all Vars in order. This will allow the executor to
632  * optimize away projection of the table tuples, if possible.
633  *
634  * But if the caller is going to ignore our tlist anyway, then don't
635  * bother generating one at all. We use an exact equality test here, so
636  * that this only applies when CP_IGNORE_TLIST is the only flag set.
637  */
638  if (flags == CP_IGNORE_TLIST)
639  {
640  tlist = NULL;
641  }
642  else if (use_physical_tlist(root, best_path, flags))
643  {
644  if (best_path->pathtype == T_IndexOnlyScan)
645  {
646  /* For index-only scan, the preferred tlist is the index's */
647  tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
648 
649  /*
650  * Transfer sortgroupref data to the replacement tlist, if
651  * requested (use_physical_tlist checked that this will work).
652  */
653  if (flags & CP_LABEL_TLIST)
654  apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
655  }
656  else
657  {
658  tlist = build_physical_tlist(root, rel);
659  if (tlist == NIL)
660  {
661  /* Failed because of dropped cols, so use regular method */
662  tlist = build_path_tlist(root, best_path);
663  }
664  else
665  {
666  /* As above, transfer sortgroupref data to replacement tlist */
667  if (flags & CP_LABEL_TLIST)
668  apply_pathtarget_labeling_to_tlist(tlist, best_path->pathtarget);
669  }
670  }
671  }
672  else
673  {
674  tlist = build_path_tlist(root, best_path);
675  }
676 
677  switch (best_path->pathtype)
678  {
679  case T_SeqScan:
681  best_path,
682  tlist,
683  scan_clauses);
684  break;
685 
686  case T_SampleScan:
688  best_path,
689  tlist,
690  scan_clauses);
691  break;
692 
693  case T_IndexScan:
695  (IndexPath *) best_path,
696  tlist,
697  scan_clauses,
698  false);
699  break;
700 
701  case T_IndexOnlyScan:
703  (IndexPath *) best_path,
704  tlist,
705  scan_clauses,
706  true);
707  break;
708 
709  case T_BitmapHeapScan:
711  (BitmapHeapPath *) best_path,
712  tlist,
713  scan_clauses);
714  break;
715 
716  case T_TidScan:
718  (TidPath *) best_path,
719  tlist,
720  scan_clauses);
721  break;
722 
723  case T_TidRangeScan:
725  (TidRangePath *) best_path,
726  tlist,
727  scan_clauses);
728  break;
729 
730  case T_SubqueryScan:
732  (SubqueryScanPath *) best_path,
733  tlist,
734  scan_clauses);
735  break;
736 
737  case T_FunctionScan:
739  best_path,
740  tlist,
741  scan_clauses);
742  break;
743 
744  case T_TableFuncScan:
746  best_path,
747  tlist,
748  scan_clauses);
749  break;
750 
751  case T_ValuesScan:
753  best_path,
754  tlist,
755  scan_clauses);
756  break;
757 
758  case T_CteScan:
760  best_path,
761  tlist,
762  scan_clauses);
763  break;
764 
765  case T_NamedTuplestoreScan:
767  best_path,
768  tlist,
769  scan_clauses);
770  break;
771 
772  case T_Result:
774  best_path,
775  tlist,
776  scan_clauses);
777  break;
778 
779  case T_WorkTableScan:
781  best_path,
782  tlist,
783  scan_clauses);
784  break;
785 
786  case T_ForeignScan:
788  (ForeignPath *) best_path,
789  tlist,
790  scan_clauses);
791  break;
792 
793  case T_CustomScan:
795  (CustomPath *) best_path,
796  tlist,
797  scan_clauses);
798  break;
799 
800  default:
801  elog(ERROR, "unrecognized node type: %d",
802  (int) best_path->pathtype);
803  plan = NULL; /* keep compiler quiet */
804  break;
805  }
806 
807  /*
808  * If there are any pseudoconstant clauses attached to this node, insert a
809  * gating Result node that evaluates the pseudoconstants as one-time
810  * quals.
811  */
812  if (gating_clauses)
813  plan = create_gating_plan(root, best_path, plan, gating_clauses);
814 
815  return plan;
816 }
static SeqScan * create_seqscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2911
static ValuesScan * create_valuesscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3841
static TableFuncScan * create_tablefuncscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3798
static CustomScan * create_customscan_plan(PlannerInfo *root, CustomPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4271
static ForeignScan * create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4116
static BitmapHeapScan * create_bitmap_scan_plan(PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3196
static TidScan * create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3534
static WorkTableScan * create_worktablescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4056
static FunctionScan * create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3755
static Result * create_resultscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4019
static CteScan * create_ctescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3885
static NamedTuplestoreScan * create_namedtuplestorescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3980
static SubqueryScan * create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3696
static TidRangeScan * create_tidrangescan_plan(PlannerInfo *root, TidRangePath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3631
static SampleScan * create_samplescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2949
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:598
#define copyObject(obj)
Definition: nodes.h:224
#define IS_JOIN_REL(rel)
Definition: pathnodes.h:838
List * build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
Definition: plancat.c:1752

References apply_pathtarget_labeling_to_tlist(), Assert, RelOptInfo::baserestrictinfo, build_path_tlist(), build_physical_tlist(), castNode, copyObject, CP_IGNORE_TLIST, CP_LABEL_TLIST, create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_gating_plan(), create_indexscan_plan(), create_namedtuplestorescan_plan(), create_resultscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidrangescan_plan(), create_tidscan_plan(), create_valuesscan_plan(), create_worktablescan_plan(), elog, ERROR, get_gating_quals(), IS_JOIN_REL, list_concat_copy(), NIL, Path::pathtype, plan, root, and use_physical_tlist().

Referenced by create_plan_recurse().

◆ create_seqscan_plan()

static SeqScan * create_seqscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 2911 of file createplan.c.

2913 {
2914  SeqScan *scan_plan;
2915  Index scan_relid = best_path->parent->relid;
2916 
2917  /* it should be a base rel... */
2918  Assert(scan_relid > 0);
2919  Assert(best_path->parent->rtekind == RTE_RELATION);
2920 
2921  /* Sort clauses into best execution order */
2922  scan_clauses = order_qual_clauses(root, scan_clauses);
2923 
2924  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2925  scan_clauses = extract_actual_clauses(scan_clauses, false);
2926 
2927  /* Replace any outer-relation variables with nestloop params */
2928  if (best_path->param_info)
2929  {
2930  scan_clauses = (List *)
2931  replace_nestloop_params(root, (Node *) scan_clauses);
2932  }
2933 
2934  scan_plan = make_seqscan(tlist,
2935  scan_clauses,
2936  scan_relid);
2937 
2938  copy_generic_path_info(&scan_plan->scan.plan, best_path);
2939 
2940  return scan_plan;
2941 }
static SeqScan * make_seqscan(List *qptlist, List *qpqual, Index scanrelid)
Definition: createplan.c:5503
Scan scan
Definition: plannodes.h:398

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_seqscan(), order_qual_clauses(), replace_nestloop_params(), root, RTE_RELATION, and SeqScan::scan.

Referenced by create_scan_plan().

◆ create_setop_plan()

static SetOp * create_setop_plan ( PlannerInfo root,
SetOpPath best_path,
int  flags 
)
static

Definition at line 2714 of file createplan.c.

2715 {
2716  SetOp *plan;
2717  Plan *subplan;
2718  long numGroups;
2719 
2720  /*
2721  * SetOp doesn't project, so tlist requirements pass through; moreover we
2722  * need grouping columns to be labeled.
2723  */
2724  subplan = create_plan_recurse(root, best_path->subpath,
2725  flags | CP_LABEL_TLIST);
2726 
2727  /* Convert numGroups to long int --- but 'ware overflow! */
2728  numGroups = clamp_cardinality_to_long(best_path->numGroups);
2729 
2730  plan = make_setop(best_path->cmd,
2731  best_path->strategy,
2732  subplan,
2733  best_path->distinctList,
2734  best_path->flagColIdx,
2735  best_path->firstFlag,
2736  numGroups);
2737 
2738  copy_generic_path_info(&plan->plan, (Path *) best_path);
2739 
2740  return plan;
2741 }
static SetOp * make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, List *distinctList, AttrNumber flagColIdx, int firstFlag, long numGroups)
Definition: createplan.c:6878
List * distinctList
Definition: pathnodes.h:2336
Cardinality numGroups
Definition: pathnodes.h:2339
int firstFlag
Definition: pathnodes.h:2338
Path * subpath
Definition: pathnodes.h:2333
SetOpCmd cmd
Definition: pathnodes.h:2334
SetOpStrategy strategy
Definition: pathnodes.h:2335
AttrNumber flagColIdx
Definition: pathnodes.h:2337

References clamp_cardinality_to_long(), SetOpPath::cmd, copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), SetOpPath::distinctList, SetOpPath::firstFlag, SetOpPath::flagColIdx, make_setop(), SetOpPath::numGroups, plan, root, SetOpPath::strategy, and SetOpPath::subpath.

Referenced by create_plan_recurse().

◆ create_sort_plan()

static Sort * create_sort_plan ( PlannerInfo root,
SortPath best_path,
int  flags 
)
static

Definition at line 2175 of file createplan.c.

2176 {
2177  Sort *plan;
2178  Plan *subplan;
2179 
2180  /*
2181  * We don't want any excess columns in the sorted tuples, so request a
2182  * smaller tlist. Otherwise, since Sort doesn't project, tlist
2183  * requirements pass through.
2184  */
2185  subplan = create_plan_recurse(root, best_path->subpath,
2186  flags | CP_SMALL_TLIST);
2187 
2188  /*
2189  * make_sort_from_pathkeys indirectly calls find_ec_member_matching_expr,
2190  * which will ignore any child EC members that don't belong to the given
2191  * relids. Thus, if this sort path is based on a child relation, we must
2192  * pass its relids.
2193  */
2194  plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys,
2195  IS_OTHER_REL(best_path->subpath->parent) ?
2196  best_path->path.parent->relids : NULL);
2197 
2198  copy_generic_path_info(&plan->plan, (Path *) best_path);
2199 
2200  return plan;
2201 }

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), IS_OTHER_REL, make_sort_from_pathkeys(), SortPath::path, Path::pathkeys, plan, root, and SortPath::subpath.

Referenced by create_plan_recurse().

◆ create_subqueryscan_plan()

static SubqueryScan * create_subqueryscan_plan ( PlannerInfo root,
SubqueryScanPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3696 of file createplan.c.

3698 {
3699  SubqueryScan *scan_plan;
3700  RelOptInfo *rel = best_path->path.parent;
3701  Index scan_relid = rel->relid;
3702  Plan *subplan;
3703 
3704  /* it should be a subquery base rel... */
3705  Assert(scan_relid > 0);
3706  Assert(rel->rtekind == RTE_SUBQUERY);
3707 
3708  /*
3709  * Recursively create Plan from Path for subquery. Since we are entering
3710  * a different planner context (subroot), recurse to create_plan not
3711  * create_plan_recurse.
3712  */
3713  subplan = create_plan(rel->subroot, best_path->subpath);
3714 
3715  /* Sort clauses into best execution order */
3716  scan_clauses = order_qual_clauses(root, scan_clauses);
3717 
3718  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3719  scan_clauses = extract_actual_clauses(scan_clauses, false);
3720 
3721  /*
3722  * Replace any outer-relation variables with nestloop params.
3723  *
3724  * We must provide nestloop params for both lateral references of the
3725  * subquery and outer vars in the scan_clauses. It's better to assign the
3726  * former first, because that code path requires specific param IDs, while
3727  * replace_nestloop_params can adapt to the IDs assigned by
3728  * process_subquery_nestloop_params. This avoids possibly duplicating
3729  * nestloop params when the same Var is needed for both reasons.
3730  */
3731  if (best_path->path.param_info)
3732  {
3734  rel->subplan_params);
3735  scan_clauses = (List *)
3736  replace_nestloop_params(root, (Node *) scan_clauses);
3737  }
3738 
3739  scan_plan = make_subqueryscan(tlist,
3740  scan_clauses,
3741  scan_relid,
3742  subplan);
3743 
3744  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3745 
3746  return scan_plan;
3747 }
static SubqueryScan * make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan)
Definition: createplan.c:5678
void process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
Definition: paramassign.c:480
@ RTE_SUBQUERY
Definition: parsenodes.h:1029
List * subplan_params
Definition: pathnodes.h:948
PlannerInfo * subroot
Definition: pathnodes.h:947

References Assert, copy_generic_path_info(), create_plan(), extract_actual_clauses(), make_subqueryscan(), order_qual_clauses(), SubqueryScanPath::path, process_subquery_nestloop_params(), RelOptInfo::relid, replace_nestloop_params(), root, RTE_SUBQUERY, RelOptInfo::rtekind, SubqueryScan::scan, SubqueryScanPath::subpath, RelOptInfo::subplan_params, and RelOptInfo::subroot.

Referenced by create_scan_plan().

◆ create_tablefuncscan_plan()

static TableFuncScan * create_tablefuncscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3798 of file createplan.c.

3800 {
3801  TableFuncScan *scan_plan;
3802  Index scan_relid = best_path->parent->relid;
3803  RangeTblEntry *rte;
3804  TableFunc *tablefunc;
3805 
3806  /* it should be a function base rel... */
3807  Assert(scan_relid > 0);
3808  rte = planner_rt_fetch(scan_relid, root);
3809  Assert(rte->rtekind == RTE_TABLEFUNC);
3810  tablefunc = rte->tablefunc;
3811 
3812  /* Sort clauses into best execution order */
3813  scan_clauses = order_qual_clauses(root, scan_clauses);
3814 
3815  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3816  scan_clauses = extract_actual_clauses(scan_clauses, false);
3817 
3818  /* Replace any outer-relation variables with nestloop params */
3819  if (best_path->param_info)
3820  {
3821  scan_clauses = (List *)
3822  replace_nestloop_params(root, (Node *) scan_clauses);
3823  /* The function expressions could contain nestloop params, too */
3824  tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
3825  }
3826 
3827  scan_plan = make_tablefuncscan(tlist, scan_clauses, scan_relid,
3828  tablefunc);
3829 
3830  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3831 
3832  return scan_plan;
3833 }
static TableFuncScan * make_tablefuncscan(List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
Definition: createplan.c:5719
@ RTE_TABLEFUNC
Definition: parsenodes.h:1032
TableFunc * tablefunc
Definition: parsenodes.h:1194

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_tablefuncscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_TABLEFUNC, RangeTblEntry::rtekind, TableFuncScan::scan, and RangeTblEntry::tablefunc.

Referenced by create_scan_plan().

◆ create_tidrangescan_plan()

static TidRangeScan * create_tidrangescan_plan ( PlannerInfo root,
TidRangePath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3631 of file createplan.c.

3633 {
3634  TidRangeScan *scan_plan;
3635  Index scan_relid = best_path->path.parent->relid;
3636  List *tidrangequals = best_path->tidrangequals;
3637 
3638  /* it should be a base rel... */
3639  Assert(scan_relid > 0);
3640  Assert(best_path->path.parent->rtekind == RTE_RELATION);
3641 
3642  /*
3643  * The qpqual list must contain all restrictions not enforced by the
3644  * tidrangequals list. tidrangequals has AND semantics, so we can simply
3645  * remove any qual that appears in it.
3646  */
3647  {
3648  List *qpqual = NIL;
3649  ListCell *l;
3650 
3651  foreach(l, scan_clauses)
3652  {
3653  RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
3654 
3655  if (rinfo->pseudoconstant)
3656  continue; /* we may drop pseudoconstants here */
3657  if (list_member_ptr(tidrangequals, rinfo))
3658  continue; /* simple duplicate */
3659  qpqual = lappend(qpqual, rinfo);
3660  }
3661  scan_clauses = qpqual;
3662  }
3663 
3664  /* Sort clauses into best execution order */
3665  scan_clauses = order_qual_clauses(root, scan_clauses);
3666 
3667  /* Reduce RestrictInfo lists to bare expressions; ignore pseudoconstants */
3668  tidrangequals = extract_actual_clauses(tidrangequals, false);
3669  scan_clauses = extract_actual_clauses(scan_clauses, false);
3670 
3671  /* Replace any outer-relation variables with nestloop params */
3672  if (best_path->path.param_info)
3673  {
3674  tidrangequals = (List *)
3675  replace_nestloop_params(root, (Node *) tidrangequals);
3676  scan_clauses = (List *)
3677  replace_nestloop_params(root, (Node *) scan_clauses);
3678  }
3679 
3680  scan_plan = make_tidrangescan(tlist,
3681  scan_clauses,
3682  scan_relid,
3683  tidrangequals);
3684 
3685  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3686 
3687  return scan_plan;
3688 }
static TidRangeScan * make_tidrangescan(List *qptlist, List *qpqual, Index scanrelid, List *tidrangequals)
Definition: createplan.c:5659
List * tidrangequals
Definition: pathnodes.h:1836

References Assert, copy_generic_path_info(), extract_actual_clauses(), lappend(), lfirst_node, list_member_ptr(), make_tidrangescan(), NIL, order_qual_clauses(), TidRangePath::path, replace_nestloop_params(), root, RTE_RELATION, TidRangeScan::scan, and TidRangePath::tidrangequals.

Referenced by create_scan_plan().

◆ create_tidscan_plan()

static TidScan * create_tidscan_plan ( PlannerInfo root,
TidPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3534 of file createplan.c.

3536 {
3537  TidScan *scan_plan;
3538  Index scan_relid = best_path->path.parent->relid;
3539  List *tidquals = best_path->tidquals;
3540 
3541  /* it should be a base rel... */
3542  Assert(scan_relid > 0);
3543  Assert(best_path->path.parent->rtekind == RTE_RELATION);
3544 
3545  /*
3546  * The qpqual list must contain all restrictions not enforced by the
3547  * tidquals list. Since tidquals has OR semantics, we have to be careful
3548  * about matching it up to scan_clauses. It's convenient to handle the
3549  * single-tidqual case separately from the multiple-tidqual case. In the
3550  * single-tidqual case, we look through the scan_clauses while they are
3551  * still in RestrictInfo form, and drop any that are redundant with the
3552  * tidqual.
3553  *
3554  * In normal cases simple pointer equality checks will be enough to spot
3555  * duplicate RestrictInfos, so we try that first.
3556  *
3557  * Another common case is that a scan_clauses entry is generated from the
3558  * same EquivalenceClass as some tidqual, and is therefore redundant with
3559  * it, though not equal.
3560  *
3561  * Unlike indexpaths, we don't bother with predicate_implied_by(); the
3562  * number of cases where it could win are pretty small.
3563  */
3564  if (list_length(tidquals) == 1)
3565  {
3566  List *qpqual = NIL;
3567  ListCell *l;
3568 
3569  foreach(l, scan_clauses)
3570  {
3571  RestrictInfo *rinfo = lfirst_node(RestrictInfo, l);
3572 
3573  if (rinfo->pseudoconstant)
3574  continue; /* we may drop pseudoconstants here */
3575  if (list_member_ptr(tidquals, rinfo))
3576  continue; /* simple duplicate */
3577  if (is_redundant_derived_clause(rinfo, tidquals))
3578  continue; /* derived from same EquivalenceClass */
3579  qpqual = lappend(qpqual, rinfo);
3580  }
3581  scan_clauses = qpqual;
3582  }
3583 
3584  /* Sort clauses into best execution order */
3585  scan_clauses = order_qual_clauses(root, scan_clauses);
3586 
3587  /* Reduce RestrictInfo lists to bare expressions; ignore pseudoconstants */
3588  tidquals = extract_actual_clauses(tidquals, false);
3589  scan_clauses = extract_actual_clauses(scan_clauses, false);
3590 
3591  /*
3592  * If we have multiple tidquals, it's more convenient to remove duplicate
3593  * scan_clauses after stripping the RestrictInfos. In this situation,
3594  * because the tidquals represent OR sub-clauses, they could not have come
3595  * from EquivalenceClasses so we don't have to worry about matching up
3596  * non-identical clauses. On the other hand, because tidpath.c will have
3597  * extracted those sub-clauses from some OR clause and built its own list,
3598  * we will certainly not have pointer equality to any scan clause. So
3599  * convert the tidquals list to an explicit OR clause and see if we can
3600  * match it via equal() to any scan clause.
3601  */
3602  if (list_length(tidquals) > 1)
3603  scan_clauses = list_difference(scan_clauses,
3604  list_make1(make_orclause(tidquals)));
3605 
3606  /* Replace any outer-relation variables with nestloop params */
3607  if (best_path->path.param_info)
3608  {
3609  tidquals = (List *)
3610  replace_nestloop_params(root, (Node *) tidquals);
3611  scan_clauses = (List *)
3612  replace_nestloop_params(root, (Node *) scan_clauses);
3613  }
3614 
3615  scan_plan = make_tidscan(tlist,
3616  scan_clauses,
3617  scan_relid,
3618  tidquals);
3619 
3620  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3621 
3622  return scan_plan;
3623 }
static TidScan * make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tidquals)
Definition: createplan.c:5640
bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)
Definition: equivclass.c:3270
List * tidquals
Definition: pathnodes.h:1824
Path path
Definition: pathnodes.h:1823
Scan scan
Definition: plannodes.h:554

References Assert, copy_generic_path_info(), extract_actual_clauses(), is_redundant_derived_clause(), lappend(), lfirst_node, list_difference(), list_length(), list_make1, list_member_ptr(), make_orclause(), make_tidscan(), NIL, order_qual_clauses(), TidPath::path, replace_nestloop_params(), root, RTE_RELATION, TidScan::scan, and TidPath::tidquals.

Referenced by create_scan_plan().

◆ create_unique_plan()

static Plan * create_unique_plan ( PlannerInfo root,
UniquePath best_path,
int  flags 
)
static

Definition at line 1720 of file createplan.c.

1721 {
1722  Plan *plan;
1723  Plan *subplan;
1724  List *in_operators;
1725  List *uniq_exprs;
1726  List *newtlist;
1727  int nextresno;
1728  bool newitems;
1729  int numGroupCols;
1730  AttrNumber *groupColIdx;
1731  Oid *groupCollations;
1732  int groupColPos;
1733  ListCell *l;
1734 
1735  /* Unique doesn't project, so tlist requirements pass through */
1736  subplan = create_plan_recurse(root, best_path->subpath, flags);
1737 
1738  /* Done if we don't need to do any actual unique-ifying */
1739  if (best_path->umethod == UNIQUE_PATH_NOOP)
1740  return subplan;
1741 
1742  /*
1743  * As constructed, the subplan has a "flat" tlist containing just the Vars
1744  * needed here and at upper levels. The values we are supposed to
1745  * unique-ify may be expressions in these variables. We have to add any
1746  * such expressions to the subplan's tlist.
1747  *
1748  * The subplan may have a "physical" tlist if it is a simple scan plan. If
1749  * we're going to sort, this should be reduced to the regular tlist, so
1750  * that we don't sort more data than we need to. For hashing, the tlist
1751  * should be left as-is if we don't need to add any expressions; but if we
1752  * do have to add expressions, then a projection step will be needed at
1753  * runtime anyway, so we may as well remove unneeded items. Therefore
1754  * newtlist starts from build_path_tlist() not just a copy of the
1755  * subplan's tlist; and we don't install it into the subplan unless we are
1756  * sorting or stuff has to be added.
1757  */
1758  in_operators = best_path->in_operators;
1759  uniq_exprs = best_path->uniq_exprs;
1760 
1761  /* initialize modified subplan tlist as just the "required" vars */
1762  newtlist = build_path_tlist(root, &best_path->path);
1763  nextresno = list_length(newtlist) + 1;
1764  newitems = false;
1765 
1766  foreach(l, uniq_exprs)
1767  {
1768  Expr *uniqexpr = lfirst(l);
1769  TargetEntry *tle;
1770 
1771  tle = tlist_member(uniqexpr, newtlist);
1772  if (!tle)
1773  {
1774  tle = makeTargetEntry((Expr *) uniqexpr,
1775  nextresno,
1776  NULL,
1777  false);
1778  newtlist = lappend(newtlist, tle);
1779  nextresno++;
1780  newitems = true;
1781  }
1782  }
1783 
1784  /* Use change_plan_targetlist in case we need to insert a Result node */
1785  if (newitems || best_path->umethod == UNIQUE_PATH_SORT)
1786  subplan = change_plan_targetlist(subplan, newtlist,
1787  best_path->path.parallel_safe);
1788 
1789  /*
1790  * Build control information showing which subplan output columns are to
1791  * be examined by the grouping step. Unfortunately we can't merge this
1792  * with the previous loop, since we didn't then know which version of the
1793  * subplan tlist we'd end up using.
1794  */
1795  newtlist = subplan->targetlist;
1796  numGroupCols = list_length(uniq_exprs);
1797  groupColIdx = (AttrNumber *) palloc(numGroupCols * sizeof(AttrNumber));
1798  groupCollations = (Oid *) palloc(numGroupCols * sizeof(Oid));
1799 
1800  groupColPos = 0;
1801  foreach(l, uniq_exprs)
1802  {
1803  Expr *uniqexpr = lfirst(l);
1804  TargetEntry *tle;
1805 
1806  tle = tlist_member(uniqexpr, newtlist);
1807  if (!tle) /* shouldn't happen */
1808  elog(ERROR, "failed to find unique expression in subplan tlist");
1809  groupColIdx[groupColPos] = tle->resno;
1810  groupCollations[groupColPos] = exprCollation((Node *) tle->expr);
1811  groupColPos++;
1812  }
1813 
1814  if (best_path->umethod == UNIQUE_PATH_HASH)
1815  {
1816  Oid *groupOperators;
1817 
1818  /*
1819  * Get the hashable equality operators for the Agg node to use.
1820  * Normally these are the same as the IN clause operators, but if
1821  * those are cross-type operators then the equality operators are the
1822  * ones for the IN clause operators' RHS datatype.
1823  */
1824  groupOperators = (Oid *) palloc(numGroupCols * sizeof(Oid));
1825  groupColPos = 0;
1826  foreach(l, in_operators)
1827  {
1828  Oid in_oper = lfirst_oid(l);
1829  Oid eq_oper;
1830 
1831  if (!get_compatible_hash_operators(in_oper, NULL, &eq_oper))
1832  elog(ERROR, "could not find compatible hash operator for operator %u",
1833  in_oper);
1834  groupOperators[groupColPos++] = eq_oper;
1835  }
1836 
1837  /*
1838  * Since the Agg node is going to project anyway, we can give it the
1839  * minimum output tlist, without any stuff we might have added to the
1840  * subplan tlist.
1841  */
1842  plan = (Plan *) make_agg(build_path_tlist(root, &best_path->path),
1843  NIL,
1844  AGG_HASHED,
1846  numGroupCols,
1847  groupColIdx,
1848  groupOperators,
1849  groupCollations,
1850  NIL,
1851  NIL,
1852  best_path->path.rows,
1853  0,
1854  subplan);
1855  }
1856  else
1857  {
1858  List *sortList = NIL;
1859  Sort *sort;
1860 
1861  /* Create an ORDER BY list to sort the input compatibly */
1862  groupColPos = 0;
1863  foreach(l, in_operators)
1864  {
1865  Oid in_oper = lfirst_oid(l);
1866  Oid sortop;
1867  Oid eqop;
1868  TargetEntry *tle;
1869  SortGroupClause *sortcl;
1870 
1871  sortop = get_ordering_op_for_equality_op(in_oper, false);
1872  if (!OidIsValid(sortop)) /* shouldn't happen */
1873  elog(ERROR, "could not find ordering operator for equality operator %u",
1874  in_oper);
1875 
1876  /*
1877  * The Unique node will need equality operators. Normally these
1878  * are the same as the IN clause operators, but if those are
1879  * cross-type operators then the equality operators are the ones
1880  * for the IN clause operators' RHS datatype.
1881  */
1882  eqop = get_equality_op_for_ordering_op(sortop, NULL);
1883  if (!OidIsValid(eqop)) /* shouldn't happen */
1884  elog(ERROR, "could not find equality operator for ordering operator %u",
1885  sortop);
1886 
1887  tle = get_tle_by_resno(subplan->targetlist,
1888  groupColIdx[groupColPos]);
1889  Assert(tle != NULL);
1890 
1891  sortcl = makeNode(SortGroupClause);
1892  sortcl->tleSortGroupRef = assignSortGroupRef(tle,
1893  subplan->targetlist);
1894  sortcl->eqop = eqop;
1895  sortcl->sortop = sortop;
1896  sortcl->nulls_first = false;
1897  sortcl->hashable = false; /* no need to make this accurate */
1898  sortList = lappend(sortList, sortcl);
1899  groupColPos++;
1900  }
1901  sort = make_sort_from_sortclauses(sortList, subplan);
1903  plan = (Plan *) make_unique_from_sortclauses((Plan *) sort, sortList);
1904  }
1905 
1906  /* Copy cost data from Path to Plan */
1907  copy_generic_path_info(plan, &best_path->path);
1908 
1909  return plan;
1910 }
static Unique * make_unique_from_sortclauses(Plan *lefttree, List *distinctList)
Definition: createplan.c:6694
Sort * make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
Definition: createplan.c:6410
Plan * change_plan_targetlist(Plan *subplan, List *tlist, bool tlist_parallel_safe)
Definition: createplan.c:2147
bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno)
Definition: lsyscache.c:410
Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse)
Definition: lsyscache.c:267
Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type)
Definition: lsyscache.c:305
Index assignSortGroupRef(TargetEntry *tle, List *tlist)
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)
@ UNIQUE_PATH_SORT
Definition: pathnodes.h:2022
@ UNIQUE_PATH_NOOP
Definition: pathnodes.h:2020
@ UNIQUE_PATH_HASH
Definition: pathnodes.h:2021
Path * subpath
Definition: pathnodes.h:2028
List * uniq_exprs
Definition: pathnodes.h:2031
UniquePathMethod umethod
Definition: pathnodes.h:2029
List * in_operators
Definition: pathnodes.h:2030
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:79

References AGG_HASHED, AGGSPLIT_SIMPLE, Assert, assignSortGroupRef(), build_path_tlist(), change_plan_targetlist(), copy_generic_path_info(), create_plan_recurse(), elog, SortGroupClause::eqop, ERROR, TargetEntry::expr, exprCollation(), get_compatible_hash_operators(), get_equality_op_for_ordering_op(), get_ordering_op_for_equality_op(), get_tle_by_resno(), UniquePath::in_operators, label_sort_with_costsize(), lappend(), lfirst, lfirst_oid, list_length(), make_agg(), make_sort_from_sortclauses(), make_unique_from_sortclauses(), makeNode, makeTargetEntry(), NIL, SortGroupClause::nulls_first, OidIsValid, palloc(), Path::parallel_safe, UniquePath::path, plan, TargetEntry::resno, root, Path::rows, sort(), SortGroupClause::sortop, UniquePath::subpath, Plan::targetlist, SortGroupClause::tleSortGroupRef, tlist_member(), UniquePath::umethod, UniquePath::uniq_exprs, UNIQUE_PATH_HASH, UNIQUE_PATH_NOOP, and UNIQUE_PATH_SORT.

Referenced by create_plan_recurse().

◆ create_upper_unique_plan()

static Unique * create_upper_unique_plan ( PlannerInfo root,
UpperUniquePath best_path,
int  flags 
)
static

Definition at line 2275 of file createplan.c.

2276 {
2277  Unique *plan;
2278  Plan *subplan;
2279 
2280  /*
2281  * Unique doesn't project, so tlist requirements pass through; moreover we
2282  * need grouping columns to be labeled.
2283  */
2284  subplan = create_plan_recurse(root, best_path->subpath,
2285  flags | CP_LABEL_TLIST);
2286 
2287  plan = make_unique_from_pathkeys(subplan,
2288  best_path->path.pathkeys,
2289  best_path->numkeys);
2290 
2291  copy_generic_path_info(&plan->plan, (Path *) best_path);
2292 
2293  return plan;
2294 }
static Unique * make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols)
Definition: createplan.c:6743

References copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), make_unique_from_pathkeys(), UpperUniquePath::numkeys, UpperUniquePath::path, Path::pathkeys, plan, root, and UpperUniquePath::subpath.

Referenced by create_plan_recurse().

◆ create_valuesscan_plan()

static ValuesScan * create_valuesscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3841 of file createplan.c.

3843 {
3844  ValuesScan *scan_plan;
3845  Index scan_relid = best_path->parent->relid;
3846  RangeTblEntry *rte;
3847  List *values_lists;
3848 
3849  /* it should be a values base rel... */
3850  Assert(scan_relid > 0);
3851  rte = planner_rt_fetch(scan_relid, root);
3852  Assert(rte->rtekind == RTE_VALUES);
3853  values_lists = rte->values_lists;
3854 
3855  /* Sort clauses into best execution order */
3856  scan_clauses = order_qual_clauses(root, scan_clauses);
3857 
3858  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3859  scan_clauses = extract_actual_clauses(scan_clauses, false);
3860 
3861  /* Replace any outer-relation variables with nestloop params */
3862  if (best_path->param_info)
3863  {
3864  scan_clauses = (List *)
3865  replace_nestloop_params(root, (Node *) scan_clauses);
3866  /* The values lists could contain nestloop params, too */
3867  values_lists = (List *)
3868  replace_nestloop_params(root, (Node *) values_lists);
3869  }
3870 
3871  scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
3872  values_lists);
3873 
3874  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3875 
3876  return scan_plan;
3877 }
static ValuesScan * make_valuesscan(List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
Definition: createplan.c:5738
@ RTE_VALUES
Definition: parsenodes.h:1033
List * values_lists
Definition: parsenodes.h:1200
Scan scan
Definition: plannodes.h:622

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_valuesscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_VALUES, RangeTblEntry::rtekind, ValuesScan::scan, and RangeTblEntry::values_lists.

Referenced by create_scan_plan().

◆ create_windowagg_plan()

static WindowAgg * create_windowagg_plan ( PlannerInfo root,
WindowAggPath best_path 
)
static

Definition at line 2611 of file createplan.c.

2612 {
2613  WindowAgg *plan;
2614  WindowClause *wc = best_path->winclause;
2615  int numPart = list_length(wc->partitionClause);
2616  int numOrder = list_length(wc->orderClause);
2617  Plan *subplan;
2618  List *tlist;
2619  int partNumCols;
2620  AttrNumber *partColIdx;
2621  Oid *partOperators;
2622  Oid *partCollations;
2623  int ordNumCols;
2624  AttrNumber *ordColIdx;
2625  Oid *ordOperators;
2626  Oid *ordCollations;
2627  ListCell *lc;
2628 
2629  /*
2630  * Choice of tlist here is motivated by the fact that WindowAgg will be
2631  * storing the input rows of window frames in a tuplestore; it therefore
2632  * behooves us to request a small tlist to avoid wasting space. We do of
2633  * course need grouping columns to be available.
2634  */
2635  subplan = create_plan_recurse(root, best_path->subpath,
2637 
2638  tlist = build_path_tlist(root, &best_path->path);
2639 
2640  /*
2641  * Convert SortGroupClause lists into arrays of attr indexes and equality
2642  * operators, as wanted by executor.
2643  */
2644  partColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numPart);
2645  partOperators = (Oid *) palloc(sizeof(Oid) * numPart);
2646  partCollations = (Oid *) palloc(sizeof(Oid) * numPart);
2647 
2648  partNumCols = 0;
2649  foreach(lc, wc->partitionClause)
2650  {
2651  SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2652  TargetEntry *tle = get_sortgroupclause_tle(sgc, subplan->targetlist);
2653 
2654  Assert(OidIsValid(sgc->eqop));
2655  partColIdx[partNumCols] = tle->resno;
2656  partOperators[partNumCols] = sgc->eqop;
2657  partCollations[partNumCols] = exprCollation((Node *) tle->expr);
2658  partNumCols++;
2659  }
2660 
2661  ordColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numOrder);
2662  ordOperators = (Oid *) palloc(sizeof(Oid) * numOrder);
2663  ordCollations = (Oid *) palloc(sizeof(Oid) * numOrder);
2664 
2665  ordNumCols = 0;
2666  foreach(lc, wc->orderClause)
2667  {
2668  SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2669  TargetEntry *tle = get_sortgroupclause_tle(sgc, subplan->targetlist);
2670 
2671  Assert(OidIsValid(sgc->eqop));
2672  ordColIdx[ordNumCols] = tle->resno;
2673  ordOperators[ordNumCols] = sgc->eqop;
2674  ordCollations[ordNumCols] = exprCollation((Node *) tle->expr);
2675  ordNumCols++;
2676  }
2677 
2678  /* And finally we can make the WindowAgg node */
2679  plan = make_windowagg(tlist,
2680  wc->winref,
2681  partNumCols,
2682  partColIdx,
2683  partOperators,
2684  partCollations,
2685  ordNumCols,
2686  ordColIdx,
2687  ordOperators,
2688  ordCollations,
2689  wc->frameOptions,
2690  wc->startOffset,
2691  wc->endOffset,
2692  wc->startInRangeFunc,
2693  wc->endInRangeFunc,
2694  wc->inRangeColl,
2695  wc->inRangeAsc,
2696  wc->inRangeNullsFirst,
2697  best_path->runCondition,
2698  best_path->qual,
2699  best_path->topwindow,
2700  subplan);
2701 
2702  copy_generic_path_info(&plan->plan, (Path *) best_path);
2703 
2704  return plan;
2705 }
static WindowAgg * make_windowagg(List *tlist, Index winref, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, int frameOptions, Node *startOffset, Node *endOffset, Oid startInRangeFunc, Oid endInRangeFunc, Oid inRangeColl, bool inRangeAsc, bool inRangeNullsFirst, List *runCondition, List *qual, bool topWindow, Plan *lefttree)
Definition: createplan.c:6622
List * runCondition
Definition: pathnodes.h:2322
Path * subpath
Definition: pathnodes.h:2319
WindowClause * winclause
Definition: pathnodes.h:2320
Node * startOffset
Definition: parsenodes.h:1550
List * partitionClause
Definition: parsenodes.h:1546
Node * endOffset
Definition: parsenodes.h:1551
List * orderClause
Definition: parsenodes.h:1548

References Assert, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, CP_SMALL_TLIST, create_plan_recurse(), WindowClause::endOffset, SortGroupClause::eqop, TargetEntry::expr, exprCollation(), WindowClause::frameOptions, get_sortgroupclause_tle(), lfirst, list_length(), make_windowagg(), OidIsValid, WindowClause::orderClause, palloc(), WindowClause::partitionClause, WindowAggPath::path, plan, WindowAggPath::qual, TargetEntry::resno, root, WindowAggPath::runCondition, WindowClause::startOffset, WindowAggPath::subpath, Plan::targetlist, WindowAggPath::topwindow, WindowAggPath::winclause, and WindowClause::winref.

Referenced by create_plan_recurse().

◆ create_worktablescan_plan()

static WorkTableScan * create_worktablescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 4056 of file createplan.c.

4058 {
4059  WorkTableScan *scan_plan;
4060  Index scan_relid = best_path->parent->relid;
4061  RangeTblEntry *rte;
4062  Index levelsup;
4063  PlannerInfo *cteroot;
4064 
4065  Assert(scan_relid > 0);
4066  rte = planner_rt_fetch(scan_relid, root);
4067  Assert(rte->rtekind == RTE_CTE);
4068  Assert(rte->self_reference);
4069 
4070  /*
4071  * We need to find the worktable param ID, which is in the plan level
4072  * that's processing the recursive UNION, which is one level *below* where
4073  * the CTE comes from.
4074  */
4075  levelsup = rte->ctelevelsup;
4076  if (levelsup == 0) /* shouldn't happen */
4077  elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
4078  levelsup--;
4079  cteroot = root;
4080  while (levelsup-- > 0)
4081  {
4082  cteroot = cteroot->parent_root;
4083  if (!cteroot) /* shouldn't happen */
4084  elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
4085  }
4086  if (cteroot->wt_param_id < 0) /* shouldn't happen */
4087  elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
4088 
4089  /* Sort clauses into best execution order */
4090  scan_clauses = order_qual_clauses(root, scan_clauses);
4091 
4092  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
4093  scan_clauses = extract_actual_clauses(scan_clauses, false);
4094 
4095  /* Replace any outer-relation variables with nestloop params */
4096  if (best_path->param_info)
4097  {
4098  scan_clauses = (List *)
4099  replace_nestloop_params(root, (Node *) scan_clauses);
4100  }
4101 
4102  scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
4103  cteroot->wt_param_id);
4104 
4105  copy_generic_path_info(&scan_plan->scan.plan, best_path);
4106 
4107  return scan_plan;
4108 }
static WorkTableScan * make_worktablescan(List *qptlist, List *qpqual, Index scanrelid, int wtParam)
Definition: createplan.c:5798
int wt_param_id
Definition: pathnodes.h:530

References Assert, copy_generic_path_info(), RangeTblEntry::ctelevelsup, RangeTblEntry::ctename, elog, ERROR, extract_actual_clauses(), make_worktablescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, RTE_CTE, RangeTblEntry::rtekind, WorkTableScan::scan, and PlannerInfo::wt_param_id.

Referenced by create_scan_plan().

◆ fix_indexorderby_references()

static List * fix_indexorderby_references ( PlannerInfo root,
IndexPath index_path 
)
static

Definition at line 5058 of file createplan.c.

5059 {
5060  IndexOptInfo *index = index_path->indexinfo;
5061  List *fixed_indexorderbys;
5062  ListCell *lcc,
5063  *lci;
5064 
5065  fixed_indexorderbys = NIL;
5066 
5067  forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5068  {
5069  Node *clause = (Node *) lfirst(lcc);
5070  int indexcol = lfirst_int(lci);
5071 
5072  clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5073  fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5074  }
5075 
5076  return fixed_indexorderbys;
5077 }
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
Definition: createplan.c:5087
#define lfirst_int(lc)
Definition: pg_list.h:173
List * indexorderbycols
Definition: pathnodes.h:1713
Definition: type.h:95

References fix_indexqual_clause(), forboth, IndexPath::indexinfo, IndexPath::indexorderbycols, IndexPath::indexorderbys, lappend(), lfirst, lfirst_int, NIL, and root.

Referenced by create_indexscan_plan().

◆ fix_indexqual_clause()

static Node * fix_indexqual_clause ( PlannerInfo root,
IndexOptInfo index,
int  indexcol,
Node clause,
List indexcolnos 
)
static

Definition at line 5087 of file createplan.c.

5089 {
5090  /*
5091  * Replace any outer-relation variables with nestloop params.
5092  *
5093  * This also makes a copy of the clause, so it's safe to modify it
5094  * in-place below.
5095  */
5096  clause = replace_nestloop_params(root, clause);
5097 
5098  if (IsA(clause, OpExpr))
5099  {
5100  OpExpr *op = (OpExpr *) clause;
5101 
5102  /* Replace the indexkey expression with an index Var. */
5104  index,
5105  indexcol);
5106  }
5107  else if (IsA(clause, RowCompareExpr))
5108  {
5109  RowCompareExpr *rc = (RowCompareExpr *) clause;
5110  ListCell *lca,
5111  *lcai;
5112 
5113  /* Replace the indexkey expressions with index Vars. */
5114  Assert(list_length(rc->largs) == list_length(indexcolnos));
5115  forboth(lca, rc->largs, lcai, indexcolnos)
5116  {
5118  index,
5119  lfirst_int(lcai));
5120  }
5121  }
5122  else if (IsA(clause, ScalarArrayOpExpr))
5123  {
5124  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5125 
5126  /* Replace the indexkey expression with an index Var. */
5128  index,
5129  indexcol);
5130  }
5131  else if (IsA(clause, NullTest))
5132  {
5133  NullTest *nt = (NullTest *) clause;
5134 
5135  /* Replace the indexkey expression with an index Var. */
5136  nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5137  index,
5138  indexcol);
5139  }
5140  else
5141  elog(ERROR, "unsupported indexqual type: %d",
5142  (int) nodeTag(clause));
5143 
5144  return clause;
5145 }
static Node * fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
Definition: createplan.c:5158
Datum lca(PG_FUNCTION_ARGS)
Definition: ltree_op.c:570
Expr * arg
Definition: primnodes.h:1954

References NullTest::arg, OpExpr::args, ScalarArrayOpExpr::args, Assert, elog, ERROR, fix_indexqual_operand(), forboth, IsA, RowCompareExpr::largs, lca(), lfirst, lfirst_int, linitial, list_length(), nodeTag, replace_nestloop_params(), and root.

Referenced by fix_indexorderby_references(), and fix_indexqual_references().

◆ fix_indexqual_operand()

static Node * fix_indexqual_operand ( Node node,
IndexOptInfo index,
int  indexcol 
)
static

Definition at line 5158 of file createplan.c.

5159 {
5160  Var *result;
5161  int pos;
5162  ListCell *indexpr_item;
5163 
5164  /*
5165  * Remove any binary-compatible relabeling of the indexkey
5166  */
5167  if (IsA(node, RelabelType))
5168  node = (Node *) ((RelabelType *) node)->arg;
5169 
5170  Assert(indexcol >= 0 && indexcol < index->ncolumns);
5171 
5172  if (index->indexkeys[indexcol] != 0)
5173  {
5174  /* It's a simple index column */
5175  if (IsA(node, Var) &&
5176  ((Var *) node)->varno == index->rel->relid &&
5177  ((Var *) node)->varattno == index->indexkeys[indexcol])
5178  {
5179  result = (Var *) copyObject(node);
5180  result->varno = INDEX_VAR;
5181  result->varattno = indexcol + 1;
5182  return (Node *) result;
5183  }
5184  else
5185  elog(ERROR, "index key does not match expected index column");
5186  }
5187 
5188  /* It's an index expression, so find and cross-check the expression */
5189  indexpr_item = list_head(index->indexprs);
5190  for (pos = 0; pos < index->ncolumns; pos++)
5191  {
5192  if (index->indexkeys[pos] == 0)
5193  {
5194  if (indexpr_item == NULL)
5195  elog(ERROR, "too few entries in indexprs list");
5196  if (pos == indexcol)
5197  {
5198  Node *indexkey;
5199 
5200  indexkey = (Node *) lfirst(indexpr_item);
5201  if (indexkey && IsA(indexkey, RelabelType))
5202  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5203  if (equal(node, indexkey))
5204  {
5205  result = makeVar(INDEX_VAR, indexcol + 1,
5206  exprType(lfirst(indexpr_item)), -1,
5207  exprCollation(lfirst(indexpr_item)),
5208  0);
5209  return (Node *) result;
5210  }
5211  else
5212  elog(ERROR, "index key does not match expected index column");
5213  }
5214  indexpr_item = lnext(index->indexprs, indexpr_item);
5215  }
5216  }
5217 
5218  /* Oops... */
5219  elog(ERROR, "index key does not match expected index column");
5220  return NULL; /* keep compiler quiet */
5221 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
void * arg
#define INDEX_VAR
Definition: primnodes.h:238

References arg, Assert, copyObject, elog, equal(), ERROR, exprCollation(), exprType(), INDEX_VAR, IsA, lfirst, list_head(), lnext(), makeVar(), Var::varattno, and Var::varno.

Referenced by fix_indexqual_clause().

◆ fix_indexqual_references()

static void fix_indexqual_references ( PlannerInfo root,
IndexPath index_path,
List **  stripped_indexquals_p,
List **  fixed_indexquals_p 
)
static

Definition at line 5017 of file createplan.c.

5019 {
5020  IndexOptInfo *index = index_path->indexinfo;
5021  List *stripped_indexquals;
5022  List *fixed_indexquals;
5023  ListCell *lc;
5024 
5025  stripped_indexquals = fixed_indexquals = NIL;
5026 
5027  foreach(lc, index_path->indexclauses)
5028  {
5029  IndexClause *iclause = lfirst_node(IndexClause, lc);
5030  int indexcol = iclause->indexcol;
5031  ListCell *lc2;
5032 
5033  foreach(lc2, iclause->indexquals)
5034  {
5035  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
5036  Node *clause = (Node *) rinfo->clause;
5037 
5038  stripped_indexquals = lappend(stripped_indexquals, clause);
5039  clause = fix_indexqual_clause(root, index, indexcol,
5040  clause, iclause->indexcols);
5041  fixed_indexquals = lappend(fixed_indexquals, clause);
5042  }
5043  }
5044 
5045  *stripped_indexquals_p = stripped_indexquals;
5046  *fixed_indexquals_p = fixed_indexquals;
5047 }
AttrNumber indexcol
Definition: pathnodes.h:1761
List * indexcols
Definition: pathnodes.h:1762

References RestrictInfo::clause, fix_indexqual_clause(), IndexPath::indexclauses, IndexClause::indexcol, IndexClause::indexcols, IndexPath::indexinfo, IndexClause::indexquals, lappend(), lfirst_node, NIL, and root.

Referenced by create_indexscan_plan().

◆ get_gating_quals()

static List * get_gating_quals ( PlannerInfo root,
List quals 
)
static

Definition at line 1002 of file createplan.c.

1003 {
1004  /* No need to look if we know there are no pseudoconstants */
1005  if (!root->hasPseudoConstantQuals)
1006  return NIL;
1007 
1008  /* Sort into desirable execution order while still in RestrictInfo form */
1009  quals = order_qual_clauses(root, quals);
1010 
1011  /* Pull out any pseudoconstant quals from the RestrictInfo list */
1012  return extract_actual_clauses(quals, true);
1013 }

References extract_actual_clauses(), NIL, order_qual_clauses(), and root.

Referenced by create_join_plan(), and create_scan_plan().

◆ get_switched_clauses()

static List * get_switched_clauses ( List clauses,
Relids  outerrelids 
)
static

Definition at line 5233 of file createplan.c.

5234 {
5235  List *t_list = NIL;
5236  ListCell *l;
5237 
5238  foreach(l, clauses)
5239  {
5240  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
5241  OpExpr *clause = (OpExpr *) restrictinfo->clause;
5242 
5243  Assert(is_opclause(clause));
5244  if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5245  {
5246  /*
5247  * Duplicate just enough of the structure to allow commuting the
5248  * clause without changing the original list. Could use
5249  * copyObject, but a complete deep copy is overkill.
5250  */
5251  OpExpr *temp = makeNode(OpExpr);
5252 
5253  temp->opno = clause->opno;
5254  temp->opfuncid = InvalidOid;
5255  temp->opresulttype = clause->opresulttype;
5256  temp->opretset = clause->opretset;
5257  temp->opcollid = clause->opcollid;
5258  temp->inputcollid = clause->inputcollid;
5259  temp->args = list_copy(clause->args);
5260  temp->location = clause->location;
5261  /* Commute it --- note this modifies the temp node in-place. */
5262  CommuteOpExpr(temp);
5263  t_list = lappend(t_list, temp);
5264  restrictinfo->outer_is_left = false;
5265  }
5266  else
5267  {
5268  Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5269  t_list = lappend(t_list, clause);
5270  restrictinfo->outer_is_left = true;
5271  }
5272  }
5273  return t_list;
5274 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
void CommuteOpExpr(OpExpr *clause)
Definition: clauses.c:2147
List * list_copy(const List *oldlist)
Definition: list.c:1573
ParseLoc location
Definition: primnodes.h:839

References OpExpr::args, Assert, bms_is_subset(), RestrictInfo::clause, CommuteOpExpr(), InvalidOid, is_opclause(), lappend(), lfirst, list_copy(), OpExpr::location, makeNode, NIL, and OpExpr::opno.

Referenced by create_hashjoin_plan(), and create_mergejoin_plan().

◆ inject_projection_plan()

static Plan * inject_projection_plan ( Plan subplan,
List tlist,
bool  parallel_safe 
)
static

Definition at line 2115 of file createplan.c.

2116 {
2117  Plan *plan;
2118 
2119  plan = (Plan *) make_result(tlist, NULL, subplan);
2120 
2121  /*
2122  * In principle, we should charge tlist eval cost plus cpu_per_tuple per
2123  * row for the Result node. But the former has probably been factored in
2124  * already and the latter was not accounted for during Path construction,
2125  * so being formally correct might just make the EXPLAIN output look less
2126  * consistent not more so. Hence, just copy the subplan's cost.
2127  */
2128  copy_plan_costsize(plan, subplan);
2129  plan->parallel_safe = parallel_safe;
2130 
2131  return plan;
2132 }

References copy_plan_costsize(), make_result(), and plan.

Referenced by change_plan_targetlist(), create_append_plan(), create_merge_append_plan(), and prepare_sort_from_pathkeys().

◆ is_projection_capable_path()

bool is_projection_capable_path ( Path path)

Definition at line 7202 of file createplan.c.

7203 {
7204  /* Most plan types can project, so just list the ones that can't */
7205  switch (path->pathtype)
7206  {
7207  case T_Hash:
7208  case T_Material:
7209  case T_Memoize:
7210  case T_Sort:
7211  case T_IncrementalSort:
7212  case T_Unique:
7213  case T_SetOp:
7214  case T_LockRows:
7215  case T_Limit:
7216  case T_ModifyTable:
7217  case T_MergeAppend:
7218  case T_RecursiveUnion:
7219  return false;
7220  case T_CustomScan:
7222  return true;
7223  return false;
7224  case T_Append:
7225 
7226  /*
7227  * Append can't project, but if an AppendPath is being used to
7228  * represent a dummy path, what will actually be generated is a
7229  * Result which can project.
7230  */
7231  return IS_DUMMY_APPEND(path);
7232  case T_ProjectSet:
7233 
7234  /*
7235  * Although ProjectSet certainly projects, say "no" because we
7236  * don't want the planner to randomly replace its tlist with
7237  * something else; the SRFs have to stay at top level. This might
7238  * get relaxed later.
7239  */
7240  return false;
7241  default:
7242  break;
7243  }
7244  return true;
7245 }
#define CUSTOMPATH_SUPPORT_PROJECTION
Definition: extensible.h:86
#define IS_DUMMY_APPEND(p)
Definition: pathnodes.h:1938

References castNode, CUSTOMPATH_SUPPORT_PROJECTION, IS_DUMMY_APPEND, and Path::pathtype.

Referenced by add_paths_with_pathkeys_for_rel(), apply_projection_to_path(), create_projection_path(), and create_projection_plan().

◆ is_projection_capable_plan()

bool is_projection_capable_plan ( Plan plan)

Definition at line 7252 of file createplan.c.

7253 {
7254  /* Most plan types can project, so just list the ones that can't */
7255  switch (nodeTag(plan))
7256  {
7257  case T_Hash:
7258  case T_Material:
7259  case T_Memoize:
7260  case T_Sort:
7261  case T_Unique:
7262  case T_SetOp:
7263  case T_LockRows:
7264  case T_Limit:
7265  case T_ModifyTable:
7266  case T_Append:
7267  case T_MergeAppend:
7268  case T_RecursiveUnion:
7269  return false;
7270  case T_CustomScan:
7271  if (((CustomScan *) plan)->flags & CUSTOMPATH_SUPPORT_PROJECTION)
7272  return true;
7273  return false;
7274  case T_ProjectSet:
7275 
7276  /*
7277  * Although ProjectSet certainly projects, say "no" because we
7278  * don't want the planner to randomly replace its tlist with
7279  * something else; the SRFs have to stay at top level. This might
7280  * get relaxed later.
7281  */
7282  return false;
7283  default:
7284  break;
7285  }
7286  return true;
7287 }

References CUSTOMPATH_SUPPORT_PROJECTION, nodeTag, and plan.

Referenced by change_plan_targetlist(), create_projection_plan(), and prepare_sort_from_pathkeys().

◆ label_sort_with_costsize()

static void label_sort_with_costsize ( PlannerInfo root,
Sort plan,
double  limit_tuples 
)
static

Definition at line 5441 of file createplan.c.

5442 {
5443  Plan *lefttree = plan->plan.lefttree;
5444  Path sort_path; /* dummy for result of cost_sort */
5445 
5446  /*
5447  * This function shouldn't have to deal with IncrementalSort plans because
5448  * they are only created from corresponding Path nodes.
5449  */
5450  Assert(IsA(plan, Sort));
5451 
5452  cost_sort(&sort_path, root, NIL,
5453  lefttree->total_cost,
5454  lefttree->plan_rows,
5455  lefttree->plan_width,
5456  0.0,
5457  work_mem,
5458  limit_tuples);
5459  plan->plan.startup_cost = sort_path.startup_cost;
5460  plan->plan.total_cost = sort_path.total_cost;
5461  plan->plan.plan_rows = lefttree->plan_rows;
5462  plan->plan.plan_width = lefttree->plan_width;
5463  plan->plan.parallel_aware = false;
5464  plan->plan.parallel_safe = lefttree->parallel_safe;
5465 }
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2103
int work_mem
Definition: globals.c:129

References Assert, cost_sort(), IsA, NIL, Plan::parallel_safe, plan, Plan::plan_rows, Plan::plan_width, root, Path::startup_cost, Path::total_cost, Plan::total_cost, and work_mem.

Referenced by create_append_plan(), create_merge_append_plan(), create_mergejoin_plan(), and create_unique_plan().

◆ make_agg()

Agg* make_agg ( List tlist,
List qual,
AggStrategy  aggstrategy,
AggSplit  aggsplit,
int  numGroupCols,
AttrNumber grpColIdx,
Oid grpOperators,
Oid grpCollations,
List groupingSets,
List chain,
double  dNumGroups,
Size  transitionSpace,
Plan lefttree 
)

Definition at line 6588 of file createplan.c.

6593 {
6594  Agg *node = makeNode(Agg);
6595  Plan *plan = &node->plan;
6596  long numGroups;
6597 
6598  /* Reduce to long, but 'ware overflow! */
6599  numGroups = clamp_cardinality_to_long(dNumGroups);
6600 
6601  node->aggstrategy = aggstrategy;
6602  node->aggsplit = aggsplit;
6603  node->numCols = numGroupCols;
6604  node->grpColIdx = grpColIdx;
6605  node->grpOperators = grpOperators;
6606  node->grpCollations = grpCollations;
6607  node->numGroups = numGroups;
6608  node->transitionSpace = transitionSpace;
6609  node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6610  node->groupingSets = groupingSets;
6611  node->chain = chain;
6612 
6613  plan->qual = qual;
6614  plan->targetlist = tlist;
6615  plan->lefttree = lefttree;
6616  plan->righttree = NULL;
6617 
6618  return node;
6619 }
AggSplit aggsplit
Definition: plannodes.h:1004
List * chain
Definition: plannodes.h:1031
long numGroups
Definition: plannodes.h:1017
List * groupingSets
Definition: plannodes.h:1028
Bitmapset * aggParams
Definition: plannodes.h:1023
Plan plan
Definition: plannodes.h:998
int numCols
Definition: plannodes.h:1007
uint64 transitionSpace
Definition: plannodes.h:1020
AggStrategy aggstrategy
Definition: plannodes.h:1001

References Agg::aggParams, Agg::aggsplit, Agg::aggstrategy, Agg::chain, clamp_cardinality_to_long(), Agg::groupingSets, makeNode, Agg::numCols, Agg::numGroups, Agg::plan, plan, and Agg::transitionSpace.

Referenced by create_agg_plan(), create_groupingsets_plan(), and create_unique_plan().

◆ make_bitmap_and()

static BitmapAnd * make_bitmap_and ( List bitmapplans)
static

Definition at line 5913 of file createplan.c.

5914 {
5915  BitmapAnd *node = makeNode(BitmapAnd);
5916  Plan *plan = &node->plan;
5917 
5918  plan->targetlist = NIL;
5919  plan->qual = NIL;
5920  plan->lefttree = NULL;
5921  plan->righttree = NULL;
5922  node->bitmapplans = bitmapplans;
5923 
5924  return node;
5925 }
Plan plan
Definition: plannodes.h:358
List * bitmapplans
Definition: plannodes.h:359

References BitmapAnd::bitmapplans, makeNode, NIL, BitmapAnd::plan, and plan.

Referenced by create_bitmap_subplan().

◆ make_bitmap_heapscan()

static BitmapHeapScan * make_bitmap_heapscan ( List qptlist,
List qpqual,
Plan lefttree,
List bitmapqualorig,
Index  scanrelid 
)
static

Definition at line 5620 of file createplan.c.

5625 {
5627  Plan *plan = &node->scan.plan;
5628 
5629  plan->targetlist = qptlist;
5630  plan->qual = qpqual;
5631  plan->lefttree = lefttree;
5632  plan->righttree = NULL;
5633  node->scan.scanrelid = scanrelid;
5634  node->bitmapqualorig = bitmapqualorig;
5635 
5636  return node;
5637 }
List * bitmapqualorig
Definition: plannodes.h:541

References BitmapHeapScan::bitmapqualorig, makeNode, plan, BitmapHeapScan::scan, and Scan::scanrelid.

Referenced by create_bitmap_scan_plan().

◆ make_bitmap_indexscan()

static BitmapIndexScan * make_bitmap_indexscan ( Index  scanrelid,
Oid  indexid,
List indexqual,
List indexqualorig 
)
static

Definition at line 5599 of file createplan.c.

5603 {
5605  Plan *plan = &node->scan.plan;
5606 
5607  plan->targetlist = NIL; /* not used */
5608  plan->qual = NIL; /* not used */
5609  plan->lefttree = NULL;
5610  plan->righttree = NULL;
5611  node->scan.scanrelid = scanrelid;
5612  node->indexid = indexid;
5613  node->indexqual = indexqual;
5614  node->indexqualorig = indexqualorig;
5615 
5616  return node;
5617 }
List * indexqualorig
Definition: plannodes.h:526
List * indexqual
Definition: plannodes.h:525

References BitmapIndexScan::indexid, BitmapIndexScan::indexqual, BitmapIndexScan::indexqualorig, makeNode, NIL, plan, BitmapIndexScan::scan, and Scan::scanrelid.

Referenced by create_bitmap_subplan().

◆ make_bitmap_or()

static BitmapOr * make_bitmap_or ( List bitmapplans)
static

Definition at line 5928 of file createplan.c.

5929 {
5930  BitmapOr *node = makeNode(BitmapOr);
5931  Plan *plan = &node->plan;
5932 
5933  plan->targetlist = NIL;
5934  plan->qual = NIL;
5935  plan->lefttree = NULL;
5936  plan->righttree = NULL;
5937  node->bitmapplans = bitmapplans;
5938 
5939  return node;
5940 }
List * bitmapplans
Definition: plannodes.h:374
Plan plan
Definition: plannodes.h:372

References BitmapOr::bitmapplans, makeNode, NIL, BitmapOr::plan, and plan.

Referenced by create_bitmap_subplan().

◆ make_ctescan()

static CteScan * make_ctescan ( List qptlist,
List qpqual,
Index  scanrelid,
int  ctePlanId,
int  cteParam 
)
static

Definition at line 5757 of file createplan.c.

5762 {
5763  CteScan *node = makeNode(CteScan);
5764  Plan *plan = &node->scan.plan;
5765 
5766  plan->targetlist = qptlist;
5767  plan->qual = qpqual;
5768  plan->lefttree = NULL;
5769  plan->righttree = NULL;
5770  node->scan.scanrelid = scanrelid;
5771  node->ctePlanId = ctePlanId;
5772  node->cteParam = cteParam;
5773 
5774  return node;
5775 }
int ctePlanId
Definition: plannodes.h:643
int cteParam
Definition: plannodes.h:644

References CteScan::cteParam, CteScan::ctePlanId, makeNode, plan, CteScan::scan, and Scan::scanrelid.

Referenced by create_ctescan_plan().

◆ make_foreignscan()

ForeignScan* make_foreignscan ( List qptlist,
List qpqual,
Index  scanrelid,
List fdw_exprs,
List fdw_private,
List fdw_scan_tlist,
List fdw_recheck_quals,
Plan outer_plan 
)

Definition at line 5817 of file createplan.c.

5825 {
5826  ForeignScan *node = makeNode(ForeignScan);
5827  Plan *plan = &node->scan.plan;
5828 
5829  /* cost will be filled in by create_foreignscan_plan */
5830  plan->targetlist = qptlist;
5831  plan->qual = qpqual;
5832  plan->lefttree = outer_plan;
5833  plan->righttree = NULL;
5834  node->scan.scanrelid = scanrelid;
5835 
5836  /* these may be overridden by the FDW's PlanDirectModify callback. */
5837  node->operation = CMD_SELECT;
5838  node->resultRelation = 0;
5839 
5840  /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5841  node->checkAsUser = InvalidOid;
5842  node->fs_server = InvalidOid;
5843  node->fdw_exprs = fdw_exprs;
5844  node->fdw_private = fdw_private;
5845  node->fdw_scan_tlist = fdw_scan_tlist;
5846  node->fdw_recheck_quals = fdw_recheck_quals;
5847  /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5848  node->fs_relids = NULL;
5849  node->fs_base_relids = NULL;
5850  /* fsSystemCol will be filled in by create_foreignscan_plan */
5851  node->fsSystemCol = false;
5852 
5853  return node;
5854 }
@ CMD_SELECT
Definition: nodes.h:265
CmdType operation
Definition: plannodes.h:710
List * fdw_private
Definition: plannodes.h:716
Index resultRelation
Definition: plannodes.h:711
List * fdw_scan_tlist
Definition: plannodes.h:717

References ForeignScan::checkAsUser, CMD_SELECT, ForeignScan::fdw_exprs, ForeignScan::fdw_private, ForeignScan::fdw_recheck_quals, ForeignScan::fdw_scan_tlist, ForeignScan::fs_base_relids, ForeignScan::fs_relids, ForeignScan::fs_server, ForeignScan::fsSystemCol, InvalidOid, makeNode, ForeignScan::operation, plan, ForeignScan::resultRelation, ForeignScan::scan, and Scan::scanrelid.

Referenced by fileGetForeignPlan(), and postgresGetForeignPlan().

◆ make_functionscan()

static FunctionScan * make_functionscan ( List qptlist,
List qpqual,
Index  scanrelid,
List functions,
bool  funcordinality 
)
static

Definition at line 5698 of file createplan.c.

5703 {
5705  Plan *plan = &node->scan.plan;
5706 
5707  plan->targetlist = qptlist;
5708  plan->qual = qpqual;
5709  plan->lefttree = NULL;
5710  plan->righttree = NULL;
5711  node->scan.scanrelid = scanrelid;
5712  node->functions = functions;
5713  node->funcordinality = funcordinality;
5714 
5715  return node;
5716 }
List * functions
Definition: plannodes.h:612
bool funcordinality
Definition: plannodes.h:613

References FunctionScan::funcordinality, functions, FunctionScan::functions, makeNode, plan, FunctionScan::scan, and Scan::scanrelid.

Referenced by create_functionscan_plan().

◆ make_gather()

static Gather * make_gather ( List qptlist,
List qpqual,
int  nworkers,
int  rescan_param,
bool  single_copy,
Plan subplan 
)
static

Definition at line 6849 of file createplan.c.

6855 {
6856  Gather *node = makeNode(Gather);
6857  Plan *plan = &node->plan;
6858 
6859  plan->targetlist = qptlist;
6860  plan->qual = qpqual;
6861  plan->lefttree = subplan;
6862  plan->righttree = NULL;
6863  node->num_workers = nworkers;
6864  node->rescan_param = rescan_param;
6865  node->single_copy = single_copy;
6866  node->invisible = false;
6867  node->initParam = NULL;
6868 
6869  return node;
6870 }
int num_workers
Definition: plannodes.h:1143
bool invisible
Definition: plannodes.h:1146
Bitmapset * initParam
Definition: plannodes.h:1147
bool single_copy
Definition: plannodes.h:1145
int rescan_param
Definition: plannodes.h:1144

References Gather::initParam, Gather::invisible, makeNode, Gather::num_workers, Gather::plan, plan, Gather::rescan_param, and Gather::single_copy.

Referenced by create_gather_plan().

◆ make_group()

static Group * make_group ( List tlist,
List qual,
int  numGroupCols,
AttrNumber grpColIdx,
Oid grpOperators,
Oid grpCollations,
Plan lefttree 
)
static

Definition at line 6664 of file createplan.c.

6671 {
6672  Group *node = makeNode(Group);
6673  Plan *plan = &node->plan;
6674 
6675  node->numCols = numGroupCols;
6676  node->grpColIdx = grpColIdx;
6677  node->grpOperators = grpOperators;
6678  node->grpCollations = grpCollations;
6679 
6680  plan->qual = qual;
6681  plan->targetlist = tlist;
6682  plan->lefttree = lefttree;
6683  plan->righttree = NULL;
6684 
6685  return node;
6686 }
int numCols
Definition: plannodes.h:972
Plan plan
Definition: plannodes.h:969

References makeNode, Group::numCols, Group::plan, and plan.

Referenced by create_group_plan().

◆ make_hash()

static Hash * make_hash ( Plan lefttree,
List hashkeys,
Oid  skewTable,
AttrNumber  skewColumn,
bool  skewInherit 
)
static

Definition at line 5999 of file createplan.c.

6004 {
6005  Hash *node = makeNode(Hash);
6006  Plan *plan = &node->plan;
6007 
6008  plan->targetlist = lefttree->targetlist;
6009  plan->qual = NIL;
6010  plan->lefttree = lefttree;
6011  plan->righttree = NULL;
6012 
6013  node->hashkeys = hashkeys;
6014  node->skewTable = skewTable;
6015  node->skewColumn = skewColumn;
6016  node->skewInherit = skewInherit;
6017 
6018  return node;
6019 }
AttrNumber skewColumn
Definition: plannodes.h:1207
List * hashkeys
Definition: plannodes.h:1205
Oid skewTable
Definition: plannodes.h:1206
bool skewInherit
Definition: plannodes.h:1208

References Hash::hashkeys, makeNode, NIL, Hash::plan, plan, Hash::skewColumn, Hash::skewInherit, Hash::skewTable, and Plan::targetlist.

Referenced by create_hashjoin_plan().

◆ make_hashjoin()

static HashJoin * make_hashjoin ( List tlist,
List joinclauses,
List otherclauses,
List hashclauses,
List hashoperators,
List hashcollations,
List hashkeys,
Plan lefttree,
Plan righttree,
JoinType  jointype,
bool  inner_unique 
)
static

Definition at line 5968 of file createplan.c.

5979 {
5980  HashJoin *node = makeNode(HashJoin);
5981  Plan *plan = &node->join.plan;
5982 
5983  plan->targetlist = tlist;
5984  plan->qual = otherclauses;
5985  plan->lefttree = lefttree;
5986  plan->righttree = righttree;
5987  node->hashclauses = hashclauses;
5988  node->hashoperators = hashoperators;
5989  node->hashcollations = hashcollations;
5990  node->hashkeys = hashkeys;
5991  node->join.jointype = jointype;
5992  node->join.inner_unique = inner_unique;
5993  node->join.joinqual = joinclauses;
5994 
5995  return node;
5996 }
List * hashcollations
Definition: plannodes.h:867
List * hashclauses
Definition: plannodes.h:865
List * hashoperators
Definition: plannodes.h:866
List * hashkeys
Definition: plannodes.h:873
List * joinqual
Definition: plannodes.h:793
JoinType jointype
Definition: plannodes.h:791
bool inner_unique
Definition: plannodes.h:792

References HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, Join::inner_unique, HashJoin::join, Join::joinqual, Join::jointype, makeNode, and plan.

Referenced by create_hashjoin_plan().

◆ make_incrementalsort()

static IncrementalSort * make_incrementalsort ( Plan lefttree,
int  numCols,
int  nPresortedCols,
AttrNumber sortColIdx,
Oid sortOperators,
Oid collations,
bool nullsFirst 
)
static

Definition at line 6093 of file createplan.c.

6096 {
6097  IncrementalSort *node;
6098  Plan *plan;
6099 
6100  node = makeNode(IncrementalSort);
6101 
6102  plan = &node->sort.plan;
6103  plan->targetlist = lefttree->targetlist;
6104  plan->qual = NIL;
6105  plan->lefttree = lefttree;
6106  plan->righttree = NULL;
6107  node->nPresortedCols = nPresortedCols;
6108  node->sort.numCols = numCols;
6109  node->sort.sortColIdx = sortColIdx;
6110  node->sort.sortOperators = sortOperators;
6111  node->sort.collations = collations;
6112  node->sort.nullsFirst = nullsFirst;
6113 
6114  return node;
6115 }
int numCols
Definition: plannodes.h:936
Plan plan
Definition: plannodes.h:933

References makeNode, NIL, IncrementalSort::nPresortedCols, Sort::numCols, Sort::plan, plan, IncrementalSort::sort, and Plan::targetlist.

Referenced by make_incrementalsort_from_pathkeys().

◆ make_incrementalsort_from_pathkeys()

static IncrementalSort * make_incrementalsort_from_pathkeys ( Plan lefttree,
List pathkeys,
Relids  relids,
int  nPresortedCols 
)
static

Definition at line 6376 of file createplan.c.

6378 {
6379  int numsortkeys;
6380  AttrNumber *sortColIdx;
6381  Oid *sortOperators;
6382  Oid *collations;
6383  bool *nullsFirst;
6384 
6385  /* Compute sort column info, and adjust lefttree as needed */
6386  lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6387  relids,
6388  NULL,
6389  false,
6390  &numsortkeys,
6391  &sortColIdx,
6392  &sortOperators,
6393  &collations,
6394  &nullsFirst);
6395 
6396  /* Now build the Sort node */
6397  return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6398  sortColIdx, sortOperators,
6399  collations, nullsFirst);
6400 }
static IncrementalSort * make_incrementalsort(Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:6093

References make_incrementalsort(), and prepare_sort_from_pathkeys().

Referenced by create_incrementalsort_plan().

◆ make_indexonlyscan()

static IndexOnlyScan * make_indexonlyscan ( List qptlist,
List qpqual,
Index  scanrelid,
Oid  indexid,
List indexqual,
List recheckqual,
List indexorderby,
List indextlist,
ScanDirection  indexscandir 
)
static

Definition at line 5570 of file createplan.c.

5579 {
5581  Plan *plan = &node->scan.plan;
5582 
5583  plan->targetlist = qptlist;
5584  plan->qual = qpqual;
5585  plan->lefttree = NULL;
5586  plan->righttree = NULL;
5587  node->scan.scanrelid = scanrelid;
5588  node->indexid = indexid;
5589  node->indexqual = indexqual;
5590  node->recheckqual = recheckqual;
5591  node->indexorderby = indexorderby;
5592  node->indextlist = indextlist;
5593  node->indexorderdir = indexscandir;
5594 
5595  return node;
5596 }
List * indexqual
Definition: plannodes.h:496
List * recheckqual
Definition: plannodes.h:497
List * indextlist
Definition: plannodes.h:499
ScanDirection indexorderdir
Definition: plannodes.h:500
List * indexorderby
Definition: plannodes.h:498

References IndexOnlyScan::indexid, IndexOnlyScan::indexorderby, IndexOnlyScan::indexorderdir, IndexOnlyScan::indexqual, IndexOnlyScan::indextlist, makeNode, plan, IndexOnlyScan::recheckqual, IndexOnlyScan::scan, and Scan::scanrelid.

Referenced by create_indexscan_plan().

◆ make_indexscan()

static IndexScan * make_indexscan ( List qptlist,
List qpqual,
Index  scanrelid,
Oid  indexid,
List indexqual,
List indexqualorig,
List indexorderby,
List indexorderbyorig,
List indexorderbyops,
ScanDirection  indexscandir 
)
static

Definition at line 5539 of file createplan.c.

5549 {
5550  IndexScan *node = makeNode(IndexScan);
5551  Plan *plan = &node->scan.plan;
5552 
5553  plan->targetlist = qptlist;
5554  plan->qual = qpqual;
5555  plan->lefttree = NULL;
5556  plan->righttree = NULL;
5557  node->scan.scanrelid = scanrelid;
5558  node->indexid = indexid;
5559  node->indexqual = indexqual;
5560  node->indexqualorig = indexqualorig;
5561  node->indexorderby = indexorderby;
5562  node->indexorderbyorig = indexorderbyorig;
5563  node->indexorderbyops = indexorderbyops;
5564  node->indexorderdir = indexscandir;
5565 
5566  return node;
5567 }
List * indexorderby
Definition: plannodes.h:455
List * indexorderbyops
Definition: plannodes.h:457
ScanDirection indexorderdir
Definition: plannodes.h:458
List * indexorderbyorig
Definition: plannodes.h:456

References IndexScan::indexid, IndexScan::indexorderby, IndexScan::indexorderbyops, IndexScan::indexorderbyorig, IndexScan::indexorderdir, IndexScan::indexqual, IndexScan::indexqualorig, makeNode, plan, IndexScan::scan, and Scan::scanrelid.

Referenced by create_indexscan_plan().

◆ make_limit()

Limit* make_limit ( Plan lefttree,
Node limitOffset,
Node limitCount,
LimitOption  limitOption,
int  uniqNumCols,
AttrNumber uniqColIdx,
Oid uniqOperators,
Oid uniqCollations 
)

Definition at line 6955 of file createplan.c.

6958 {
6959  Limit *node = makeNode(Limit);
6960  Plan *plan = &node->plan;
6961 
6962  plan->targetlist = lefttree->targetlist;
6963  plan->qual = NIL;
6964  plan->lefttree = lefttree;
6965  plan->righttree = NULL;
6966 
6967  node->limitOffset = limitOffset;
6968  node->limitCount = limitCount;
6969  node->limitOption = limitOption;
6970  node->uniqNumCols = uniqNumCols;
6971  node->uniqColIdx = uniqColIdx;
6972  node->uniqOperators = uniqOperators;
6973  node->uniqCollations = uniqCollations;
6974 
6975  return node;
6976 }
LimitOption limitOption
Definition: plannodes.h:1281
Plan plan
Definition: plannodes.h:1272
Node * limitCount
Definition: plannodes.h:1278
int uniqNumCols
Definition: plannodes.h:1284
Node * limitOffset
Definition: plannodes.h:1275

References Limit::limitCount, Limit::limitOffset, Limit::limitOption, makeNode, NIL, Limit::plan, plan, Plan::targetlist, and Limit::uniqNumCols.

Referenced by create_limit_plan(), and create_minmaxagg_plan().

◆ make_lockrows()

static LockRows * make_lockrows ( Plan lefttree,
List rowMarks,
int  epqParam 
)
static

Definition at line 6934 of file createplan.c.

6935 {
6936  LockRows *node = makeNode(LockRows);
6937  Plan *plan = &node->plan;
6938 
6939  plan->targetlist = lefttree->targetlist;
6940  plan->qual = NIL;
6941  plan->lefttree = lefttree;
6942  plan->righttree = NULL;
6943 
6944  node->rowMarks = rowMarks;
6945  node->epqParam = epqParam;
6946 
6947  return node;
6948 }
int epqParam
Definition: plannodes.h:1260
List * rowMarks
Definition: plannodes.h:1259
Plan plan
Definition: plannodes.h:1258

References LockRows::epqParam, makeNode, NIL, LockRows::plan, plan, LockRows::rowMarks, and Plan::targetlist.

Referenced by create_lockrows_plan().

◆ make_material()

static Material * make_material ( Plan lefttree)
static

Definition at line 6500 of file createplan.c.

6501 {
6502  Material *node = makeNode(Material);
6503  Plan *plan = &node->plan;
6504 
6505  plan->targetlist = lefttree->targetlist;
6506  plan->qual = NIL;
6507  plan->lefttree = lefttree;
6508  plan->righttree = NULL;
6509 
6510  return node;
6511 }
Plan plan
Definition: plannodes.h:882

References makeNode, NIL, Material::plan, plan, and Plan::targetlist.

Referenced by create_material_plan(), create_mergejoin_plan(), and materialize_finished_plan().

◆ make_memoize()

static Memoize * make_memoize ( Plan lefttree,
Oid hashoperators,
Oid collations,
List param_exprs,
bool  singlerow,
bool  binary_mode,
uint32  est_entries,
Bitmapset keyparamids 
)
static

Definition at line 6563 of file createplan.c.

6566 {
6567  Memoize *node = makeNode(Memoize);
6568  Plan *plan = &node->plan;
6569 
6570  plan->targetlist = lefttree->targetlist;
6571  plan->qual = NIL;
6572  plan->lefttree = lefttree;
6573  plan->righttree = NULL;
6574 
6575  node->numKeys = list_length(param_exprs);
6576  node->hashOperators = hashoperators;
6577  node->collations = collations;
6578  node->param_exprs = param_exprs;
6579  node->singlerow = singlerow;
6580  node->binary_mode = binary_mode;
6581  node->est_entries = est_entries;
6582  node->keyparamids = keyparamids;
6583 
6584  return node;
6585 }
Plan plan
Definition: plannodes.h:891
bool singlerow
Definition: plannodes.h:909
Bitmapset * keyparamids
Definition: plannodes.h:924
bool binary_mode
Definition: plannodes.h:915
int numKeys
Definition: plannodes.h:894
List * param_exprs
Definition: plannodes.h:903
uint32 est_entries
Definition: plannodes.h:921

References Memoize::binary_mode, Memoize::est_entries, Memoize::keyparamids, list_length(), makeNode, NIL, Memoize::numKeys, Memoize::param_exprs, Memoize::plan, plan, Memoize::singlerow, and Plan::targetlist.

Referenced by create_memoize_plan().

◆ make_mergejoin()

static MergeJoin * make_mergejoin ( List tlist,
List joinclauses,
List otherclauses,
List mergeclauses,
Oid mergefamilies,
Oid mergecollations,
int *  mergestrategies,
bool mergenullsfirst,
Plan lefttree,
Plan righttree,
JoinType  jointype,
bool  inner_unique,
bool  skip_mark_restore 
)
static

Definition at line 6022 of file createplan.c.

6035 {
6036  MergeJoin *node = makeNode(MergeJoin);
6037  Plan *plan = &node->join.plan;
6038 
6039  plan->targetlist = tlist;
6040  plan->qual = otherclauses;
6041  plan->lefttree = lefttree;
6042  plan->righttree = righttree;
6043  node->skip_mark_restore = skip_mark_restore;
6044  node->mergeclauses = mergeclauses;
6045  node->mergeFamilies = mergefamilies;
6046  node->mergeCollations = mergecollations;
6047  node->mergeStrategies = mergestrategies;
6048  node->mergeNullsFirst = mergenullsfirst;
6049  node->join.jointype = jointype;
6050  node->join.inner_unique = inner_unique;
6051  node->join.joinqual = joinclauses;
6052 
6053  return node;
6054 }
List * mergeclauses
Definition: plannodes.h:841
bool skip_mark_restore
Definition: plannodes.h:838

References Join::inner_unique, MergeJoin::join, Join::joinqual, Join::jointype, makeNode, MergeJoin::mergeclauses, plan, and MergeJoin::skip_mark_restore.

Referenced by create_mergejoin_plan().

◆ make_modifytable()

static ModifyTable * make_modifytable ( PlannerInfo root,
Plan subplan,
CmdType  operation,
bool  canSetTag,
Index  nominalRelation,
Index  rootRelation,
bool  partColsUpdated,
List resultRelations,
List updateColnosLists,
List withCheckOptionLists,
List returningLists,
List rowMarks,
OnConflictExpr onconflict,
List mergeActionLists,
List mergeJoinConditions,
int  epqParam 
)
static

Definition at line 7023 of file createplan.c.

7033 {
7034  ModifyTable *node = makeNode(ModifyTable);
7035  List *fdw_private_list;
7036  Bitmapset *direct_modify_plans;
7037  ListCell *lc;
7038  int i;
7039 
7040  Assert(operation == CMD_MERGE ||
7041  (operation == CMD_UPDATE ?
7042  list_length(resultRelations) == list_length(updateColnosLists) :
7043  updateColnosLists == NIL));
7044  Assert(withCheckOptionLists == NIL ||
7045  list_length(resultRelations) == list_length(withCheckOptionLists));
7046  Assert(returningLists == NIL ||
7047  list_length(resultRelations) == list_length(returningLists));
7048 
7049  node->plan.lefttree = subplan;
7050  node->plan.righttree = NULL;
7051  node->plan.qual = NIL;
7052  /* setrefs.c will fill in the targetlist, if needed */
7053  node->plan.targetlist = NIL;
7054 
7055  node->operation = operation;
7056  node->canSetTag = canSetTag;
7057  node->nominalRelation = nominalRelation;
7058  node->rootRelation = rootRelation;
7059  node->partColsUpdated = partColsUpdated;
7060  node->resultRelations = resultRelations;
7061  if (!onconflict)
7062  {
7064  node->onConflictSet = NIL;
7065  node->onConflictCols = NIL;
7066  node->onConflictWhere = NULL;
7067  node->arbiterIndexes = NIL;
7068  node->exclRelRTI = 0;
7069  node->exclRelTlist = NIL;
7070  }
7071  else
7072  {
7073  node->onConflictAction = onconflict->action;
7074 
7075  /*
7076  * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7077  * executor's convention of having consecutive resno's. The actual
7078  * target column numbers are saved in node->onConflictCols. (This
7079  * could be done earlier, but there seems no need to.)
7080  */
7081  node->onConflictSet = onconflict->onConflictSet;
7082  node->onConflictCols =
7084  node->onConflictWhere = onconflict->onConflictWhere;
7085 
7086  /*
7087  * If a set of unique index inference elements was provided (an
7088  * INSERT...ON CONFLICT "inference specification"), then infer
7089  * appropriate unique indexes (or throw an error if none are
7090  * available).
7091  */
7093 
7094  node->exclRelRTI = onconflict->exclRelIndex;
7095  node->exclRelTlist = onconflict->exclRelTlist;
7096  }
7097  node->updateColnosLists = updateColnosLists;
7098  node->withCheckOptionLists = withCheckOptionLists;
7099  node->returningLists = returningLists;
7100  node->rowMarks = rowMarks;
7101  node->mergeActionLists = mergeActionLists;
7102  node->mergeJoinConditions = mergeJoinConditions;
7103  node->epqParam = epqParam;
7104 
7105  /*
7106  * For each result relation that is a foreign table, allow the FDW to
7107  * construct private plan data, and accumulate it all into a list.
7108  */
7109  fdw_private_list = NIL;
7110  direct_modify_plans = NULL;
7111  i = 0;
7112  foreach(lc, resultRelations)
7113  {
7114  Index rti = lfirst_int(lc);
7115  FdwRoutine *fdwroutine;
7116  List *fdw_private;
7117  bool direct_modify;
7118 
7119  /*
7120  * If possible, we want to get the FdwRoutine from our RelOptInfo for
7121  * the table. But sometimes we don't have a RelOptInfo and must get
7122  * it the hard way. (In INSERT, the target relation is not scanned,
7123  * so it's not a baserel; and there are also corner cases for
7124  * updatable views where the target rel isn't a baserel.)
7125  */
7126  if (rti < root->simple_rel_array_size &&
7127  root->simple_rel_array[rti] != NULL)
7128  {
7129  RelOptInfo *resultRel = root->simple_rel_array[rti];
7130 
7131  fdwroutine = resultRel->fdwroutine;
7132  }
7133  else
7134  {
7135  RangeTblEntry *rte = planner_rt_fetch(rti, root);
7136 
7137  if (rte->rtekind == RTE_RELATION &&
7138  rte->relkind == RELKIND_FOREIGN_TABLE)
7139  fdwroutine = GetFdwRoutineByRelId(rte->relid);
7140  else
7141  fdwroutine = NULL;
7142  }
7143 
7144  /*
7145  * MERGE is not currently supported for foreign tables. We already
7146  * checked that when the table mentioned in the query is foreign; but
7147  * we can still get here if a partitioned table has a foreign table as
7148  * partition. Disallow that now, to avoid an uglier error message
7149  * later.
7150  */
7151  if (operation == CMD_MERGE && fdwroutine != NULL)
7152  {
7153  RangeTblEntry *rte = planner_rt_fetch(rti, root);
7154 
7155  ereport(ERROR,
7156  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7157  errmsg("cannot execute MERGE on relation \"%s\"",
7158  get_rel_name(rte->relid)),
7159  errdetail_relkind_not_supported(rte->relkind));
7160  }
7161 
7162  /*
7163  * Try to modify the foreign table directly if (1) the FDW provides
7164  * callback functions needed for that and (2) there are no local
7165  * structures that need to be run for each modified row: row-level
7166  * triggers on the foreign table, stored generated columns, WITH CHECK
7167  * OPTIONs from parent views.
7168  */
7169  direct_modify = false;
7170  if (fdwroutine != NULL &&
7171  fdwroutine->PlanDirectModify != NULL &&
7172  fdwroutine->BeginDirectModify != NULL &&
7173  fdwroutine->IterateDirectModify != NULL &&
7174  fdwroutine->EndDirectModify != NULL &&
7175  withCheckOptionLists == NIL &&
7176  !has_row_triggers(root, rti, operation) &&
7178  direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
7179  if (direct_modify)
7180  direct_modify_plans = bms_add_member(direct_modify_plans, i);
7181 
7182  if (!direct_modify &&
7183  fdwroutine != NULL &&
7184  fdwroutine->PlanForeignModify != NULL)
7185  fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7186  else
7187  fdw_private = NIL;
7188  fdw_private_list = lappend(fdw_private_list, fdw_private);
7189  i++;
7190  }
7191  node->fdwPrivLists = fdw_private_list;
7192  node->fdwDirectModifyPlans = direct_modify_plans;
7193 
7194  return node;
7195 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:409
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
@ ONCONFLICT_NONE
Definition: nodes.h:418
@ CMD_MERGE
Definition: nodes.h:269
@ CMD_UPDATE
Definition: nodes.h:266
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
bool has_stored_generated_columns(PlannerInfo *root, Index rti)
Definition: plancat.c:2278
bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
Definition: plancat.c:2228
List * infer_arbiter_indexes(PlannerInfo *root)
Definition: plancat.c:693
List * extract_update_targetlist_colnos(List *tlist)
Definition: preptlist.c:345
BeginDirectModify_function BeginDirectModify
Definition: fdwapi.h:242
PlanForeignModify_function PlanForeignModify
Definition: fdwapi.h:230
PlanDirectModify_function PlanDirectModify
Definition: fdwapi.h:241
IterateDirectModify_function IterateDirectModify
Definition: fdwapi.h:243
EndDirectModify_function EndDirectModify
Definition: fdwapi.h:244
List * updateColnosLists
Definition: plannodes.h:238
Index nominalRelation
Definition: plannodes.h:234
List * arbiterIndexes
Definition: plannodes.h:246
List * onConflictCols
Definition: plannodes.h:248
List * mergeJoinConditions
Definition: plannodes.h:254
CmdType operation
Definition: plannodes.h:232
int epqParam
Definition: plannodes.h:244
List * resultRelations
Definition: plannodes.h:237
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:242
List * onConflictSet
Definition: plannodes.h:247
List * exclRelTlist
Definition: plannodes.h:251
List * mergeActionLists
Definition: plannodes.h:252
bool canSetTag
Definition: plannodes.h:233
List * fdwPrivLists
Definition: plannodes.h:241
bool partColsUpdated
Definition: plannodes.h:236
List * returningLists
Definition: plannodes.h:240
List * withCheckOptionLists
Definition: plannodes.h:239
Index rootRelation
Definition: plannodes.h:235
Node * onConflictWhere
Definition: plannodes.h:249
List * rowMarks
Definition: plannodes.h:243
OnConflictAction onConflictAction
Definition: plannodes.h:245
Index exclRelRTI
Definition: plannodes.h:250
OnConflictAction action
Definition: primnodes.h:2320
List * onConflictSet
Definition: primnodes.h:2329
List * exclRelTlist
Definition: primnodes.h:2332
Node * onConflictWhere
Definition: primnodes.h:2330
struct Plan * righttree
Definition: plannodes.h:155
List * qual
Definition: plannodes.h:153

References OnConflictExpr::action, ModifyTable::arbiterIndexes, Assert, FdwRoutine::BeginDirectModify, bms_add_member(), ModifyTable::canSetTag, CMD_MERGE, CMD_UPDATE, FdwRoutine::EndDirectModify, ModifyTable::epqParam, ereport, errcode(), errdetail_relkind_not_supported(), errmsg(), ERROR, OnConflictExpr::exclRelIndex, ModifyTable::exclRelRTI, ModifyTable::exclRelTlist, OnConflictExpr::exclRelTlist, extract_update_targetlist_colnos(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, get_rel_name(), GetFdwRoutineByRelId(), has_row_triggers(), has_stored_generated_columns(), i, infer_arbiter_indexes(), FdwRoutine::IterateDirectModify, lappend(), Plan::lefttree, lfirst_int, list_length(), makeNode, ModifyTable::mergeActionLists, ModifyTable::mergeJoinConditions, NIL, ModifyTable::nominalRelation, ONCONFLICT_NONE, ModifyTable::onConflictAction, ModifyTable::onConflictCols, ModifyTable::onConflictSet, OnConflictExpr::onConflictSet, ModifyTable::onConflictWhere, OnConflictExpr::onConflictWhere, ModifyTable::operation, ModifyTable::partColsUpdated, ModifyTable::plan, FdwRoutine::PlanDirectModify, FdwRoutine::PlanForeignModify, planner_rt_fetch, Plan::qual, RangeTblEntry::relid, ModifyTable::resultRelations, ModifyTable::returningLists, Plan::righttree, root, ModifyTable::rootRelation, ModifyTable::rowMarks, RTE_RELATION, RangeTblEntry::rtekind, Plan::targetlist, ModifyTable::updateColnosLists, and ModifyTable::withCheckOptionLists.

Referenced by create_modifytable_plan().

◆ make_namedtuplestorescan()

static NamedTuplestoreScan * make_namedtuplestorescan ( List qptlist,
List qpqual,
Index  scanrelid,
char *  enrname 
)
static

Definition at line 5778 of file createplan.c.

5782 {
5784  Plan *plan = &node->scan.plan;
5785 
5786  /* cost should be inserted by caller */
5787  plan->targetlist = qptlist;
5788  plan->qual = qpqual;
5789  plan->lefttree = NULL;
5790  plan->righttree = NULL;
5791  node->scan.scanrelid = scanrelid;
5792  node->enrname = enrname;
5793 
5794  return node;
5795 }

References NamedTuplestoreScan::enrname, makeNode, plan, NamedTuplestoreScan::scan, and Scan::scanrelid.

Referenced by create_namedtuplestorescan_plan().

◆ make_nestloop()

static NestLoop * make_nestloop ( List tlist,
List joinclauses,
List otherclauses,
List nestParams,
Plan lefttree,
Plan righttree,
JoinType  jointype,
bool  inner_unique 
)
static

Definition at line 5943 of file createplan.c.

5951 {
5952  NestLoop *node = makeNode(NestLoop);
5953  Plan *plan = &node->join.plan;
5954 
5955  plan->targetlist = tlist;
5956  plan->qual = otherclauses;
5957  plan->lefttree = lefttree;
5958  plan->righttree = righttree;
5959  node->join.jointype = jointype;
5960  node->join.inner_unique = inner_unique;
5961  node->join.joinqual = joinclauses;
5962  node->nestParams = nestParams;
5963 
5964  return node;
5965 }
List * nestParams
Definition: plannodes.h:810

References Join::inner_unique, NestLoop::join, Join::joinqual, Join::jointype, makeNode, NestLoop::nestParams, and plan.

Referenced by create_nestloop_plan().

◆ make_project_set()

static ProjectSet * make_project_set ( List tlist,
Plan subplan 
)
static

Definition at line 7004 of file createplan.c.

7006 {
7007  ProjectSet *node = makeNode(ProjectSet);
7008  Plan *plan = &node->plan;
7009 
7010  plan->targetlist = tlist;
7011  plan->qual = NIL;
7012  plan->lefttree = subplan;
7013  plan->righttree = NULL;
7014 
7015  return node;
7016 }
Plan plan
Definition: plannodes.h:210

References makeNode, NIL, ProjectSet::plan, and plan.

Referenced by create_project_set_plan().

◆ make_recursive_union()

static RecursiveUnion * make_recursive_union ( List tlist,
Plan lefttree,
Plan righttree,
int  wtParam,
List distinctList,
long  numGroups 
)
static

Definition at line 5857 of file createplan.c.

5863 {
5865  Plan *plan = &node->plan;
5866  int numCols = list_length(distinctList);
5867 
5868  plan->targetlist = tlist;
5869  plan->qual = NIL;
5870  plan->lefttree = lefttree;
5871  plan->righttree = righttree;
5872  node->wtParam = wtParam;
5873 
5874  /*
5875  * convert SortGroupClause list into arrays of attr indexes and equality
5876  * operators, as wanted by executor
5877  */
5878  node->numCols = numCols;
5879  if (numCols > 0)
5880  {
5881  int keyno = 0;
5882  AttrNumber *dupColIdx;
5883  Oid *dupOperators;
5884  Oid *dupCollations;
5885  ListCell *slitem;
5886 
5887  dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5888  dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5889  dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
5890 
5891  foreach(slitem, distinctList)
5892  {
5893  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5894  TargetEntry *tle = get_sortgroupclause_tle(sortcl,
5895  plan->targetlist);
5896 
5897  dupColIdx[keyno] = tle->resno;
5898  dupOperators[keyno] = sortcl->eqop;
5899  dupCollations[keyno] = exprCollation((Node *) tle->expr);
5900  Assert(OidIsValid(dupOperators[keyno]));
5901  keyno++;
5902  }
5903  node->dupColIdx = dupColIdx;
5904  node->dupOperators = dupOperators;
5905  node->dupCollations = dupCollations;
5906  }
5907  node->numGroups = numGroups;
5908 
5909  return node;
5910 }

References Assert, SortGroupClause::eqop, TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, RecursiveUnion::numCols, RecursiveUnion::numGroups, OidIsValid, palloc(), RecursiveUnion::plan, plan, TargetEntry::resno, and RecursiveUnion::wtParam.

Referenced by create_recursiveunion_plan().

◆ make_result()

static Result * make_result ( List tlist,
Node resconstantqual,
Plan subplan 
)
static

Definition at line 6983 of file createplan.c.

6986 {
6987  Result *node = makeNode(Result);
6988  Plan *plan = &node->plan;
6989 
6990  plan->targetlist = tlist;
6991  plan->qual = NIL;
6992  plan->lefttree = subplan;
6993  plan->righttree = NULL;
6994  node->resconstantqual = resconstantqual;
6995 
6996  return node;
6997 }

References makeNode, NIL, Result::plan, plan, and Result::resconstantqual.

Referenced by create_append_plan(), create_gating_plan(), create_group_result_plan(), create_minmaxagg_plan(), create_projection_plan(), create_resultscan_plan(), and inject_projection_plan().

◆ make_samplescan()

static SampleScan * make_samplescan ( List qptlist,
List qpqual,
Index  scanrelid,
TableSampleClause tsc 
)
static

Definition at line 5520 of file createplan.c.

5524 {
5525  SampleScan *node = makeNode(SampleScan);
5526  Plan *plan = &node->scan.plan;
5527 
5528  plan->targetlist = qptlist;
5529  plan->qual = qpqual;
5530  plan->lefttree = NULL;
5531  plan->righttree = NULL;
5532  node->scan.scanrelid = scanrelid;
5533  node->tablesample = tsc;
5534 
5535  return node;
5536 }
struct TableSampleClause * tablesample
Definition: plannodes.h:409

References makeNode, plan, SampleScan::scan, Scan::scanrelid, and SampleScan::tablesample.

Referenced by create_samplescan_plan().

◆ make_seqscan()

static SeqScan * make_seqscan ( List qptlist,
List qpqual,
Index  scanrelid 
)
static

Definition at line 5503 of file createplan.c.

5506 {
5507  SeqScan *node = makeNode(SeqScan);
5508  Plan *plan = &node->scan.plan;
5509 
5510  plan->targetlist = qptlist;
5511  plan->qual = qpqual;
5512  plan->lefttree = NULL;
5513  plan->righttree = NULL;
5514  node->scan.scanrelid = scanrelid;
5515 
5516  return node;
5517 }

References makeNode, plan, SeqScan::scan, and Scan::scanrelid.

Referenced by create_seqscan_plan().

◆ make_setop()

static SetOp * make_setop ( SetOpCmd  cmd,
SetOpStrategy  strategy,
Plan lefttree,
List distinctList,
AttrNumber  flagColIdx,
int  firstFlag,
long  numGroups 
)
static

Definition at line 6878 of file createplan.c.

6881 {
6882  SetOp *node = makeNode(SetOp);
6883  Plan *plan = &node->plan;
6884  int numCols = list_length(distinctList);
6885  int keyno = 0;
6886  AttrNumber *dupColIdx;
6887  Oid *dupOperators;
6888  Oid *dupCollations;
6889  ListCell *slitem;
6890 
6891  plan->targetlist = lefttree->targetlist;
6892  plan->qual = NIL;
6893  plan->lefttree = lefttree;
6894  plan->righttree = NULL;
6895 
6896  /*
6897  * convert SortGroupClause list into arrays of attr indexes and equality
6898  * operators, as wanted by executor
6899  */
6900  dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6901  dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6902  dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6903 
6904  foreach(slitem, distinctList)
6905  {
6906  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6907  TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6908 
6909  dupColIdx[keyno] = tle->resno;
6910  dupOperators[keyno] = sortcl->eqop;
6911  dupCollations[keyno] = exprCollation((Node *) tle->expr);
6912  Assert(OidIsValid(dupOperators[keyno]));
6913  keyno++;
6914  }
6915 
6916  node->cmd = cmd;
6917  node->strategy = strategy;
6918  node->numCols = numCols;
6919  node->dupColIdx = dupColIdx;
6920  node->dupOperators = dupOperators;
6921  node->dupCollations = dupCollations;
6922  node->flagColIdx = flagColIdx;
6923  node->firstFlag = firstFlag;
6924  node->numGroups = numGroups;
6925 
6926  return node;
6927 }
SetOpStrategy strategy
Definition: plannodes.h:1225
AttrNumber flagColIdx
Definition: plannodes.h:1238
SetOpCmd cmd
Definition: plannodes.h:1222
int numCols
Definition: plannodes.h:1228
int firstFlag
Definition: plannodes.h:1241
Plan plan
Definition: plannodes.h:1219
long numGroups
Definition: plannodes.h:1244

References Assert, SetOp::cmd, SortGroupClause::eqop, TargetEntry::expr, exprCollation(), SetOp::firstFlag, SetOp::flagColIdx, get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, SetOp::numCols, SetOp::numGroups, OidIsValid, palloc(), SetOp::plan, plan, TargetEntry::resno, SetOp::strategy, and Plan::targetlist.

Referenced by create_setop_plan().

◆ make_sort()

static Sort * make_sort ( Plan lefttree,
int  numCols,
AttrNumber sortColIdx,
Oid sortOperators,
Oid collations,
bool nullsFirst 
)
static

Definition at line 6063 of file createplan.c.

6066 {
6067  Sort *node;
6068  Plan *plan;
6069 
6070  node = makeNode(Sort);
6071 
6072  plan = &node->plan;
6073  plan->targetlist = lefttree->targetlist;
6074  plan->qual = NIL;
6075  plan->lefttree = lefttree;
6076  plan->righttree = NULL;
6077  node->numCols = numCols;
6078  node->sortColIdx = sortColIdx;
6079  node->sortOperators = sortOperators;
6080  node->collations = collations;
6081  node->nullsFirst = nullsFirst;
6082 
6083  return node;
6084 }

References makeNode, NIL, Sort::numCols, Sort::plan, plan, and Plan::targetlist.

Referenced by create_append_plan(), create_merge_append_plan(), make_sort_from_groupcols(), make_sort_from_pathkeys(), and make_sort_from_sortclauses().

◆ make_sort_from_groupcols()

static Sort * make_sort_from_groupcols ( List groupcls,
AttrNumber grpColIdx,
Plan lefttree 
)
static

Definition at line 6459 of file createplan.c.

6462 {
6463  List *sub_tlist = lefttree->targetlist;
6464  ListCell *l;
6465  int numsortkeys;
6466  AttrNumber *sortColIdx;
6467  Oid *sortOperators;
6468  Oid *collations;
6469  bool *nullsFirst;
6470 
6471  /* Convert list-ish representation to arrays wanted by executor */
6472  numsortkeys = list_length(groupcls);
6473  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6474  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6475  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6476  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6477 
6478  numsortkeys = 0;
6479  foreach(l, groupcls)
6480  {
6481  SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
6482  TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
6483 
6484  if (!tle)
6485  elog(ERROR, "could not retrieve tle for sort-from-groupcols");
6486 
6487  sortColIdx[numsortkeys] = tle->resno;
6488  sortOperators[numsortkeys] = grpcl->sortop;
6489  collations[numsortkeys] = exprCollation((Node *) tle->expr);
6490  nullsFirst[numsortkeys] = grpcl->nulls_first;
6491  numsortkeys++;
6492  }
6493 
6494  return make_sort(lefttree, numsortkeys,
6495  sortColIdx, sortOperators,
6496  collations, nullsFirst);
6497 }

References elog, ERROR, TargetEntry::expr, exprCollation(), get_tle_by_resno(), lfirst, list_length(), make_sort(), SortGroupClause::nulls_first, palloc(), TargetEntry::resno, SortGroupClause::sortop, and Plan::targetlist.

Referenced by create_groupingsets_plan().

◆ make_sort_from_pathkeys()

static Sort * make_sort_from_pathkeys ( Plan lefttree,
List pathkeys,
Relids  relids 
)
static

Definition at line 6341 of file createplan.c.

6342 {
6343  int numsortkeys;
6344  AttrNumber *sortColIdx;
6345  Oid *sortOperators;
6346  Oid *collations;
6347  bool *nullsFirst;
6348 
6349  /* Compute sort column info, and adjust lefttree as needed */
6350  lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6351  relids,
6352  NULL,
6353  false,
6354  &numsortkeys,
6355  &sortColIdx,
6356  &sortOperators,
6357  &collations,
6358  &nullsFirst);
6359 
6360  /* Now build the Sort node */
6361  return make_sort(lefttree, numsortkeys,
6362  sortColIdx, sortOperators,
6363  collations, nullsFirst);
6364 }

References make_sort(), and prepare_sort_from_pathkeys().

Referenced by create_mergejoin_plan(), and create_sort_plan().

◆ make_sort_from_sortclauses()

Sort* make_sort_from_sortclauses ( List sortcls,
Plan lefttree 
)

Definition at line 6410 of file createplan.c.

6411 {
6412  List *sub_tlist = lefttree->targetlist;
6413  ListCell *l;
6414  int numsortkeys;
6415  AttrNumber *sortColIdx;
6416  Oid *sortOperators;
6417  Oid *collations;
6418  bool *nullsFirst;
6419 
6420  /* Convert list-ish representation to arrays wanted by executor */
6421  numsortkeys = list_length(sortcls);
6422  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6423  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6424  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6425  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6426 
6427  numsortkeys = 0;
6428  foreach(l, sortcls)
6429  {
6430  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
6431  TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
6432 
6433  sortColIdx[numsortkeys] = tle->resno;
6434  sortOperators[numsortkeys] = sortcl->sortop;
6435  collations[numsortkeys] = exprCollation((Node *) tle->expr);
6436  nullsFirst[numsortkeys] = sortcl->nulls_first;
6437  numsortkeys++;
6438  }
6439 
6440  return make_sort(lefttree, numsortkeys,
6441  sortColIdx, sortOperators,
6442  collations, nullsFirst);
6443 }

References TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), make_sort(), SortGroupClause::nulls_first, palloc(), TargetEntry::resno, SortGroupClause::sortop, and Plan::targetlist.

Referenced by create_unique_plan().

◆ make_subqueryscan()

static SubqueryScan * make_subqueryscan ( List qptlist,
List qpqual,
Index  scanrelid,
Plan subplan 
)
static

Definition at line 5678 of file createplan.c.

5682 {
5684  Plan *plan = &node->scan.plan;
5685 
5686  plan->targetlist = qptlist;
5687  plan->qual = qpqual;
5688  plan->lefttree = NULL;
5689  plan->righttree = NULL;
5690  node->scan.scanrelid = scanrelid;
5691  node->subplan = subplan;
5693 
5694  return node;
5695 }
@ SUBQUERY_SCAN_UNKNOWN
Definition: plannodes.h:593
SubqueryScanStatus scanstatus
Definition: plannodes.h:602
Plan * subplan
Definition: plannodes.h:601

References makeNode, plan, SubqueryScan::scan, Scan::scanrelid, SubqueryScan::scanstatus, SubqueryScan::subplan, and SUBQUERY_SCAN_UNKNOWN.

Referenced by create_subqueryscan_plan().

◆ make_tablefuncscan()

static TableFuncScan * make_tablefuncscan ( List qptlist,
List qpqual,
Index  scanrelid,
TableFunc tablefunc 
)
static

Definition at line 5719 of file createplan.c.

5723 {
5725  Plan *plan = &node->scan.plan;
5726 
5727  plan->targetlist = qptlist;
5728  plan->qual = qpqual;
5729  plan->lefttree = NULL;
5730  plan->righttree = NULL;
5731  node->scan.scanrelid = scanrelid;
5732  node->tablefunc = tablefunc;
5733 
5734  return node;
5735 }
TableFunc * tablefunc
Definition: plannodes.h:633

References makeNode, plan, TableFuncScan::scan, Scan::scanrelid, and TableFuncScan::tablefunc.

Referenced by create_tablefuncscan_plan().

◆ make_tidrangescan()

static TidRangeScan * make_tidrangescan ( List qptlist,
List qpqual,
Index  scanrelid,
List tidrangequals 
)
static

Definition at line 5659 of file createplan.c.

5663 {
5665  Plan *plan = &node->scan.plan;
5666 
5667  plan->targetlist = qptlist;
5668  plan->qual = qpqual;
5669  plan->lefttree = NULL;
5670  plan->righttree = NULL;
5671  node->scan.scanrelid = scanrelid;
5672  node->tidrangequals = tidrangequals;
5673 
5674  return node;
5675 }
List * tidrangequals
Definition: plannodes.h:568

References makeNode, plan, TidRangeScan::scan, Scan::scanrelid, and TidRangeScan::tidrangequals.

Referenced by create_tidrangescan_plan().

◆ make_tidscan()

static TidScan * make_tidscan ( List qptlist,
List qpqual,
Index  scanrelid,
List tidquals 
)
static

Definition at line 5640 of file createplan.c.

5644 {
5645  TidScan *node = makeNode(TidScan);
5646  Plan *plan = &node->scan.plan;
5647 
5648  plan->targetlist = qptlist;
5649  plan->qual = qpqual;
5650  plan->lefttree = NULL;
5651  plan->righttree = NULL;
5652  node->scan.scanrelid = scanrelid;
5653  node->tidquals = tidquals;
5654 
5655  return node;
5656 }
List * tidquals
Definition: plannodes.h:555

References makeNode, plan, TidScan::scan, Scan::scanrelid, and TidScan::tidquals.

Referenced by create_tidscan_plan().

◆ make_unique_from_pathkeys()

static Unique * make_unique_from_pathkeys ( Plan lefttree,
List pathkeys,
int  numCols 
)
static

Definition at line 6743 of file createplan.c.

6744 {
6745  Unique *node = makeNode(Unique);
6746  Plan *plan = &node->plan;
6747  int keyno = 0;
6748  AttrNumber *uniqColIdx;
6749  Oid *uniqOperators;
6750  Oid *uniqCollations;
6751  ListCell *lc;
6752 
6753  plan->targetlist = lefttree->targetlist;
6754  plan->qual = NIL;
6755  plan->lefttree = lefttree;
6756  plan->righttree = NULL;
6757 
6758  /*
6759  * Convert pathkeys list into arrays of attr indexes and equality
6760  * operators, as wanted by executor. This has a lot in common with
6761  * prepare_sort_from_pathkeys ... maybe unify sometime?
6762  */
6763  Assert(numCols >= 0 && numCols <= list_length(pathkeys));
6764  uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6765  uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6766  uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6767 
6768  foreach(lc, pathkeys)
6769  {
6770  PathKey *pathkey = (PathKey *) lfirst(lc);
6771  EquivalenceClass *ec = pathkey->pk_eclass;
6772  EquivalenceMember *em;
6773  TargetEntry *tle = NULL;
6774  Oid pk_datatype = InvalidOid;
6775  Oid eqop;
6776  ListCell *j;
6777 
6778  /* Ignore pathkeys beyond the specified number of columns */
6779  if (keyno >= numCols)
6780  break;
6781 
6782  if (ec->ec_has_volatile)
6783  {
6784  /*
6785  * If the pathkey's EquivalenceClass is volatile, then it must
6786  * have come from an ORDER BY clause, and we have to match it to
6787  * that same targetlist entry.
6788  */
6789  if (ec->ec_sortref == 0) /* can't happen */
6790  elog(ERROR, "volatile EquivalenceClass has no sortref");
6791  tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
6792  Assert(tle);
6793  Assert(list_length(ec->ec_members) == 1);
6794  pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6795  }
6796  else
6797  {
6798  /*
6799  * Otherwise, we can use any non-constant expression listed in the
6800  * pathkey's EquivalenceClass. For now, we take the first tlist
6801  * item found in the EC.
6802  */
6803  foreach(j, plan->targetlist)
6804  {
6805  tle = (TargetEntry *) lfirst(j);
6806  em = find_ec_member_matching_expr(ec, tle->expr, NULL);
6807  if (em)
6808  {
6809  /* found expr already in tlist */
6810  pk_datatype = em->em_datatype;
6811  break;
6812  }
6813  tle = NULL;
6814  }
6815  }
6816 
6817  if (!tle)
6818  elog(ERROR, "could not find pathkey item to sort");
6819 
6820  /*
6821  * Look up the correct equality operator from the PathKey's slightly
6822  * abstracted representation.
6823  */
6824  eqop = get_opfamily_member(pathkey->pk_opfamily,
6825  pk_datatype,
6826  pk_datatype,
6828  if (!OidIsValid(eqop)) /* should not happen */
6829  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6830  BTEqualStrategyNumber, pk_datatype, pk_datatype,
6831  pathkey->pk_opfamily);
6832 
6833  uniqColIdx[keyno] = tle->resno;
6834  uniqOperators[keyno] = eqop;
6835  uniqCollations[keyno] = ec->ec_collation;
6836 
6837  keyno++;
6838  }
6839 
6840  node->numCols = numCols;
6841  node->uniqColIdx = uniqColIdx;
6842  node->uniqOperators = uniqOperators;
6843  node->uniqCollations = uniqCollations;
6844 
6845  return node;
6846 }
EquivalenceMember * find_ec_member_matching_expr(EquivalenceClass *ec, Expr *expr, Relids relids)
Definition: equivclass.c:760
int j
Definition: isn.c:74
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Plan plan
Definition: plannodes.h:1114
int numCols
Definition: plannodes.h:1117
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition: tlist.c:345

References Assert, BTEqualStrategyNumber, EquivalenceClass::ec_collation, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_sortref, elog, EquivalenceMember::em_datatype, ERROR, TargetEntry::expr, find_ec_member_matching_expr(), get_opfamily_member(), get_sortgroupref_tle(), InvalidOid, j, lfirst, linitial, list_length(), makeNode, NIL, Unique::numCols, OidIsValid, palloc(), PathKey::pk_opfamily, Unique::plan, plan, TargetEntry::resno, and Plan::targetlist.

Referenced by create_upper_unique_plan().

◆ make_unique_from_sortclauses()

static Unique * make_unique_from_sortclauses ( Plan lefttree,
List distinctList 
)
static

Definition at line 6694 of file createplan.c.

6695 {
6696  Unique *node = makeNode(Unique);
6697  Plan *plan = &node->plan;
6698  int numCols = list_length(distinctList);
6699  int keyno = 0;
6700  AttrNumber *uniqColIdx;
6701  Oid *uniqOperators;
6702  Oid *uniqCollations;
6703  ListCell *slitem;
6704 
6705  plan->targetlist = lefttree->targetlist;
6706  plan->qual = NIL;
6707  plan->lefttree = lefttree;
6708  plan->righttree = NULL;
6709 
6710  /*
6711  * convert SortGroupClause list into arrays of attr indexes and equality
6712  * operators, as wanted by executor
6713  */
6714  Assert(numCols > 0);
6715  uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6716  uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6717  uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6718 
6719  foreach(slitem, distinctList)
6720  {
6721  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6722  TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6723 
6724  uniqColIdx[keyno] = tle->resno;
6725  uniqOperators[keyno] = sortcl->eqop;
6726  uniqCollations[keyno] = exprCollation((Node *) tle->expr);
6727  Assert(OidIsValid(uniqOperators[keyno]));
6728  keyno++;
6729  }
6730 
6731  node->numCols = numCols;
6732  node->uniqColIdx = uniqColIdx;
6733  node->uniqOperators = uniqOperators;
6734  node->uniqCollations = uniqCollations;
6735 
6736  return node;
6737 }

References Assert, SortGroupClause::eqop, TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, Unique::numCols, OidIsValid, palloc(), Unique::plan, plan, TargetEntry::resno, and Plan::targetlist.

Referenced by create_unique_plan().

◆ make_valuesscan()

static ValuesScan * make_valuesscan ( List qptlist,
List qpqual,
Index  scanrelid,
List values_lists 
)
static

Definition at line 5738 of file createplan.c.

5742 {
5743  ValuesScan *node = makeNode(ValuesScan);
5744  Plan *plan = &node->scan.plan;
5745 
5746  plan->targetlist = qptlist;
5747  plan->qual = qpqual;
5748  plan->lefttree = NULL;
5749  plan->righttree = NULL;
5750  node->scan.scanrelid = scanrelid;
5751  node->values_lists = values_lists;
5752 
5753  return node;
5754 }
List * values_lists
Definition: plannodes.h:623

References makeNode, plan, ValuesScan::scan, Scan::scanrelid, and ValuesScan::values_lists.

Referenced by create_valuesscan_plan().

◆ make_windowagg()

static WindowAgg * make_windowagg ( List tlist,
Index  winref,
int  partNumCols,
AttrNumber partColIdx,
Oid partOperators,
Oid partCollations,
int  ordNumCols,
AttrNumber ordColIdx,
Oid ordOperators,
Oid ordCollations,
int  frameOptions,
Node startOffset,
Node endOffset,
Oid  startInRangeFunc,
Oid  endInRangeFunc,
Oid  inRangeColl,
bool  inRangeAsc,
bool  inRangeNullsFirst,
List runCondition,
List qual,
bool  topWindow,
Plan lefttree 
)
static

Definition at line 6622 of file createplan.c.

6629 {
6630  WindowAgg *node = makeNode(WindowAgg);
6631  Plan *plan = &node->plan;
6632 
6633  node->winref = winref;
6634  node->partNumCols = partNumCols;
6635  node->partColIdx = partColIdx;
6636  node->partOperators = partOperators;
6637  node->partCollations = partCollations;
6638  node->ordNumCols = ordNumCols;
6639  node->ordColIdx = ordColIdx;
6640  node->ordOperators = ordOperators;
6641  node->ordCollations = ordCollations;
6642  node->frameOptions = frameOptions;
6643  node->startOffset = startOffset;
6644  node->endOffset = endOffset;
6645  node->runCondition = runCondition;
6646  /* a duplicate of the above for EXPLAIN */
6647  node->runConditionOrig = runCondition;
6648  node->startInRangeFunc = startInRangeFunc;
6649  node->endInRangeFunc = endInRangeFunc;
6650  node->inRangeColl = inRangeColl;
6651  node->inRangeAsc = inRangeAsc;
6652  node->inRangeNullsFirst = inRangeNullsFirst;
6653  node->topWindow = topWindow;
6654 
6655  plan->targetlist = tlist;
6656  plan->lefttree = lefttree;
6657  plan->righttree = NULL;
6658  plan->qual = qual;
6659 
6660  return node;
6661 }
int partNumCols
Definition: plannodes.h:1046
Oid endInRangeFunc
Definition: plannodes.h:1090
Node * endOffset
Definition: plannodes.h:1076
bool topWindow
Definition: plannodes.h:1105
Plan plan
Definition: plannodes.h:1040
List * runConditionOrig
Definition: plannodes.h:1082
Oid inRangeColl
Definition: plannodes.h:1093
Node * startOffset
Definition: plannodes.h:1073
List * runCondition
Definition: plannodes.h:1079
Oid startInRangeFunc
Definition: plannodes.h:1087
bool inRangeAsc
Definition: plannodes.h:1096
Index winref
Definition: plannodes.h:1043
bool inRangeNullsFirst
Definition: plannodes.h:1099
int ordNumCols
Definition: plannodes.h:1058
int frameOptions
Definition: plannodes.h:1070

References WindowAgg::endInRangeFunc, WindowAgg::endOffset, WindowAgg::frameOptions, WindowAgg::inRangeAsc, WindowAgg::inRangeColl, WindowAgg::inRangeNullsFirst, makeNode, WindowAgg::ordNumCols, WindowAgg::partNumCols, WindowAgg::plan, plan, WindowAgg::runCondition, WindowAgg::runConditionOrig, WindowAgg::startInRangeFunc, WindowAgg::startOffset, WindowAgg::topWindow, and WindowAgg::winref.

Referenced by create_windowagg_plan().

◆ make_worktablescan()

static WorkTableScan * make_worktablescan ( List qptlist,
List qpqual,
Index  scanrelid,
int  wtParam 
)
static

Definition at line 5798 of file createplan.c.

5802 {
5804  Plan *plan = &node->scan.plan;
5805 
5806  plan->targetlist = qptlist;
5807  plan->qual = qpqual;
5808  plan->lefttree = NULL;
5809  plan->righttree = NULL;
5810  node->scan.scanrelid = scanrelid;
5811  node->wtParam = wtParam;
5812 
5813  return node;
5814 }

References makeNode, plan, WorkTableScan::scan, Scan::scanrelid, and WorkTableScan::wtParam.

Referenced by create_worktablescan_plan().

◆ mark_async_capable_plan()

static bool mark_async_capable_plan ( Plan plan,
Path path 
)
static

Definition at line 1140 of file createplan.c.

1141 {
1142  switch (nodeTag(path))
1143  {
1144  case T_SubqueryScanPath:
1145  {
1146  SubqueryScan *scan_plan = (SubqueryScan *) plan;
1147 
1148  /*
1149  * If the generated plan node includes a gating Result node,
1150  * we can't execute it asynchronously.
1151  */
1152  if (IsA(plan, Result))
1153  return false;
1154 
1155  /*
1156  * If a SubqueryScan node atop of an async-capable plan node
1157  * is deletable, consider it as async-capable.
1158  */
1159  if (trivial_subqueryscan(scan_plan) &&
1160  mark_async_capable_plan(scan_plan->subplan,
1161  ((SubqueryScanPath *) path)->subpath))
1162  break;
1163  return false;
1164  }
1165  case T_ForeignPath:
1166  {
1167  FdwRoutine *fdwroutine = path->parent->fdwroutine;
1168 
1169  /*
1170  * If the generated plan node includes a gating Result node,
1171  * we can't execute it asynchronously.
1172  */
1173  if (IsA(plan, Result))
1174  return false;
1175 
1176  Assert(fdwroutine != NULL);
1177  if (fdwroutine->IsForeignPathAsyncCapable != NULL &&
1178  fdwroutine->IsForeignPathAsyncCapable((ForeignPath *) path))
1179  break;
1180  return false;
1181  }
1182  case T_ProjectionPath:
1183 
1184  /*
1185  * If the generated plan node includes a Result node for the
1186  * projection, we can't execute it asynchronously.
1187  */
1188  if (IsA(plan, Result))
1189  return false;
1190 
1191  /*
1192  * create_projection_plan() would have pulled up the subplan, so
1193  * check the capability using the subpath.
1194  */
1196  ((ProjectionPath *) path)->subpath))
1197  return true;
1198  return false;
1199  default:
1200  return false;
1201  }
1202 
1203  plan->async_capable = true;
1204 
1205  return true;
1206 }
bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1464
IsForeignPathAsyncCapable_function IsForeignPathAsyncCapable
Definition: fdwapi.h:277

References Assert, IsA, FdwRoutine::IsForeignPathAsyncCapable, nodeTag, plan, subpath(), SubqueryScan::subplan, and trivial_subqueryscan().

Referenced by create_append_plan().

◆ materialize_finished_plan()

Plan* materialize_finished_plan ( Plan subplan)

Definition at line 6522 of file createplan.c.

6523 {
6524  Plan *matplan;
6525  Path matpath; /* dummy for result of cost_material */
6526  Cost initplan_cost;
6527  bool unsafe_initplans;
6528 
6529  matplan = (Plan *) make_material(subplan);
6530 
6531  /*
6532  * XXX horrid kluge: if there are any initPlans attached to the subplan,
6533  * move them up to the Material node, which is now effectively the top
6534  * plan node in its query level. This prevents failure in
6535  * SS_finalize_plan(), which see for comments.
6536  */
6537  matplan->initPlan = subplan->initPlan;
6538  subplan->initPlan = NIL;
6539 
6540  /* Move the initplans' cost delta, as well */
6542  &initplan_cost, &unsafe_initplans);
6543  subplan->startup_cost -= initplan_cost;
6544  subplan->total_cost -= initplan_cost;
6545 
6546  /* Set cost data */
6547  cost_material(&matpath,
6548  subplan->startup_cost,
6549  subplan->total_cost,
6550  subplan->plan_rows,
6551  subplan->plan_width);
6552  matplan->startup_cost = matpath.startup_cost + initplan_cost;
6553  matplan->total_cost = matpath.total_cost + initplan_cost;
6554  matplan->plan_rows = subplan->plan_rows;
6555  matplan->plan_width = subplan->plan_width;
6556  matplan->parallel_aware = false;
6557  matplan->parallel_safe = subplan->parallel_safe;
6558 
6559  return matplan;
6560 }
void cost_material(Path *path, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition: costsize.c:2432
double Cost
Definition: nodes.h:251
List * initPlan
Definition: plannodes.h:156
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition: subselect.c:2198

References cost_material(), Plan::initPlan, make_material(), NIL, Plan::parallel_aware, Plan::parallel_safe, Plan::plan_rows, Plan::plan_width, SS_compute_initplan_cost(), Path::startup_cost, Plan::startup_cost, Path::total_cost, and Plan::total_cost.

Referenced by build_subplan(), and standard_planner().

◆ order_qual_clauses()

static List * order_qual_clauses ( PlannerInfo root,
List clauses 
)
static

Definition at line 5310 of file createplan.c.

5311 {
5312  typedef struct
5313  {
5314  Node *clause;
5315  Cost cost;
5316  Index security_level;
5317  } QualItem;
5318  int nitems = list_length(clauses);
5319  QualItem *items;
5320  ListCell *lc;
5321  int i;
5322  List *result;
5323 
5324  /* No need to work hard for 0 or 1 clause */
5325  if (nitems <= 1)
5326  return clauses;
5327 
5328  /*
5329  * Collect the items and costs into an array. This is to avoid repeated
5330  * cost_qual_eval work if the inputs aren't RestrictInfos.
5331  */
5332  items = (QualItem *) palloc(nitems * sizeof(QualItem));
5333  i = 0;
5334  foreach(lc, clauses)
5335  {
5336  Node *clause = (Node *) lfirst(lc);
5337  QualCost qcost;
5338 
5339  cost_qual_eval_node(&qcost, clause, root);
5340  items[i].clause = clause;
5341  items[i].cost = qcost.per_tuple;
5342  if (IsA(clause, RestrictInfo))
5343  {
5344  RestrictInfo *rinfo = (RestrictInfo *) clause;
5345 
5346  /*
5347  * If a clause is leakproof, it doesn't have to be constrained by
5348  * its nominal security level. If it's also reasonably cheap
5349  * (here defined as 10X cpu_operator_cost), pretend it has
5350  * security_level 0, which will allow it to go in front of
5351  * more-expensive quals of lower security levels. Of course, that
5352  * will also force it to go in front of cheaper quals of its own
5353  * security level, which is not so great, but we can alleviate
5354  * that risk by applying the cost limit cutoff.
5355  */
5356  if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
5357  items[i].security_level = 0;
5358  else
5359  items[i].security_level = rinfo->security_level;
5360  }
5361  else
5362  items[i].security_level = 0;
5363  i++;
5364  }
5365 
5366  /*
5367  * Sort. We don't use qsort() because it's not guaranteed stable for
5368  * equal keys. The expected number of entries is small enough that a
5369  * simple insertion sort should be good enough.
5370  */
5371  for (i = 1; i < nitems; i++)
5372  {
5373  QualItem newitem = items[i];
5374  int j;
5375 
5376  /* insert newitem into the already-sorted subarray */
5377  for (j = i; j > 0; j--)
5378  {
5379  QualItem *olditem = &items[j - 1];
5380 
5381  if (newitem.security_level > olditem->security_level ||
5382  (newitem.security_level == olditem->security_level &&
5383  newitem.cost >= olditem->cost))
5384  break;
5385  items[j] = *olditem;
5386  }
5387  items[j] = newitem;
5388  }
5389 
5390  /* Convert back to a list */
5391  result = NIL;
5392  for (i = 0; i < nitems; i++)
5393  result = lappend(result, items[i].clause);
5394 
5395  return result;
5396 }
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4645
#define nitems(x)
Definition: indent.h:31
Cost per_tuple
Definition: pathnodes.h:48
Index security_level
Definition: pathnodes.h:2586
static ItemArray items
Definition: test_tidstore.c:49

References cost_qual_eval_node(), cpu_operator_cost, i, IsA, items, j, lappend(), lfirst, list_length(), NIL, nitems, palloc(), QualCost::per_tuple, root, and RestrictInfo::security_level.

Referenced by create_agg_plan(), create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_group_plan(), create_group_result_plan(), create_hashjoin_plan(), create_indexscan_plan(), create_mergejoin_plan(), create_namedtuplestorescan_plan(), create_nestloop_plan(), create_resultscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidrangescan_plan(), create_tidscan_plan(), create_valuesscan_plan(), create_worktablescan_plan(), and get_gating_quals().

◆ prepare_sort_from_pathkeys()

static Plan * prepare_sort_from_pathkeys ( Plan lefttree,
List pathkeys,
Relids  relids,
const AttrNumber reqColIdx,
bool  adjust_tlist_in_place,
int *  p_numsortkeys,
AttrNumber **  p_sortColIdx,
Oid **  p_sortOperators,
Oid **  p_collations,
bool **  p_nullsFirst 
)
static

Definition at line 6159 of file createplan.c.

6168 {
6169  List *tlist = lefttree->targetlist;
6170  ListCell *i;
6171  int numsortkeys;
6172  AttrNumber *sortColIdx;
6173  Oid *sortOperators;
6174  Oid *collations;
6175  bool *nullsFirst;
6176 
6177  /*
6178  * We will need at most list_length(pathkeys) sort columns; possibly less
6179  */
6180  numsortkeys = list_length(pathkeys);
6181  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6182  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6183  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6184  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6185 
6186  numsortkeys = 0;
6187 
6188  foreach(i, pathkeys)
6189  {
6190  PathKey *pathkey = (PathKey *) lfirst(i);
6191  EquivalenceClass *ec = pathkey->pk_eclass;
6192  EquivalenceMember *em;
6193  TargetEntry *tle = NULL;
6194  Oid pk_datatype = InvalidOid;
6195  Oid sortop;
6196  ListCell *j;
6197 
6198  if (ec->ec_has_volatile)
6199  {
6200  /*
6201  * If the pathkey's EquivalenceClass is volatile, then it must
6202  * have come from an ORDER BY clause, and we have to match it to
6203  * that same targetlist entry.
6204  */
6205  if (ec->ec_sortref == 0) /* can't happen */
6206  elog(ERROR, "volatile EquivalenceClass has no sortref");
6207  tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
6208  Assert(tle);
6209  Assert(list_length(ec->ec_members) == 1);
6210  pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6211  }
6212  else if (reqColIdx != NULL)
6213  {
6214  /*
6215  * If we are given a sort column number to match, only consider
6216  * the single TLE at that position. It's possible that there is
6217  * no such TLE, in which case fall through and generate a resjunk
6218  * targetentry (we assume this must have happened in the parent
6219  * plan as well). If there is a TLE but it doesn't match the
6220  * pathkey's EC, we do the same, which is probably the wrong thing
6221  * but we'll leave it to caller to complain about the mismatch.
6222  */
6223  tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
6224  if (tle)
6225  {
6226  em = find_ec_member_matching_expr(ec, tle->expr, relids);
6227  if (em)
6228  {
6229  /* found expr at right place in tlist */
6230  pk_datatype = em->em_datatype;
6231  }
6232  else
6233  tle = NULL;
6234  }
6235  }
6236  else
6237  {
6238  /*
6239  * Otherwise, we can sort by any non-constant expression listed in
6240  * the pathkey's EquivalenceClass. For now, we take the first
6241  * tlist item found in the EC. If there's no match, we'll generate
6242  * a resjunk entry using the first EC member that is an expression
6243  * in the input's vars.
6244  *
6245  * XXX if we have a choice, is there any way of figuring out which
6246  * might be cheapest to execute? (For example, int4lt is likely
6247  * much cheaper to execute than numericlt, but both might appear
6248  * in the same equivalence class...) Not clear that we ever will
6249  * have an interesting choice in practice, so it may not matter.
6250  */
6251  foreach(j, tlist)
6252  {
6253  tle = (TargetEntry *) lfirst(j);
6254  em = find_ec_member_matching_expr(ec, tle->expr, relids);
6255  if (em)
6256  {
6257  /* found expr already in tlist */
6258  pk_datatype = em->em_datatype;
6259  break;
6260  }
6261  tle = NULL;
6262  }
6263  }
6264 
6265  if (!tle)
6266  {
6267  /*
6268  * No matching tlist item; look for a computable expression.
6269  */
6270  em = find_computable_ec_member(NULL, ec, tlist, relids, false);
6271  if (!em)
6272  elog(ERROR, "could not find pathkey item to sort");
6273  pk_datatype = em->em_datatype;
6274 
6275  /*
6276  * Do we need to insert a Result node?
6277  */
6278  if (!adjust_tlist_in_place &&
6279  !is_projection_capable_plan(lefttree))
6280  {
6281  /* copy needed so we don't modify input's tlist below */
6282  tlist = copyObject(tlist);
6283  lefttree = inject_projection_plan(lefttree, tlist,
6284  lefttree->parallel_safe);
6285  }
6286 
6287  /* Don't bother testing is_projection_capable_plan again */
6288  adjust_tlist_in_place = true;
6289 
6290  /*
6291  * Add resjunk entry to input's tlist
6292  */
6293  tle = makeTargetEntry(copyObject(em->em_expr),
6294  list_length(tlist) + 1,
6295  NULL,
6296  true);
6297  tlist = lappend(tlist, tle);
6298  lefttree->targetlist = tlist; /* just in case NIL before */
6299  }
6300 
6301  /*
6302  * Look up the correct sort operator from the PathKey's slightly
6303  * abstracted representation.
6304  */
6305  sortop = get_opfamily_member(pathkey->pk_opfamily,
6306  pk_datatype,
6307  pk_datatype,
6308  pathkey->pk_strategy);
6309  if (!OidIsValid(sortop)) /* should not happen */
6310  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6311  pathkey->pk_strategy, pk_datatype, pk_datatype,
6312  pathkey->pk_opfamily);
6313 
6314  /* Add the column to the sort arrays */
6315  sortColIdx[numsortkeys] = tle->resno;
6316  sortOperators[numsortkeys] = sortop;
6317  collations[numsortkeys] = ec->ec_collation;
6318  nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
6319  numsortkeys++;
6320  }
6321 
6322  /* Return results */
6323  *p_numsortkeys = numsortkeys;
6324  *p_sortColIdx = sortColIdx;
6325  *p_sortOperators = sortOperators;
6326  *p_collations = collations;
6327  *p_nullsFirst = nullsFirst;
6328 
6329  return lefttree;
6330 }
EquivalenceMember * find_computable_ec_member(PlannerInfo *root, EquivalenceClass *ec, List *exprs, Relids relids, bool require_parallel_safe)
Definition: equivclass.c:825

References Assert, copyObject, EquivalenceClass::ec_collation, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_sortref, elog, EquivalenceMember::em_datatype, EquivalenceMember::em_expr, ERROR, TargetEntry::expr, find_computable_ec_member(), find_ec_member_matching_expr(), get_opfamily_member(), get_sortgroupref_tle(), get_tle_by_resno(), i, inject_projection_plan(), InvalidOid, is_projection_capable_plan(), j, lappend(), lfirst, linitial, list_length(), makeTargetEntry(), OidIsValid, palloc(), Plan::parallel_safe, PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, TargetEntry::resno, and Plan::targetlist.

Referenced by create_append_plan(), create_gather_merge_plan(), create_merge_append_plan(), make_incrementalsort_from_pathkeys(), and make_sort_from_pathkeys().

◆ remap_groupColIdx()

static AttrNumber* remap_groupColIdx ( PlannerInfo root,
List groupClause 
)
static

Definition at line 2349 of file createplan.c.

2350 {
2351  AttrNumber *grouping_map = root->grouping_map;
2352  AttrNumber *new_grpColIdx;
2353  ListCell *lc;
2354  int i;
2355 
2356  Assert(grouping_map);
2357 
2358  new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
2359 
2360  i = 0;
2361  foreach(lc, groupClause)
2362  {
2363  SortGroupClause *clause = lfirst(lc);
2364 
2365  new_grpColIdx[i++] = grouping_map[clause->tleSortGroupRef];
2366  }
2367 
2368  return new_grpColIdx;
2369 }

References Assert, i, lfirst, list_length(), palloc0(), root, and SortGroupClause::tleSortGroupRef.

Referenced by create_groupingsets_plan().

◆ replace_nestloop_params()

◆ replace_nestloop_params_mutator()

static Node * replace_nestloop_params_mutator ( Node node,
PlannerInfo root 
)
static

Definition at line 4937 of file createplan.c.

4938 {
4939  if (node == NULL)
4940  return NULL;
4941  if (IsA(node, Var))
4942  {
4943  Var *var = (Var *) node;
4944 
4945  /* Upper-level Vars should be long gone at this point */
4946  Assert(var->varlevelsup == 0);
4947  /* If not to be replaced, we can just return the Var unmodified */
4948  if (IS_SPECIAL_VARNO(var->varno) ||
4949  !bms_is_member(var->varno, root->curOuterRels))
4950  return node;
4951  /* Replace the Var with a nestloop Param */
4952  return (Node *) replace_nestloop_param_var(root, var);
4953  }
4954  if (IsA(node, PlaceHolderVar))
4955  {
4956  PlaceHolderVar *phv = (PlaceHolderVar *) node;
4957 
4958  /* Upper-level PlaceHolderVars should be long gone at this point */
4959  Assert(phv->phlevelsup == 0);
4960 
4961  /* Check whether we need to replace the PHV */
4962  if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
4963  root->curOuterRels))
4964  {
4965  /*
4966  * We can't replace the whole PHV, but we might still need to
4967  * replace Vars or PHVs within its expression, in case it ends up
4968  * actually getting evaluated here. (It might get evaluated in
4969  * this plan node, or some child node; in the latter case we don't
4970  * really need to process the expression here, but we haven't got
4971  * enough info to tell if that's the case.) Flat-copy the PHV
4972  * node and then recurse on its expression.
4973  *
4974  * Note that after doing this, we might have different
4975  * representations of the contents of the same PHV in different
4976  * parts of the plan tree. This is OK because equal() will just
4977  * match on phid/phlevelsup, so setrefs.c will still recognize an
4978  * upper-level reference to a lower-level copy of the same PHV.
4979  */
4981 
4982  memcpy(newphv, phv, sizeof(PlaceHolderVar));
4983  newphv->phexpr = (Expr *)
4984  replace_nestloop_params_mutator((Node *) phv->phexpr,
4985  root);
4986  return (Node *) newphv;
4987  }
4988  /* Replace the PlaceHolderVar with a nestloop Param */
4990  }
4991  return expression_tree_mutator(node,
4993  (void *) root);
4994 }
#define expression_tree_mutator(n, m, c)
Definition: nodeFuncs.h:153
Param * replace_nestloop_param_var(PlannerInfo *root, Var *var)
Definition: paramassign.c:367
Param * replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
Definition: paramassign.c:416
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
Definition: placeholder.c:83
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:241
Index phlevelsup
Definition: pathnodes.h:2797
Index varlevelsup
Definition: primnodes.h:280

References Assert, bms_is_member(), bms_is_subset(), expression_tree_mutator, find_placeholder_info(), IS_SPECIAL_VARNO, IsA, makeNode, PlaceHolderVar::phlevelsup, replace_nestloop_param_placeholdervar(), replace_nestloop_param_var(), root, Var::varlevelsup, and Var::varno.

Referenced by replace_nestloop_params().

◆ use_physical_tlist()

static bool use_physical_tlist ( PlannerInfo root,
Path path,
int  flags 
)
static

Definition at line 865 of file createplan.c.

866 {
867  RelOptInfo *rel = path->parent;
868  int i;
869  ListCell *lc;
870 
871  /*
872  * Forget it if either exact tlist or small tlist is demanded.
873  */
874  if (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST))
875  return false;
876 
877  /*
878  * We can do this for real relation scans, subquery scans, function scans,
879  * tablefunc scans, values scans, and CTE scans (but not for, eg, joins).
880  */
881  if (rel->rtekind != RTE_RELATION &&
882  rel->rtekind != RTE_SUBQUERY &&
883  rel->rtekind != RTE_FUNCTION &&
884  rel->rtekind != RTE_TABLEFUNC &&
885  rel->rtekind != RTE_VALUES &&
886  rel->rtekind != RTE_CTE)
887  return false;
888 
889  /*
890  * Can't do it with inheritance cases either (mainly because Append
891  * doesn't project; this test may be unnecessary now that
892  * create_append_plan instructs its children to return an exact tlist).
893  */
894  if (rel->reloptkind != RELOPT_BASEREL)
895  return false;
896 
897  /*
898  * Also, don't do it to a CustomPath; the premise that we're extracting
899  * columns from a simple physical tuple is unlikely to hold for those.
900  * (When it does make sense, the custom path creator can set up the path's
901  * pathtarget that way.)
902  */
903  if (IsA(path, CustomPath))
904  return false;
905 
906  /*
907  * If a bitmap scan's tlist is empty, keep it as-is. This may allow the
908  * executor to skip heap page fetches, and in any case, the benefit of
909  * using a physical tlist instead would be minimal.
910  */
911  if (IsA(path, BitmapHeapPath) &&
912  path->pathtarget->exprs == NIL)
913  return false;
914 
915  /*
916  * Can't do it if any system columns or whole-row Vars are requested.
917  * (This could possibly be fixed but would take some fragile assumptions
918  * in setrefs.c, I think.)
919  */
920  for (i = rel->min_attr; i <= 0; i++)
921  {
922  if (!bms_is_empty(rel->attr_needed[i - rel->min_attr]))
923  return false;
924  }
925 
926  /*
927  * Can't do it if the rel is required to emit any placeholder expressions,
928  * either.
929  */
930  foreach(lc, root->placeholder_list)
931  {
932  PlaceHolderInfo *phinfo = (PlaceHolderInfo *) lfirst(lc);
933 
934  if (bms_nonempty_difference(phinfo->ph_needed, rel->relids) &&
935  bms_is_subset(phinfo->ph_eval_at, rel->relids))
936  return false;
937  }
938 
939  /*
940  * For an index-only scan, the "physical tlist" is the index's indextlist.
941  * We can only return that without a projection if all the index's columns
942  * are returnable.
943  */
944  if (path->pathtype == T_IndexOnlyScan)
945  {
946  IndexOptInfo *indexinfo = ((IndexPath *) path)->indexinfo;
947 
948  for (i = 0; i < indexinfo->ncolumns; i++)
949  {
950  if (!indexinfo->canreturn[i])
951  return false;
952  }
953  }
954 
955  /*
956  * Also, can't do it if CP_LABEL_TLIST is specified and path is requested
957  * to emit any sort/group columns that are not simple Vars. (If they are
958  * simple Vars, they should appear in the physical tlist, and
959  * apply_pathtarget_labeling_to_tlist will take care of getting them
960  * labeled again.) We also have to check that no two sort/group columns
961  * are the same Var, else that element of the physical tlist would need
962  * conflicting ressortgroupref labels.
963  */
964  if ((flags & CP_LABEL_TLIST) && path->pathtarget->sortgrouprefs)
965  {
966  Bitmapset *sortgroupatts = NULL;
967 
968  i = 0;
969  foreach(lc, path->pathtarget->exprs)
970  {
971  Expr *expr = (Expr *) lfirst(lc);
972 
973  if (path->pathtarget->sortgrouprefs[i])
974  {
975  if (expr && IsA(expr, Var))
976  {
977  int attno = ((Var *) expr)->varattno;
978 
980  if (bms_is_member(attno, sortgroupatts))
981  return false;
982  sortgroupatts = bms_add_member(sortgroupatts, attno);
983  }
984  else
985  return false;
986  }
987  i++;
988  }
989  }
990 
991  return true;
992 }
bool bms_nonempty_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:641
#define bms_is_empty(a)
Definition: bitmapset.h:118
@ RELOPT_BASEREL
Definition: pathnodes.h:821
Relids ph_needed
Definition: pathnodes.h:3094
Relids ph_eval_at
Definition: pathnodes.h:3088
AttrNumber min_attr
Definition: pathnodes.h:918

References bms_add_member(), bms_is_empty, bms_is_member(), bms_is_subset(), bms_nonempty_difference(), CP_EXACT_TLIST, CP_LABEL_TLIST, CP_SMALL_TLIST, FirstLowInvalidHeapAttributeNumber, i, IsA, lfirst, RelOptInfo::min_attr, IndexOptInfo::ncolumns, NIL, Path::pathtype, PlaceHolderInfo::ph_eval_at, PlaceHolderInfo::ph_needed, RelOptInfo::relids, RELOPT_BASEREL, RelOptInfo::reloptkind, root, RTE_CTE, RTE_FUNCTION, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, and RelOptInfo::rtekind.

Referenced by create_projection_plan(), and create_scan_plan().