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 5478 of file createplan.c.

5479 {
5480  if (IsA(plan, BitmapAnd))
5481  bitmap_subplan_mark_shared(linitial(((BitmapAnd *) plan)->bitmapplans));
5482  else if (IsA(plan, BitmapOr))
5483  {
5484  ((BitmapOr *) plan)->isshared = true;
5485  bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5486  }
5487  else if (IsA(plan, BitmapIndexScan))
5488  ((BitmapIndexScan *) plan)->isshared = true;
5489  else
5490  elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5491 }
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:5478
#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:4935
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:1884
Definition: pg_list.h:54
Definition: nodes.h:129
Index ressortgroupref
Definition: primnodes.h:2168

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 2152 of file createplan.c.

2153 {
2154  /*
2155  * If the top plan node can't do projections and its existing target list
2156  * isn't already what we need, we need to add a Result node to help it
2157  * along.
2158  */
2159  if (!is_projection_capable_plan(subplan) &&
2160  !tlist_same_exprs(tlist, subplan->targetlist))
2161  subplan = inject_projection_plan(subplan, tlist,
2162  subplan->parallel_safe &&
2163  tlist_parallel_safe);
2164  else
2165  {
2166  /* Else we can just replace the plan node's tlist */
2167  subplan->targetlist = tlist;
2168  subplan->parallel_safe &= tlist_parallel_safe;
2169  }
2170  return subplan;
2171 }
bool is_projection_capable_plan(Plan *plan)
Definition: createplan.c:7257
static Plan * inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
Definition: createplan.c:2120
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 5409 of file createplan.c.

5410 {
5411  dest->startup_cost = src->startup_cost;
5412  dest->total_cost = src->total_cost;
5413  dest->plan_rows = src->rows;
5414  dest->plan_width = src->pathtarget->width;
5415  dest->parallel_aware = src->parallel_aware;
5416  dest->parallel_safe = src->parallel_safe;
5417 }
Cardinality rows
Definition: pathnodes.h:1649
Cost startup_cost
Definition: pathnodes.h:1650
Cost total_cost
Definition: pathnodes.h:1651
bool parallel_aware
Definition: pathnodes.h:1642
bool parallel_safe
Definition: pathnodes.h:1644

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 5424 of file createplan.c.

5425 {
5426  dest->startup_cost = src->startup_cost;
5427  dest->total_cost = src->total_cost;
5428  dest->plan_rows = src->plan_rows;
5429  dest->plan_width = src->plan_width;
5430  /* Assume the inserted node is not parallel-aware. */
5431  dest->parallel_aware = false;
5432  /* Assume the inserted node is parallel-safe, if child plan is. */
5433  dest->parallel_safe = src->parallel_safe;
5434 }
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 2308 of file createplan.c.

2309 {
2310  Agg *plan;
2311  Plan *subplan;
2312  List *tlist;
2313  List *quals;
2314 
2315  /*
2316  * Agg can project, so no need to be terribly picky about child tlist, but
2317  * we do need grouping columns to be available
2318  */
2319  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2320 
2321  tlist = build_path_tlist(root, &best_path->path);
2322 
2323  quals = order_qual_clauses(root, best_path->qual);
2324 
2325  plan = make_agg(tlist, quals,
2326  best_path->aggstrategy,
2327  best_path->aggsplit,
2328  list_length(best_path->groupClause),
2330  subplan->targetlist),
2331  extract_grouping_ops(best_path->groupClause),
2333  subplan->targetlist),
2334  NIL,
2335  NIL,
2336  best_path->numGroups,
2337  best_path->transitionSpace,
2338  subplan);
2339 
2340  copy_generic_path_info(&plan->plan, (Path *) best_path);
2341 
2342  return plan;
2343 }
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:5315
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:6593
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5409
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:2243
Cardinality numGroups
Definition: pathnodes.h:2246
AggSplit aggsplit
Definition: pathnodes.h:2245
List * groupClause
Definition: pathnodes.h:2248
uint64 transitionSpace
Definition: pathnodes.h:2247
AggStrategy aggstrategy
Definition: pathnodes.h:2244
Path path
Definition: pathnodes.h:2242
List * qual
Definition: pathnodes.h:2249
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:6988
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Definition: createplan.c:5446
#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:6068
#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:6164
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:1923
Cardinality limit_tuples
Definition: pathnodes.h:1924
List * subpaths
Definition: pathnodes.h:1921
List * pathkeys
Definition: pathnodes.h:1654
bool async_capable
Definition: plannodes.h:146
List * baserestrictinfo
Definition: pathnodes.h:975
Relids relids
Definition: pathnodes.h:861

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 3201 of file createplan.c.

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

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 3331 of file createplan.c.

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

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

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 4276 of file createplan.c.

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

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

3762 {
3763  FunctionScan *scan_plan;
3764  Index scan_relid = best_path->parent->relid;
3765  RangeTblEntry *rte;
3766  List *functions;
3767 
3768  /* it should be a function base rel... */
3769  Assert(scan_relid > 0);
3770  rte = planner_rt_fetch(scan_relid, root);
3771  Assert(rte->rtekind == RTE_FUNCTION);
3772  functions = rte->functions;
3773 
3774  /* Sort clauses into best execution order */
3775  scan_clauses = order_qual_clauses(root, scan_clauses);
3776 
3777  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3778  scan_clauses = extract_actual_clauses(scan_clauses, false);
3779 
3780  /* Replace any outer-relation variables with nestloop params */
3781  if (best_path->param_info)
3782  {
3783  scan_clauses = (List *)
3784  replace_nestloop_params(root, (Node *) scan_clauses);
3785  /* The function expressions could contain nestloop params, too */
3787  }
3788 
3789  scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3790  functions, rte->funcordinality);
3791 
3792  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3793 
3794  return scan_plan;
3795 }
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5703
@ 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  /*
1992  * All gather merge paths should have already guaranteed the necessary
1993  * sort order either by adding an explicit sort node or by using presorted
1994  * input. We can't simply add a sort here on additional pathkeys, because
1995  * we can't guarantee the sort would be safe. For example, expressions may
1996  * be volatile or otherwise parallel unsafe.
1997  */
1998  if (!pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys))
1999  elog(ERROR, "gather merge input not sufficiently sorted");
2000 
2001  /* Now insert the subplan under GatherMerge. */
2002  gm_plan->plan.lefttree = subplan;
2003 
2004  /* use parallel mode for parallel plans. */
2005  root->glob->parallelModeNeeded = true;
2006 
2007  return gm_plan;
2008 }
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(), elog, ERROR, 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:6854
bool single_copy
Definition: pathnodes.h:2032
Path * subpath
Definition: pathnodes.h:2031
int num_workers
Definition: pathnodes.h:2033
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:5424
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 2241 of file createplan.c.

2242 {
2243  Group *plan;
2244  Plan *subplan;
2245  List *tlist;
2246  List *quals;
2247 
2248  /*
2249  * Group can project, so no need to be terribly picky about child tlist,
2250  * but we do need grouping columns to be available
2251  */
2252  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2253 
2254  tlist = build_path_tlist(root, &best_path->path);
2255 
2256  quals = order_qual_clauses(root, best_path->qual);
2257 
2258  plan = make_group(tlist,
2259  quals,
2260  list_length(best_path->groupClause),
2262  subplan->targetlist),
2263  extract_grouping_ops(best_path->groupClause),
2265  subplan->targetlist),
2266  subplan);
2267 
2268  copy_generic_path_info(&plan->plan, (Path *) best_path);
2269 
2270  return plan;
2271 }
static Group * make_group(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, Plan *lefttree)
Definition: createplan.c:6669
List * qual
Definition: pathnodes.h:2217
List * groupClause
Definition: pathnodes.h:2216
Path * subpath
Definition: pathnodes.h:2215
Path path
Definition: pathnodes.h:2214

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 2392 of file createplan.c.

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

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

2216 {
2218  Plan *subplan;
2219 
2220  /* See comments in create_sort_plan() above */
2221  subplan = create_plan_recurse(root, best_path->spath.subpath,
2222  flags | CP_SMALL_TLIST);
2224  best_path->spath.path.pathkeys,
2225  IS_OTHER_REL(best_path->spath.subpath->parent) ?
2226  best_path->spath.path.parent->relids : NULL,
2227  best_path->nPresortedCols);
2228 
2229  copy_generic_path_info(&plan->sort.plan, (Path *) best_path);
2230 
2231  return plan;
2232 }
static IncrementalSort * make_incrementalsort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
Definition: createplan.c:6381
#define IS_OTHER_REL(rel)
Definition: pathnodes.h:844
Path path
Definition: pathnodes.h:2188
Path * subpath
Definition: pathnodes.h:2189

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 3005 of file createplan.c.

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

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:4746
static MergeJoin * create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
Definition: createplan.c:4439
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:4347

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 2855 of file createplan.c.

2856 {
2857  Limit *plan;
2858  Plan *subplan;
2859  int numUniqkeys = 0;
2860  AttrNumber *uniqColIdx = NULL;
2861  Oid *uniqOperators = NULL;
2862  Oid *uniqCollations = NULL;
2863 
2864  /* Limit doesn't project, so tlist requirements pass through */
2865  subplan = create_plan_recurse(root, best_path->subpath, flags);
2866 
2867  /* Extract information necessary for comparing rows for WITH TIES. */
2868  if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
2869  {
2870  Query *parse = root->parse;
2871  ListCell *l;
2872 
2873  numUniqkeys = list_length(parse->sortClause);
2874  uniqColIdx = (AttrNumber *) palloc(numUniqkeys * sizeof(AttrNumber));
2875  uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2876  uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2877 
2878  numUniqkeys = 0;
2879  foreach(l, parse->sortClause)
2880  {
2881  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
2882  TargetEntry *tle = get_sortgroupclause_tle(sortcl, parse->targetList);
2883 
2884  uniqColIdx[numUniqkeys] = tle->resno;
2885  uniqOperators[numUniqkeys] = sortcl->eqop;
2886  uniqCollations[numUniqkeys] = exprCollation((Node *) tle->expr);
2887  numUniqkeys++;
2888  }
2889  }
2890 
2891  plan = make_limit(subplan,
2892  best_path->limitOffset,
2893  best_path->limitCount,
2894  best_path->limitOption,
2895  numUniqkeys, uniqColIdx, uniqOperators, uniqCollations);
2896 
2897  copy_generic_path_info(&plan->plan, (Path *) best_path);
2898 
2899  return plan;
2900 }
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
Definition: createplan.c:6960
void * palloc(Size size)
Definition: mcxt.c:1316
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:431
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:2389
LimitOption limitOption
Definition: pathnodes.h:2392
Node * limitOffset
Definition: pathnodes.h:2390
Node * limitCount
Definition: pathnodes.h:2391
Expr * expr
Definition: primnodes.h:2162

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 2791 of file createplan.c.

2793 {
2794  LockRows *plan;
2795  Plan *subplan;
2796 
2797  /* LockRows doesn't project, so tlist requirements pass through */
2798  subplan = create_plan_recurse(root, best_path->subpath, flags);
2799 
2800  plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2801 
2802  copy_generic_path_info(&plan->plan, (Path *) best_path);
2803 
2804  return plan;
2805 }
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:6939
Path * subpath
Definition: pathnodes.h:2349
List * rowMarks
Definition: pathnodes.h:2350

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:6505
Path * subpath
Definition: pathnodes.h:1971

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:5405
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:6568
#define lfirst_oid(lc)
Definition: pg_list.h:174
bool singlerow
Definition: pathnodes.h:1985
List * hash_operators
Definition: pathnodes.h:1983
uint32 est_entries
Definition: pathnodes.h:1990
bool binary_mode
Definition: pathnodes.h:1987
Path * subpath
Definition: pathnodes.h:1982
List * param_exprs
Definition: pathnodes.h:1984

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:1946
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 4439 of file createplan.c.

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

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 2550 of file createplan.c.

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

2815 {
2816  ModifyTable *plan;
2817  Path *subpath = best_path->subpath;
2818  Plan *subplan;
2819 
2820  /* Subplan must produce exactly the specified tlist */
2822 
2823  /* Transfer resname/resjunk labeling, too, to keep executor happy */
2824  apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2825 
2827  subplan,
2828  best_path->operation,
2829  best_path->canSetTag,
2830  best_path->nominalRelation,
2831  best_path->rootRelation,
2832  best_path->partColsUpdated,
2833  best_path->resultRelations,
2834  best_path->updateColnosLists,
2835  best_path->withCheckOptionLists,
2836  best_path->returningLists,
2837  best_path->rowMarks,
2838  best_path->onconflict,
2839  best_path->mergeActionLists,
2840  best_path->mergeJoinConditions,
2841  best_path->epqParam);
2842 
2843  copy_generic_path_info(&plan->plan, &best_path->path);
2844 
2845  return plan;
2846 }
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:7028
bool partColsUpdated
Definition: pathnodes.h:2369
List * returningLists
Definition: pathnodes.h:2373
List * resultRelations
Definition: pathnodes.h:2370
List * withCheckOptionLists
Definition: pathnodes.h:2372
List * mergeJoinConditions
Definition: pathnodes.h:2379
List * updateColnosLists
Definition: pathnodes.h:2371
OnConflictExpr * onconflict
Definition: pathnodes.h:2375
CmdType operation
Definition: pathnodes.h:2365
Index rootRelation
Definition: pathnodes.h:2368
Index nominalRelation
Definition: pathnodes.h:2367
List * mergeActionLists
Definition: pathnodes.h:2377
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 3985 of file createplan.c.

3987 {
3988  NamedTuplestoreScan *scan_plan;
3989  Index scan_relid = best_path->parent->relid;
3990  RangeTblEntry *rte;
3991 
3992  Assert(scan_relid > 0);
3993  rte = planner_rt_fetch(scan_relid, root);
3995 
3996  /* Sort clauses into best execution order */
3997  scan_clauses = order_qual_clauses(root, scan_clauses);
3998 
3999  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
4000  scan_clauses = extract_actual_clauses(scan_clauses, false);
4001 
4002  /* Replace any outer-relation variables with nestloop params */
4003  if (best_path->param_info)
4004  {
4005  scan_clauses = (List *)
4006  replace_nestloop_params(root, (Node *) scan_clauses);
4007  }
4008 
4009  scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
4010  rte->enrname);
4011 
4012  copy_generic_path_info(&scan_plan->scan.plan, best_path);
4013 
4014  return scan_plan;
4015 }
static NamedTuplestoreScan * make_namedtuplestorescan(List *qptlist, List *qpqual, Index scanrelid, char *enrname)
Definition: createplan.c:5783
@ 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 4347 of file createplan.c.

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

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:2855
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
Definition: createplan.c:2308
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
Definition: createplan.c:2719
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
Definition: createplan.c:2180
static Unique * create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
Definition: createplan.c:2280
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:2241
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
Definition: createplan.c:2814
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
Definition: createplan.c:2550
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
Definition: createplan.c:2791
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:2214
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
Definition: createplan.c:2018
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:2616
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
Definition: createplan.c:2392
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
Definition: createplan.c:2755
static Plan * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
Definition: createplan.c:1720
void check_stack_depth(void)
Definition: postgres.c:3531
NodeTag pathtype
Definition: pathnodes.h:1615

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:7009
Path * subpath
Definition: pathnodes.h:2175

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 2018 of file createplan.c.

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

2756 {
2758  Plan *leftplan;
2759  Plan *rightplan;
2760  List *tlist;
2761  long numGroups;
2762 
2763  /* Need both children to produce same tlist, so force it */
2764  leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
2765  rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
2766 
2767  tlist = build_path_tlist(root, &best_path->path);
2768 
2769  /* Convert numGroups to long int --- but 'ware overflow! */
2770  numGroups = clamp_cardinality_to_long(best_path->numGroups);
2771 
2772  plan = make_recursive_union(tlist,
2773  leftplan,
2774  rightplan,
2775  best_path->wtParam,
2776  best_path->distinctList,
2777  numGroups);
2778 
2779  copy_generic_path_info(&plan->plan, (Path *) best_path);
2780 
2781  return plan;
2782 }
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:5862
Cardinality numGroups
Definition: pathnodes.h:2340

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 4024 of file createplan.c.

4026 {
4027  Result *scan_plan;
4028  Index scan_relid = best_path->parent->relid;
4030 
4031  Assert(scan_relid > 0);
4032  rte = planner_rt_fetch(scan_relid, root);
4033  Assert(rte->rtekind == RTE_RESULT);
4034 
4035  /* Sort clauses into best execution order */
4036  scan_clauses = order_qual_clauses(root, scan_clauses);
4037 
4038  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
4039  scan_clauses = extract_actual_clauses(scan_clauses, false);
4040 
4041  /* Replace any outer-relation variables with nestloop params */
4042  if (best_path->param_info)
4043  {
4044  scan_clauses = (List *)
4045  replace_nestloop_params(root, (Node *) scan_clauses);
4046  }
4047 
4048  scan_plan = make_result(tlist, (Node *) scan_clauses, NULL);
4049 
4050  copy_generic_path_info(&scan_plan->plan, best_path);
4051 
4052  return scan_plan;
4053 }
#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 2954 of file createplan.c.

2956 {
2957  SampleScan *scan_plan;
2958  Index scan_relid = best_path->parent->relid;
2959  RangeTblEntry *rte;
2960  TableSampleClause *tsc;
2961 
2962  /* it should be a base rel with a tablesample clause... */
2963  Assert(scan_relid > 0);
2964  rte = planner_rt_fetch(scan_relid, root);
2965  Assert(rte->rtekind == RTE_RELATION);
2966  tsc = rte->tablesample;
2967  Assert(tsc != NULL);
2968 
2969  /* Sort clauses into best execution order */
2970  scan_clauses = order_qual_clauses(root, scan_clauses);
2971 
2972  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2973  scan_clauses = extract_actual_clauses(scan_clauses, false);
2974 
2975  /* Replace any outer-relation variables with nestloop params */
2976  if (best_path->param_info)
2977  {
2978  scan_clauses = (List *)
2979  replace_nestloop_params(root, (Node *) scan_clauses);
2980  tsc = (TableSampleClause *)
2981  replace_nestloop_params(root, (Node *) tsc);
2982  }
2983 
2984  scan_plan = make_samplescan(tlist,
2985  scan_clauses,
2986  scan_relid,
2987  tsc);
2988 
2989  copy_generic_path_info(&scan_plan->scan.plan, best_path);
2990 
2991  return scan_plan;
2992 }
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:5525
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:2916
static ValuesScan * create_valuesscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3846
static TableFuncScan * create_tablefuncscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3803
static CustomScan * create_customscan_plan(PlannerInfo *root, CustomPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4276
static ForeignScan * create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4121
static BitmapHeapScan * create_bitmap_scan_plan(PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3201
static TidScan * create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3539
static WorkTableScan * create_worktablescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4061
static FunctionScan * create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3760
static Result * create_resultscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:4024
static CteScan * create_ctescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3890
static NamedTuplestoreScan * create_namedtuplestorescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3985
static SubqueryScan * create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3701
static TidRangeScan * create_tidrangescan_plan(PlannerInfo *root, TidRangePath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3636
static SampleScan * create_samplescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2954
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:834
List * build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
Definition: plancat.c:1747

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 2916 of file createplan.c.

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

2720 {
2721  SetOp *plan;
2722  Plan *subplan;
2723  long numGroups;
2724 
2725  /*
2726  * SetOp doesn't project, so tlist requirements pass through; moreover we
2727  * need grouping columns to be labeled.
2728  */
2729  subplan = create_plan_recurse(root, best_path->subpath,
2730  flags | CP_LABEL_TLIST);
2731 
2732  /* Convert numGroups to long int --- but 'ware overflow! */
2733  numGroups = clamp_cardinality_to_long(best_path->numGroups);
2734 
2735  plan = make_setop(best_path->cmd,
2736  best_path->strategy,
2737  subplan,
2738  best_path->distinctList,
2739  best_path->flagColIdx,
2740  best_path->firstFlag,
2741  numGroups);
2742 
2743  copy_generic_path_info(&plan->plan, (Path *) best_path);
2744 
2745  return plan;
2746 }
static SetOp * make_setop(SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, List *distinctList, AttrNumber flagColIdx, int firstFlag, long numGroups)
Definition: createplan.c:6883
List * distinctList
Definition: pathnodes.h:2324
Cardinality numGroups
Definition: pathnodes.h:2327
int firstFlag
Definition: pathnodes.h:2326
Path * subpath
Definition: pathnodes.h:2321
SetOpCmd cmd
Definition: pathnodes.h:2322
SetOpStrategy strategy
Definition: pathnodes.h:2323
AttrNumber flagColIdx
Definition: pathnodes.h:2325

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 2180 of file createplan.c.

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

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 3701 of file createplan.c.

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

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 3803 of file createplan.c.

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

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

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 3539 of file createplan.c.

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

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

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 3846 of file createplan.c.

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

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

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

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 5063 of file createplan.c.

5064 {
5065  IndexOptInfo *index = index_path->indexinfo;
5066  List *fixed_indexorderbys;
5067  ListCell *lcc,
5068  *lci;
5069 
5070  fixed_indexorderbys = NIL;
5071 
5072  forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5073  {
5074  Node *clause = (Node *) lfirst(lcc);
5075  int indexcol = lfirst_int(lci);
5076 
5077  clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5078  fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5079  }
5080 
5081  return fixed_indexorderbys;
5082 }
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
Definition: createplan.c:5092
#define lfirst_int(lc)
Definition: pg_list.h:173
List * indexorderbycols
Definition: pathnodes.h:1702
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 5092 of file createplan.c.

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

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 5163 of file createplan.c.

5164 {
5165  Var *result;
5166  int pos;
5167  ListCell *indexpr_item;
5168 
5169  /*
5170  * Remove any binary-compatible relabeling of the indexkey
5171  */
5172  if (IsA(node, RelabelType))
5173  node = (Node *) ((RelabelType *) node)->arg;
5174 
5175  Assert(indexcol >= 0 && indexcol < index->ncolumns);
5176 
5177  if (index->indexkeys[indexcol] != 0)
5178  {
5179  /* It's a simple index column */
5180  if (IsA(node, Var) &&
5181  ((Var *) node)->varno == index->rel->relid &&
5182  ((Var *) node)->varattno == index->indexkeys[indexcol])
5183  {
5184  result = (Var *) copyObject(node);
5185  result->varno = INDEX_VAR;
5186  result->varattno = indexcol + 1;
5187  return (Node *) result;
5188  }
5189  else
5190  elog(ERROR, "index key does not match expected index column");
5191  }
5192 
5193  /* It's an index expression, so find and cross-check the expression */
5194  indexpr_item = list_head(index->indexprs);
5195  for (pos = 0; pos < index->ncolumns; pos++)
5196  {
5197  if (index->indexkeys[pos] == 0)
5198  {
5199  if (indexpr_item == NULL)
5200  elog(ERROR, "too few entries in indexprs list");
5201  if (pos == indexcol)
5202  {
5203  Node *indexkey;
5204 
5205  indexkey = (Node *) lfirst(indexpr_item);
5206  if (indexkey && IsA(indexkey, RelabelType))
5207  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5208  if (equal(node, indexkey))
5209  {
5210  result = makeVar(INDEX_VAR, indexcol + 1,
5211  exprType(lfirst(indexpr_item)), -1,
5212  exprCollation(lfirst(indexpr_item)),
5213  0);
5214  return (Node *) result;
5215  }
5216  else
5217  elog(ERROR, "index key does not match expected index column");
5218  }
5219  indexpr_item = lnext(index->indexprs, indexpr_item);
5220  }
5221  }
5222 
5223  /* Oops... */
5224  elog(ERROR, "index key does not match expected index column");
5225  return NULL; /* keep compiler quiet */
5226 }
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 5022 of file createplan.c.

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

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 5238 of file createplan.c.

5239 {
5240  List *t_list = NIL;
5241  ListCell *l;
5242 
5243  foreach(l, clauses)
5244  {
5245  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
5246  OpExpr *clause = (OpExpr *) restrictinfo->clause;
5247 
5248  Assert(is_opclause(clause));
5249  if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5250  {
5251  /*
5252  * Duplicate just enough of the structure to allow commuting the
5253  * clause without changing the original list. Could use
5254  * copyObject, but a complete deep copy is overkill.
5255  */
5256  OpExpr *temp = makeNode(OpExpr);
5257 
5258  temp->opno = clause->opno;
5259  temp->opfuncid = InvalidOid;
5260  temp->opresulttype = clause->opresulttype;
5261  temp->opretset = clause->opretset;
5262  temp->opcollid = clause->opcollid;
5263  temp->inputcollid = clause->inputcollid;
5264  temp->args = list_copy(clause->args);
5265  temp->location = clause->location;
5266  /* Commute it --- note this modifies the temp node in-place. */
5267  CommuteOpExpr(temp);
5268  t_list = lappend(t_list, temp);
5269  restrictinfo->outer_is_left = false;
5270  }
5271  else
5272  {
5273  Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5274  t_list = lappend(t_list, clause);
5275  restrictinfo->outer_is_left = true;
5276  }
5277  }
5278  return t_list;
5279 }
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:809

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 2120 of file createplan.c.

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

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 7207 of file createplan.c.

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

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 7257 of file createplan.c.

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

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 5446 of file createplan.c.

5447 {
5448  Plan *lefttree = plan->plan.lefttree;
5449  Path sort_path; /* dummy for result of cost_sort */
5450 
5451  /*
5452  * This function shouldn't have to deal with IncrementalSort plans because
5453  * they are only created from corresponding Path nodes.
5454  */
5455  Assert(IsA(plan, Sort));
5456 
5457  cost_sort(&sort_path, root, NIL,
5458  lefttree->total_cost,
5459  lefttree->plan_rows,
5460  lefttree->plan_width,
5461  0.0,
5462  work_mem,
5463  limit_tuples);
5464  plan->plan.startup_cost = sort_path.startup_cost;
5465  plan->plan.total_cost = sort_path.total_cost;
5466  plan->plan.plan_rows = lefttree->plan_rows;
5467  plan->plan.plan_width = lefttree->plan_width;
5468  plan->plan.parallel_aware = false;
5469  plan->plan.parallel_safe = lefttree->parallel_safe;
5470 }
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:2124
int work_mem
Definition: globals.c:128

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 6593 of file createplan.c.

6598 {
6599  Agg *node = makeNode(Agg);
6600  Plan *plan = &node->plan;
6601  long numGroups;
6602 
6603  /* Reduce to long, but 'ware overflow! */
6604  numGroups = clamp_cardinality_to_long(dNumGroups);
6605 
6606  node->aggstrategy = aggstrategy;
6607  node->aggsplit = aggsplit;
6608  node->numCols = numGroupCols;
6609  node->grpColIdx = grpColIdx;
6610  node->grpOperators = grpOperators;
6611  node->grpCollations = grpCollations;
6612  node->numGroups = numGroups;
6613  node->transitionSpace = transitionSpace;
6614  node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6615  node->groupingSets = groupingSets;
6616  node->chain = chain;
6617 
6618  plan->qual = qual;
6619  plan->targetlist = tlist;
6620  plan->lefttree = lefttree;
6621  plan->righttree = NULL;
6622 
6623  return node;
6624 }
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 5918 of file createplan.c.

5919 {
5920  BitmapAnd *node = makeNode(BitmapAnd);
5921  Plan *plan = &node->plan;
5922 
5923  plan->targetlist = NIL;
5924  plan->qual = NIL;
5925  plan->lefttree = NULL;
5926  plan->righttree = NULL;
5927  node->bitmapplans = bitmapplans;
5928 
5929  return node;
5930 }
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 5625 of file createplan.c.

5630 {
5632  Plan *plan = &node->scan.plan;
5633 
5634  plan->targetlist = qptlist;
5635  plan->qual = qpqual;
5636  plan->lefttree = lefttree;
5637  plan->righttree = NULL;
5638  node->scan.scanrelid = scanrelid;
5639  node->bitmapqualorig = bitmapqualorig;
5640 
5641  return node;
5642 }
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 5604 of file createplan.c.

5608 {
5610  Plan *plan = &node->scan.plan;
5611 
5612  plan->targetlist = NIL; /* not used */
5613  plan->qual = NIL; /* not used */
5614  plan->lefttree = NULL;
5615  plan->righttree = NULL;
5616  node->scan.scanrelid = scanrelid;
5617  node->indexid = indexid;
5618  node->indexqual = indexqual;
5619  node->indexqualorig = indexqualorig;
5620 
5621  return node;
5622 }
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 5933 of file createplan.c.

5934 {
5935  BitmapOr *node = makeNode(BitmapOr);
5936  Plan *plan = &node->plan;
5937 
5938  plan->targetlist = NIL;
5939  plan->qual = NIL;
5940  plan->lefttree = NULL;
5941  plan->righttree = NULL;
5942  node->bitmapplans = bitmapplans;
5943 
5944  return node;
5945 }
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 5762 of file createplan.c.

5767 {
5768  CteScan *node = makeNode(CteScan);
5769  Plan *plan = &node->scan.plan;
5770 
5771  plan->targetlist = qptlist;
5772  plan->qual = qpqual;
5773  plan->lefttree = NULL;
5774  plan->righttree = NULL;
5775  node->scan.scanrelid = scanrelid;
5776  node->ctePlanId = ctePlanId;
5777  node->cteParam = cteParam;
5778 
5779  return node;
5780 }
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 5822 of file createplan.c.

5830 {
5831  ForeignScan *node = makeNode(ForeignScan);
5832  Plan *plan = &node->scan.plan;
5833 
5834  /* cost will be filled in by create_foreignscan_plan */
5835  plan->targetlist = qptlist;
5836  plan->qual = qpqual;
5837  plan->lefttree = outer_plan;
5838  plan->righttree = NULL;
5839  node->scan.scanrelid = scanrelid;
5840 
5841  /* these may be overridden by the FDW's PlanDirectModify callback. */
5842  node->operation = CMD_SELECT;
5843  node->resultRelation = 0;
5844 
5845  /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5846  node->checkAsUser = InvalidOid;
5847  node->fs_server = InvalidOid;
5848  node->fdw_exprs = fdw_exprs;
5849  node->fdw_private = fdw_private;
5850  node->fdw_scan_tlist = fdw_scan_tlist;
5851  node->fdw_recheck_quals = fdw_recheck_quals;
5852  /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5853  node->fs_relids = NULL;
5854  node->fs_base_relids = NULL;
5855  /* fsSystemCol will be filled in by create_foreignscan_plan */
5856  node->fsSystemCol = false;
5857 
5858  return node;
5859 }
@ 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 5703 of file createplan.c.

5708 {
5710  Plan *plan = &node->scan.plan;
5711 
5712  plan->targetlist = qptlist;
5713  plan->qual = qpqual;
5714  plan->lefttree = NULL;
5715  plan->righttree = NULL;
5716  node->scan.scanrelid = scanrelid;
5717  node->functions = functions;
5718  node->funcordinality = funcordinality;
5719 
5720  return node;
5721 }
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 6854 of file createplan.c.

6860 {
6861  Gather *node = makeNode(Gather);
6862  Plan *plan = &node->plan;
6863 
6864  plan->targetlist = qptlist;
6865  plan->qual = qpqual;
6866  plan->lefttree = subplan;
6867  plan->righttree = NULL;
6868  node->num_workers = nworkers;
6869  node->rescan_param = rescan_param;
6870  node->single_copy = single_copy;
6871  node->invisible = false;
6872  node->initParam = NULL;
6873 
6874  return node;
6875 }
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 6669 of file createplan.c.

6676 {
6677  Group *node = makeNode(Group);
6678  Plan *plan = &node->plan;
6679 
6680  node->numCols = numGroupCols;
6681  node->grpColIdx = grpColIdx;
6682  node->grpOperators = grpOperators;
6683  node->grpCollations = grpCollations;
6684 
6685  plan->qual = qual;
6686  plan->targetlist = tlist;
6687  plan->lefttree = lefttree;
6688  plan->righttree = NULL;
6689 
6690  return node;
6691 }
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 6004 of file createplan.c.

6009 {
6010  Hash *node = makeNode(Hash);
6011  Plan *plan = &node->plan;
6012 
6013  plan->targetlist = lefttree->targetlist;
6014  plan->qual = NIL;
6015  plan->lefttree = lefttree;
6016  plan->righttree = NULL;
6017 
6018  node->hashkeys = hashkeys;
6019  node->skewTable = skewTable;
6020  node->skewColumn = skewColumn;
6021  node->skewInherit = skewInherit;
6022 
6023  return node;
6024 }
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 5973 of file createplan.c.

5984 {
5985  HashJoin *node = makeNode(HashJoin);
5986  Plan *plan = &node->join.plan;
5987 
5988  plan->targetlist = tlist;
5989  plan->qual = otherclauses;
5990  plan->lefttree = lefttree;
5991  plan->righttree = righttree;
5992  node->hashclauses = hashclauses;
5993  node->hashoperators = hashoperators;
5994  node->hashcollations = hashcollations;
5995  node->hashkeys = hashkeys;
5996  node->join.jointype = jointype;
5997  node->join.inner_unique = inner_unique;
5998  node->join.joinqual = joinclauses;
5999 
6000  return node;
6001 }
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 6098 of file createplan.c.

6101 {
6102  IncrementalSort *node;
6103  Plan *plan;
6104 
6105  node = makeNode(IncrementalSort);
6106 
6107  plan = &node->sort.plan;
6108  plan->targetlist = lefttree->targetlist;
6109  plan->qual = NIL;
6110  plan->lefttree = lefttree;
6111  plan->righttree = NULL;
6112  node->nPresortedCols = nPresortedCols;
6113  node->sort.numCols = numCols;
6114  node->sort.sortColIdx = sortColIdx;
6115  node->sort.sortOperators = sortOperators;
6116  node->sort.collations = collations;
6117  node->sort.nullsFirst = nullsFirst;
6118 
6119  return node;
6120 }
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 6381 of file createplan.c.

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

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 5575 of file createplan.c.

5584 {
5586  Plan *plan = &node->scan.plan;
5587 
5588  plan->targetlist = qptlist;
5589  plan->qual = qpqual;
5590  plan->lefttree = NULL;
5591  plan->righttree = NULL;
5592  node->scan.scanrelid = scanrelid;
5593  node->indexid = indexid;
5594  node->indexqual = indexqual;
5595  node->recheckqual = recheckqual;
5596  node->indexorderby = indexorderby;
5597  node->indextlist = indextlist;
5598  node->indexorderdir = indexscandir;
5599 
5600  return node;
5601 }
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 5544 of file createplan.c.

5554 {
5555  IndexScan *node = makeNode(IndexScan);
5556  Plan *plan = &node->scan.plan;
5557 
5558  plan->targetlist = qptlist;
5559  plan->qual = qpqual;
5560  plan->lefttree = NULL;
5561  plan->righttree = NULL;
5562  node->scan.scanrelid = scanrelid;
5563  node->indexid = indexid;
5564  node->indexqual = indexqual;
5565  node->indexqualorig = indexqualorig;
5566  node->indexorderby = indexorderby;
5567  node->indexorderbyorig = indexorderbyorig;
5568  node->indexorderbyops = indexorderbyops;
5569  node->indexorderdir = indexscandir;
5570 
5571  return node;
5572 }
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 6960 of file createplan.c.

6963 {
6964  Limit *node = makeNode(Limit);
6965  Plan *plan = &node->plan;
6966 
6967  plan->targetlist = lefttree->targetlist;
6968  plan->qual = NIL;
6969  plan->lefttree = lefttree;
6970  plan->righttree = NULL;
6971 
6972  node->limitOffset = limitOffset;
6973  node->limitCount = limitCount;
6974  node->limitOption = limitOption;
6975  node->uniqNumCols = uniqNumCols;
6976  node->uniqColIdx = uniqColIdx;
6977  node->uniqOperators = uniqOperators;
6978  node->uniqCollations = uniqCollations;
6979 
6980  return node;
6981 }
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 6939 of file createplan.c.

6940 {
6941  LockRows *node = makeNode(LockRows);
6942  Plan *plan = &node->plan;
6943 
6944  plan->targetlist = lefttree->targetlist;
6945  plan->qual = NIL;
6946  plan->lefttree = lefttree;
6947  plan->righttree = NULL;
6948 
6949  node->rowMarks = rowMarks;
6950  node->epqParam = epqParam;
6951 
6952  return node;
6953 }
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 6505 of file createplan.c.

6506 {
6507  Material *node = makeNode(Material);
6508  Plan *plan = &node->plan;
6509 
6510  plan->targetlist = lefttree->targetlist;
6511  plan->qual = NIL;
6512  plan->lefttree = lefttree;
6513  plan->righttree = NULL;
6514 
6515  return node;
6516 }
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 6568 of file createplan.c.

6571 {
6572  Memoize *node = makeNode(Memoize);
6573  Plan *plan = &node->plan;
6574 
6575  plan->targetlist = lefttree->targetlist;
6576  plan->qual = NIL;
6577  plan->lefttree = lefttree;
6578  plan->righttree = NULL;
6579 
6580  node->numKeys = list_length(param_exprs);
6581  node->hashOperators = hashoperators;
6582  node->collations = collations;
6583  node->param_exprs = param_exprs;
6584  node->singlerow = singlerow;
6585  node->binary_mode = binary_mode;
6586  node->est_entries = est_entries;
6587  node->keyparamids = keyparamids;
6588 
6589  return node;
6590 }
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 6027 of file createplan.c.

6040 {
6041  MergeJoin *node = makeNode(MergeJoin);
6042  Plan *plan = &node->join.plan;
6043 
6044  plan->targetlist = tlist;
6045  plan->qual = otherclauses;
6046  plan->lefttree = lefttree;
6047  plan->righttree = righttree;
6048  node->skip_mark_restore = skip_mark_restore;
6049  node->mergeclauses = mergeclauses;
6050  node->mergeFamilies = mergefamilies;
6051  node->mergeCollations = mergecollations;
6052  node->mergeStrategies = mergestrategies;
6053  node->mergeNullsFirst = mergenullsfirst;
6054  node->join.jointype = jointype;
6055  node->join.inner_unique = inner_unique;
6056  node->join.joinqual = joinclauses;
6057 
6058  return node;
6059 }
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 7028 of file createplan.c.

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

5787 {
5789  Plan *plan = &node->scan.plan;
5790 
5791  /* cost should be inserted by caller */
5792  plan->targetlist = qptlist;
5793  plan->qual = qpqual;
5794  plan->lefttree = NULL;
5795  plan->righttree = NULL;
5796  node->scan.scanrelid = scanrelid;
5797  node->enrname = enrname;
5798 
5799  return node;
5800 }

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 5948 of file createplan.c.

5956 {
5957  NestLoop *node = makeNode(NestLoop);
5958  Plan *plan = &node->join.plan;
5959 
5960  plan->targetlist = tlist;
5961  plan->qual = otherclauses;
5962  plan->lefttree = lefttree;
5963  plan->righttree = righttree;
5964  node->join.jointype = jointype;
5965  node->join.inner_unique = inner_unique;
5966  node->join.joinqual = joinclauses;
5967  node->nestParams = nestParams;
5968 
5969  return node;
5970 }
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 7009 of file createplan.c.

7011 {
7012  ProjectSet *node = makeNode(ProjectSet);
7013  Plan *plan = &node->plan;
7014 
7015  plan->targetlist = tlist;
7016  plan->qual = NIL;
7017  plan->lefttree = subplan;
7018  plan->righttree = NULL;
7019 
7020  return node;
7021 }
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 5862 of file createplan.c.

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

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 6988 of file createplan.c.

6991 {
6992  Result *node = makeNode(Result);
6993  Plan *plan = &node->plan;
6994 
6995  plan->targetlist = tlist;
6996  plan->qual = NIL;
6997  plan->lefttree = subplan;
6998  plan->righttree = NULL;
6999  node->resconstantqual = resconstantqual;
7000 
7001  return node;
7002 }

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 5525 of file createplan.c.

5529 {
5530  SampleScan *node = makeNode(SampleScan);
5531  Plan *plan = &node->scan.plan;
5532 
5533  plan->targetlist = qptlist;
5534  plan->qual = qpqual;
5535  plan->lefttree = NULL;
5536  plan->righttree = NULL;
5537  node->scan.scanrelid = scanrelid;
5538  node->tablesample = tsc;
5539 
5540  return node;
5541 }
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 5508 of file createplan.c.

5511 {
5512  SeqScan *node = makeNode(SeqScan);
5513  Plan *plan = &node->scan.plan;
5514 
5515  plan->targetlist = qptlist;
5516  plan->qual = qpqual;
5517  plan->lefttree = NULL;
5518  plan->righttree = NULL;
5519  node->scan.scanrelid = scanrelid;
5520 
5521  return node;
5522 }

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 6883 of file createplan.c.

6886 {
6887  SetOp *node = makeNode(SetOp);
6888  Plan *plan = &node->plan;
6889  int numCols = list_length(distinctList);
6890  int keyno = 0;
6891  AttrNumber *dupColIdx;
6892  Oid *dupOperators;
6893  Oid *dupCollations;
6894  ListCell *slitem;
6895 
6896  plan->targetlist = lefttree->targetlist;
6897  plan->qual = NIL;
6898  plan->lefttree = lefttree;
6899  plan->righttree = NULL;
6900 
6901  /*
6902  * convert SortGroupClause list into arrays of attr indexes and equality
6903  * operators, as wanted by executor
6904  */
6905  dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6906  dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6907  dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6908 
6909  foreach(slitem, distinctList)
6910  {
6911  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6912  TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6913 
6914  dupColIdx[keyno] = tle->resno;
6915  dupOperators[keyno] = sortcl->eqop;
6916  dupCollations[keyno] = exprCollation((Node *) tle->expr);
6917  Assert(OidIsValid(dupOperators[keyno]));
6918  keyno++;
6919  }
6920 
6921  node->cmd = cmd;
6922  node->strategy = strategy;
6923  node->numCols = numCols;
6924  node->dupColIdx = dupColIdx;
6925  node->dupOperators = dupOperators;
6926  node->dupCollations = dupCollations;
6927  node->flagColIdx = flagColIdx;
6928  node->firstFlag = firstFlag;
6929  node->numGroups = numGroups;
6930 
6931  return node;
6932 }
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 6068 of file createplan.c.

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

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 6464 of file createplan.c.

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

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 6346 of file createplan.c.

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

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 6415 of file createplan.c.

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

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 5683 of file createplan.c.

5687 {
5689  Plan *plan = &node->scan.plan;
5690 
5691  plan->targetlist = qptlist;
5692  plan->qual = qpqual;
5693  plan->lefttree = NULL;
5694  plan->righttree = NULL;
5695  node->scan.scanrelid = scanrelid;
5696  node->subplan = subplan;
5698 
5699  return node;
5700 }
@ 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 5724 of file createplan.c.

5728 {
5730  Plan *plan = &node->scan.plan;
5731 
5732  plan->targetlist = qptlist;
5733  plan->qual = qpqual;
5734  plan->lefttree = NULL;
5735  plan->righttree = NULL;
5736  node->scan.scanrelid = scanrelid;
5737  node->tablefunc = tablefunc;
5738 
5739  return node;
5740 }
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 5664 of file createplan.c.

5668 {
5670  Plan *plan = &node->scan.plan;
5671 
5672  plan->targetlist = qptlist;
5673  plan->qual = qpqual;
5674  plan->lefttree = NULL;
5675  plan->righttree = NULL;
5676  node->scan.scanrelid = scanrelid;
5677  node->tidrangequals = tidrangequals;
5678 
5679  return node;
5680 }
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 5645 of file createplan.c.

5649 {
5650  TidScan *node = makeNode(TidScan);
5651  Plan *plan = &node->scan.plan;
5652 
5653  plan->targetlist = qptlist;
5654  plan->qual = qpqual;
5655  plan->lefttree = NULL;
5656  plan->righttree = NULL;
5657  node->scan.scanrelid = scanrelid;
5658  node->tidquals = tidquals;
5659 
5660  return node;
5661 }
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 6748 of file createplan.c.

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

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

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 5743 of file createplan.c.

5747 {
5748  ValuesScan *node = makeNode(ValuesScan);
5749  Plan *plan = &node->scan.plan;
5750 
5751  plan->targetlist = qptlist;
5752  plan->qual = qpqual;
5753  plan->lefttree = NULL;
5754  plan->righttree = NULL;
5755  node->scan.scanrelid = scanrelid;
5756  node->values_lists = values_lists;
5757 
5758  return node;
5759 }
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 6627 of file createplan.c.

6634 {
6635  WindowAgg *node = makeNode(WindowAgg);
6636  Plan *plan = &node->plan;
6637 
6638  node->winref = winref;
6639  node->partNumCols = partNumCols;
6640  node->partColIdx = partColIdx;
6641  node->partOperators = partOperators;
6642  node->partCollations = partCollations;
6643  node->ordNumCols = ordNumCols;
6644  node->ordColIdx = ordColIdx;
6645  node->ordOperators = ordOperators;
6646  node->ordCollations = ordCollations;
6647  node->frameOptions = frameOptions;
6648  node->startOffset = startOffset;
6649  node->endOffset = endOffset;
6650  node->runCondition = runCondition;
6651  /* a duplicate of the above for EXPLAIN */
6652  node->runConditionOrig = runCondition;
6653  node->startInRangeFunc = startInRangeFunc;
6654  node->endInRangeFunc = endInRangeFunc;
6655  node->inRangeColl = inRangeColl;
6656  node->inRangeAsc = inRangeAsc;
6657  node->inRangeNullsFirst = inRangeNullsFirst;
6658  node->topWindow = topWindow;
6659 
6660  plan->targetlist = tlist;
6661  plan->lefttree = lefttree;
6662  plan->righttree = NULL;
6663  plan->qual = qual;
6664 
6665  return node;
6666 }
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 5803 of file createplan.c.

5807 {
5809  Plan *plan = &node->scan.plan;
5810 
5811  plan->targetlist = qptlist;
5812  plan->qual = qpqual;
5813  plan->lefttree = NULL;
5814  plan->righttree = NULL;
5815  node->scan.scanrelid = scanrelid;
5816  node->wtParam = wtParam;
5817 
5818  return node;
5819 }

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 6527 of file createplan.c.

6528 {
6529  Plan *matplan;
6530  Path matpath; /* dummy for result of cost_material */
6531  Cost initplan_cost;
6532  bool unsafe_initplans;
6533 
6534  matplan = (Plan *) make_material(subplan);
6535 
6536  /*
6537  * XXX horrid kluge: if there are any initPlans attached to the subplan,
6538  * move them up to the Material node, which is now effectively the top
6539  * plan node in its query level. This prevents failure in
6540  * SS_finalize_plan(), which see for comments.
6541  */
6542  matplan->initPlan = subplan->initPlan;
6543  subplan->initPlan = NIL;
6544 
6545  /* Move the initplans' cost delta, as well */
6547  &initplan_cost, &unsafe_initplans);
6548  subplan->startup_cost -= initplan_cost;
6549  subplan->total_cost -= initplan_cost;
6550 
6551  /* Set cost data */
6552  cost_material(&matpath,
6553  subplan->startup_cost,
6554  subplan->total_cost,
6555  subplan->plan_rows,
6556  subplan->plan_width);
6557  matplan->startup_cost = matpath.startup_cost + initplan_cost;
6558  matplan->total_cost = matpath.total_cost + initplan_cost;
6559  matplan->plan_rows = subplan->plan_rows;
6560  matplan->plan_width = subplan->plan_width;
6561  matplan->parallel_aware = false;
6562  matplan->parallel_safe = subplan->parallel_safe;
6563 
6564  return matplan;
6565 }
void cost_material(Path *path, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition: costsize.c:2453
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 5315 of file createplan.c.

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

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

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 2354 of file createplan.c.

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

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 4942 of file createplan.c.

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

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().