PostgreSQL Source Code  git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 "tcop/tcopprot.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 void label_incrementalsort_with_costsize (PlannerInfo *root, IncrementalSort *plan, List *pathkeys, 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, bool *mergereversals, 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 70 of file createplan.c.

◆ CP_IGNORE_TLIST

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

Definition at line 73 of file createplan.c.

◆ CP_LABEL_TLIST

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

Definition at line 72 of file createplan.c.

◆ CP_SMALL_TLIST

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

Definition at line 71 of file createplan.c.

Function Documentation

◆ bitmap_subplan_mark_shared()

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 5552 of file createplan.c.

5553 {
5554  if (IsA(plan, BitmapAnd))
5555  bitmap_subplan_mark_shared(linitial(((BitmapAnd *) plan)->bitmapplans));
5556  else if (IsA(plan, BitmapOr))
5557  {
5558  ((BitmapOr *) plan)->isshared = true;
5559  bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5560  }
5561  else if (IsA(plan, BitmapIndexScan))
5562  ((BitmapIndexScan *) plan)->isshared = true;
5563  else
5564  elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5565 }
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:5552
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#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:161

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

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

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

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

5454 {
5455  dest->disabled_nodes = src->disabled_nodes;
5456  dest->startup_cost = src->startup_cost;
5457  dest->total_cost = src->total_cost;
5458  dest->plan_rows = src->rows;
5459  dest->plan_width = src->pathtarget->width;
5460  dest->parallel_aware = src->parallel_aware;
5461  dest->parallel_safe = src->parallel_safe;
5462 }
Cardinality rows
Definition: pathnodes.h:1669
Cost startup_cost
Definition: pathnodes.h:1671
int disabled_nodes
Definition: pathnodes.h:1670
Cost total_cost
Definition: pathnodes.h:1672
bool parallel_aware
Definition: pathnodes.h:1662
bool parallel_safe
Definition: pathnodes.h:1664

References generate_unaccent_rules::dest, Path::disabled_nodes, 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 5469 of file createplan.c.

5470 {
5471  dest->disabled_nodes = src->disabled_nodes;
5472  dest->startup_cost = src->startup_cost;
5473  dest->total_cost = src->total_cost;
5474  dest->plan_rows = src->plan_rows;
5475  dest->plan_width = src->plan_width;
5476  /* Assume the inserted node is not parallel-aware. */
5477  dest->parallel_aware = false;
5478  /* Assume the inserted node is parallel-safe, if child plan is. */
5479  dest->parallel_safe = src->parallel_safe;
5480 }
Cost total_cost
Definition: plannodes.h:130
Cost startup_cost
Definition: plannodes.h:129
int plan_width
Definition: plannodes.h:136
Cardinality plan_rows
Definition: plannodes.h:135
int disabled_nodes
Definition: plannodes.h:128

References generate_unaccent_rules::dest, Plan::disabled_nodes, 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 2307 of file createplan.c.

2308 {
2309  Agg *plan;
2310  Plan *subplan;
2311  List *tlist;
2312  List *quals;
2313 
2314  /*
2315  * Agg can project, so no need to be terribly picky about child tlist, but
2316  * we do need grouping columns to be available
2317  */
2318  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2319 
2320  tlist = build_path_tlist(root, &best_path->path);
2321 
2322  quals = order_qual_clauses(root, best_path->qual);
2323 
2324  plan = make_agg(tlist, quals,
2325  best_path->aggstrategy,
2326  best_path->aggsplit,
2327  list_length(best_path->groupClause),
2329  subplan->targetlist),
2330  extract_grouping_ops(best_path->groupClause),
2332  subplan->targetlist),
2333  NIL,
2334  NIL,
2335  best_path->numGroups,
2336  best_path->transitionSpace,
2337  subplan);
2338 
2339  copy_generic_path_info(&plan->plan, (Path *) best_path);
2340 
2341  return plan;
2342 }
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:5359
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:6670
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5453
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:391
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:828
#define CP_LABEL_TLIST
Definition: createplan.c:72
static int list_length(const List *l)
Definition: pg_list.h:152
Path * subpath
Definition: pathnodes.h:2264
Cardinality numGroups
Definition: pathnodes.h:2267
AggSplit aggsplit
Definition: pathnodes.h:2266
List * groupClause
Definition: pathnodes.h:2269
uint64 transitionSpace
Definition: pathnodes.h:2268
AggStrategy aggstrategy
Definition: pathnodes.h:2265
Path path
Definition: pathnodes.h:2263
List * qual
Definition: pathnodes.h:2270
Definition: plannodes.h:998
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 1219 of file createplan.c.

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

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:5699
if(TABLE==NULL||TABLE_index==NULL)
Definition: isn.c:76
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:1017
#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:1795
Expr * clause
Definition: pathnodes.h:2574

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:213
static BitmapOr * make_bitmap_or(List *bitmapplans)
Definition: createplan.c:6007
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
Definition: createplan.c:5678
static BitmapAnd * make_bitmap_and(List *bitmapplans)
Definition: createplan.c:5992
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:749
Expr * make_orclause(List *orclauses)
Definition: makefuncs.c:693
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:460
Selectivity bitmapselectivity
Definition: pathnodes.h:1808
List * bitmapquals
Definition: pathnodes.h:1807
Selectivity bitmapselectivity
Definition: pathnodes.h:1821
List * bitmapquals
Definition: pathnodes.h:1820
List * indexquals
Definition: pathnodes.h:1769
struct RestrictInfo * rinfo
Definition: pathnodes.h:1768
List * indpred
Definition: pathnodes.h:1174
List * indexclauses
Definition: pathnodes.h:1721
Path path
Definition: pathnodes.h:1719
Selectivity indexselectivity
Definition: pathnodes.h:1726
Cost indextotalcost
Definition: pathnodes.h:1725
IndexOptInfo * indexinfo
Definition: pathnodes.h:1720
Scan scan
Definition: plannodes.h:452
List * indexqualorig
Definition: plannodes.h:455
Oid indexid
Definition: plannodes.h:453
List * indexqual
Definition: plannodes.h:454
Index scanrelid
Definition: plannodes.h:390

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:5836
@ RTE_CTE
Definition: parsenodes.h:1023
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:570
#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:643
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:168
char * ctename
Definition: parsenodes.h:1196
Index ctelevelsup
Definition: parsenodes.h:1198
RTEKind rtekind
Definition: parsenodes.h:1047
int plan_id
Definition: primnodes.h:1070
List * setParam
Definition: primnodes.h:1088

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

Referenced by create_scan_plan().

◆ create_customscan_plan()

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

Definition at line 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:1921
List * custom_paths
Definition: pathnodes.h:1918
Scan scan
Definition: plannodes.h:742
Bitmapset * custom_relids
Definition: plannodes.h:749
List * custom_exprs
Definition: plannodes.h:746

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:72
@ RELOPT_UPPER_REL
Definition: pathnodes.h:831
#define InvalidOid
Definition: postgres_ext.h:36
Path * fdw_outerpath
Definition: pathnodes.h:1880
Oid checkAsUser
Definition: plannodes.h:713
Oid fs_server
Definition: plannodes.h:715
List * fdw_exprs
Definition: plannodes.h:716
bool fsSystemCol
Definition: plannodes.h:722
Bitmapset * fs_relids
Definition: plannodes.h:720
Bitmapset * fs_base_relids
Definition: plannodes.h:721
List * fdw_recheck_quals
Definition: plannodes.h:719
List * exprs
Definition: pathnodes.h:1542
bool useridiscurrent
Definition: pathnodes.h:968
struct PathTarget * reltarget
Definition: pathnodes.h:893
Index relid
Definition: pathnodes.h:918
RelOptKind reloptkind
Definition: pathnodes.h:865
Oid userid
Definition: pathnodes.h:966
Oid serverid
Definition: pathnodes.h:964
RTEKind rtekind
Definition: pathnodes.h:922
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:27
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:296

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:5777
@ RTE_FUNCTION
Definition: parsenodes.h:1020
static const struct fns functions
Definition: regcomp.c:358
bool funcordinality
Definition: parsenodes.h:1179
List * functions
Definition: parsenodes.h:1177

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

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

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

Referenced by create_plan_recurse().

◆ create_gather_plan()

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

Definition at line 1923 of file createplan.c.

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

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

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

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

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

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

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

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

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

4792 {
4793  HashJoin *join_plan;
4794  Hash *hash_plan;
4795  Plan *outer_plan;
4796  Plan *inner_plan;
4797  List *tlist = build_path_tlist(root, &best_path->jpath.path);
4798  List *joinclauses;
4799  List *otherclauses;
4800  List *hashclauses;
4801  List *hashoperators = NIL;
4802  List *hashcollations = NIL;
4803  List *inner_hashkeys = NIL;
4804  List *outer_hashkeys = NIL;
4805  Oid skewTable = InvalidOid;
4806  AttrNumber skewColumn = InvalidAttrNumber;
4807  bool skewInherit = false;
4808  ListCell *lc;
4809 
4810  /*
4811  * HashJoin can project, so we don't have to demand exact tlists from the
4812  * inputs. However, it's best to request a small tlist from the inner
4813  * side, so that we aren't storing more data than necessary. Likewise, if
4814  * we anticipate batching, request a small tlist from the outer side so
4815  * that we don't put extra data in the outer batch files.
4816  */
4817  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4818  (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
4819 
4820  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4821  CP_SMALL_TLIST);
4822 
4823  /* Sort join qual clauses into best execution order */
4824  joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4825  /* There's no point in sorting the hash clauses ... */
4826 
4827  /* Get the join qual clauses (in plain expression form) */
4828  /* Any pseudoconstant clauses are ignored here */
4829  if (IS_OUTER_JOIN(best_path->jpath.jointype))
4830  {
4831  extract_actual_join_clauses(joinclauses,
4832  best_path->jpath.path.parent->relids,
4833  &joinclauses, &otherclauses);
4834  }
4835  else
4836  {
4837  /* We can treat all clauses alike for an inner join */
4838  joinclauses = extract_actual_clauses(joinclauses, false);
4839  otherclauses = NIL;
4840  }
4841 
4842  /*
4843  * Remove the hashclauses from the list of join qual clauses, leaving the
4844  * list of quals that must be checked as qpquals.
4845  */
4846  hashclauses = get_actual_clauses(best_path->path_hashclauses);
4847  joinclauses = list_difference(joinclauses, hashclauses);
4848 
4849  /*
4850  * Replace any outer-relation variables with nestloop params. There
4851  * should not be any in the hashclauses.
4852  */
4853  if (best_path->jpath.path.param_info)
4854  {
4855  joinclauses = (List *)
4856  replace_nestloop_params(root, (Node *) joinclauses);
4857  otherclauses = (List *)
4858  replace_nestloop_params(root, (Node *) otherclauses);
4859  }
4860 
4861  /*
4862  * Rearrange hashclauses, if needed, so that the outer variable is always
4863  * on the left.
4864  */
4865  hashclauses = get_switched_clauses(best_path->path_hashclauses,
4866  best_path->jpath.outerjoinpath->parent->relids);
4867 
4868  /*
4869  * If there is a single join clause and we can identify the outer variable
4870  * as a simple column reference, supply its identity for possible use in
4871  * skew optimization. (Note: in principle we could do skew optimization
4872  * with multiple join clauses, but we'd have to be able to determine the
4873  * most common combinations of outer values, which we don't currently have
4874  * enough stats for.)
4875  */
4876  if (list_length(hashclauses) == 1)
4877  {
4878  OpExpr *clause = (OpExpr *) linitial(hashclauses);
4879  Node *node;
4880 
4881  Assert(is_opclause(clause));
4882  node = (Node *) linitial(clause->args);
4883  if (IsA(node, RelabelType))
4884  node = (Node *) ((RelabelType *) node)->arg;
4885  if (IsA(node, Var))
4886  {
4887  Var *var = (Var *) node;
4888  RangeTblEntry *rte;
4889 
4890  rte = root->simple_rte_array[var->varno];
4891  if (rte->rtekind == RTE_RELATION)
4892  {
4893  skewTable = rte->relid;
4894  skewColumn = var->varattno;
4895  skewInherit = rte->inh;
4896  }
4897  }
4898  }
4899 
4900  /*
4901  * Collect hash related information. The hashed expressions are
4902  * deconstructed into outer/inner expressions, so they can be computed
4903  * separately (inner expressions are used to build the hashtable via Hash,
4904  * outer expressions to perform lookups of tuples from HashJoin's outer
4905  * plan in the hashtable). Also collect operator information necessary to
4906  * build the hashtable.
4907  */
4908  foreach(lc, hashclauses)
4909  {
4910  OpExpr *hclause = lfirst_node(OpExpr, lc);
4911 
4912  hashoperators = lappend_oid(hashoperators, hclause->opno);
4913  hashcollations = lappend_oid(hashcollations, hclause->inputcollid);
4914  outer_hashkeys = lappend(outer_hashkeys, linitial(hclause->args));
4915  inner_hashkeys = lappend(inner_hashkeys, lsecond(hclause->args));
4916  }
4917 
4918  /*
4919  * Build the hash node and hash join node.
4920  */
4921  hash_plan = make_hash(inner_plan,
4922  inner_hashkeys,
4923  skewTable,
4924  skewColumn,
4925  skewInherit);
4926 
4927  /*
4928  * Set Hash node's startup & total costs equal to total cost of input
4929  * plan; this only affects EXPLAIN display not decisions.
4930  */
4931  copy_plan_costsize(&hash_plan->plan, inner_plan);
4932  hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
4933 
4934  /*
4935  * If parallel-aware, the executor will also need an estimate of the total
4936  * number of rows expected from all participants so that it can size the
4937  * shared hash table.
4938  */
4939  if (best_path->jpath.path.parallel_aware)
4940  {
4941  hash_plan->plan.parallel_aware = true;
4942  hash_plan->rows_total = best_path->inner_rows_total;
4943  }
4944 
4945  join_plan = make_hashjoin(tlist,
4946  joinclauses,
4947  otherclauses,
4948  hashclauses,
4949  hashoperators,
4950  hashcollations,
4951  outer_hashkeys,
4952  outer_plan,
4953  (Plan *) hash_plan,
4954  best_path->jpath.jointype,
4955  best_path->jpath.inner_unique);
4956 
4957  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4958 
4959  return join_plan;
4960 }
#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:6047
static List * get_switched_clauses(List *clauses, Relids outerrelids)
Definition: createplan.c:5282
static Hash * make_hash(Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
Definition: createplan.c:6078
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:76
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:338
#define lsecond(l)
Definition: pg_list.h:183
void extract_actual_join_clauses(List *restrictinfo_list, Relids joinrelids, List **joinquals, List **otherquals)
Definition: restrictinfo.c:513
Join join
Definition: plannodes.h:865
List * path_hashclauses
Definition: pathnodes.h:2162
Cardinality inner_rows_total
Definition: pathnodes.h:2164
int num_batches
Definition: pathnodes.h:2163
JoinPath jpath
Definition: pathnodes.h:2161
Cardinality rows_total
Definition: plannodes.h:1211
Plan plan
Definition: plannodes.h:1200
Path * outerjoinpath
Definition: pathnodes.h:2084
Path * innerjoinpath
Definition: pathnodes.h:2085
JoinType jointype
Definition: pathnodes.h:2079
bool inner_unique
Definition: pathnodes.h:2081
List * joinrestrictinfo
Definition: pathnodes.h:2087
Oid opno
Definition: primnodes.h:818
List * args
Definition: primnodes.h:836
bool parallel_aware
Definition: plannodes.h:141
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 2213 of file createplan.c.

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

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:780
static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
Definition: createplan.c:5066
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:5107
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:5649
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:5618
bool is_redundant_with_indexclauses(RestrictInfo *rinfo, List *indexclauses)
Definition: equivclass.c:3351
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:1177
ScanDirection indexscandir
Definition: pathnodes.h:1724
List * indexorderbys
Definition: pathnodes.h:1722
int pk_strategy
Definition: pathnodes.h:1479
Oid pk_opfamily
Definition: pathnodes.h:1478

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

1085 {
1086  Plan *plan;
1087  List *gating_clauses;
1088 
1089  switch (best_path->path.pathtype)
1090  {
1091  case T_MergeJoin:
1093  (MergePath *) best_path);
1094  break;
1095  case T_HashJoin:
1097  (HashPath *) best_path);
1098  break;
1099  case T_NestLoop:
1101  (NestPath *) best_path);
1102  break;
1103  default:
1104  elog(ERROR, "unrecognized node type: %d",
1105  (int) best_path->path.pathtype);
1106  plan = NULL; /* keep compiler quiet */
1107  break;
1108  }
1109 
1110  /*
1111  * If there are any pseudoconstant clauses attached to this node, insert a
1112  * gating Result node that evaluates the pseudoconstants as one-time
1113  * quals.
1114  */
1115  gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
1116  if (gating_clauses)
1117  plan = create_gating_plan(root, (Path *) best_path, plan,
1118  gating_clauses);
1119 
1120 #ifdef NOT_USED
1121 
1122  /*
1123  * * Expensive function pullups may have pulled local predicates * into
1124  * this path node. Put them in the qpqual of the plan node. * JMH,
1125  * 6/15/92
1126  */
1127  if (get_loc_restrictinfo(best_path) != NIL)
1128  set_qpqual((Plan) plan,
1129  list_concat(get_qpqual((Plan) plan),
1130  get_actual_clauses(get_loc_restrictinfo(best_path))));
1131 #endif
1132 
1133  return plan;
1134 }
static HashJoin * create_hashjoin_plan(PlannerInfo *root, HashPath *best_path)
Definition: createplan.c:4790
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:1025
static List * get_gating_quals(PlannerInfo *root, List *quals)
Definition: createplan.c:1005
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:7037
void * palloc(Size size)
Definition: mcxt.c:1317
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:816
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:432
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
Path * subpath
Definition: pathnodes.h:2411
LimitOption limitOption
Definition: pathnodes.h:2414
Node * limitOffset
Definition: pathnodes.h:2412
Node * limitCount
Definition: pathnodes.h:2413
Expr * expr
Definition: primnodes.h:2190

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:7016
Path * subpath
Definition: pathnodes.h:2371
List * rowMarks
Definition: pathnodes.h:2372

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

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

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

1670 {
1671  Memoize *plan;
1672  Bitmapset *keyparamids;
1673  Plan *subplan;
1674  Oid *operators;
1675  Oid *collations;
1676  List *param_exprs = NIL;
1677  ListCell *lc;
1678  ListCell *lc2;
1679  int nkeys;
1680  int i;
1681 
1682  subplan = create_plan_recurse(root, best_path->subpath,
1683  flags | CP_SMALL_TLIST);
1684 
1685  param_exprs = (List *) replace_nestloop_params(root, (Node *)
1686  best_path->param_exprs);
1687 
1688  nkeys = list_length(param_exprs);
1689  Assert(nkeys > 0);
1690  operators = palloc(nkeys * sizeof(Oid));
1691  collations = palloc(nkeys * sizeof(Oid));
1692 
1693  i = 0;
1694  forboth(lc, param_exprs, lc2, best_path->hash_operators)
1695  {
1696  Expr *param_expr = (Expr *) lfirst(lc);
1697  Oid opno = lfirst_oid(lc2);
1698 
1699  operators[i] = opno;
1700  collations[i] = exprCollation((Node *) param_expr);
1701  i++;
1702  }
1703 
1704  keyparamids = pull_paramids((Expr *) param_exprs);
1705 
1706  plan = make_memoize(subplan, operators, collations, param_exprs,
1707  best_path->singlerow, best_path->binary_mode,
1708  best_path->est_entries, keyparamids);
1709 
1710  copy_generic_path_info(&plan->plan, (Path *) best_path);
1711 
1712  return plan;
1713 }
Bitmapset * pull_paramids(Expr *expr)
Definition: clauses.c:5418
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:6645
#define lfirst_oid(lc)
Definition: pg_list.h:174
bool singlerow
Definition: pathnodes.h:2006
List * hash_operators
Definition: pathnodes.h:2004
uint32 est_entries
Definition: pathnodes.h:2011
bool binary_mode
Definition: pathnodes.h:2008
Path * subpath
Definition: pathnodes.h:2003
List * param_exprs
Definition: pathnodes.h:2005

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

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

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  bool *mergereversals;
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  Plan *sort_plan;
4530  bool use_incremental_sort = false;
4531  int presorted_keys;
4532 
4533  /*
4534  * We choose to use incremental sort if it is enabled and there are
4535  * presorted keys; otherwise we use full sort.
4536  */
4538  {
4539  bool is_sorted PG_USED_FOR_ASSERTS_ONLY;
4540 
4541  is_sorted = pathkeys_count_contained_in(best_path->outersortkeys,
4542  outer_path->pathkeys,
4543  &presorted_keys);
4544  Assert(!is_sorted);
4545 
4546  if (presorted_keys > 0)
4547  use_incremental_sort = true;
4548  }
4549 
4550  if (!use_incremental_sort)
4551  {
4552  sort_plan = (Plan *)
4553  make_sort_from_pathkeys(outer_plan,
4554  best_path->outersortkeys,
4555  outer_relids);
4556 
4557  label_sort_with_costsize(root, (Sort *) sort_plan, -1.0);
4558  }
4559  else
4560  {
4561  sort_plan = (Plan *)
4563  best_path->outersortkeys,
4564  outer_relids,
4565  presorted_keys);
4566 
4568  (IncrementalSort *) sort_plan,
4569  best_path->outersortkeys,
4570  -1.0);
4571  }
4572 
4573  outer_plan = sort_plan;
4574  outerpathkeys = best_path->outersortkeys;
4575  }
4576  else
4577  outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
4578 
4579  if (best_path->innersortkeys)
4580  {
4581  /*
4582  * We do not consider incremental sort for inner path, because
4583  * incremental sort does not support mark/restore.
4584  */
4585 
4586  Relids inner_relids = inner_path->parent->relids;
4587  Sort *sort = make_sort_from_pathkeys(inner_plan,
4588  best_path->innersortkeys,
4589  inner_relids);
4590 
4592  inner_plan = (Plan *) sort;
4593  innerpathkeys = best_path->innersortkeys;
4594  }
4595  else
4596  innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
4597 
4598  /*
4599  * If specified, add a materialize node to shield the inner plan from the
4600  * need to handle mark/restore.
4601  */
4602  if (best_path->materialize_inner)
4603  {
4604  Plan *matplan = (Plan *) make_material(inner_plan);
4605 
4606  /*
4607  * We assume the materialize will not spill to disk, and therefore
4608  * charge just cpu_operator_cost per tuple. (Keep this estimate in
4609  * sync with final_cost_mergejoin.)
4610  */
4611  copy_plan_costsize(matplan, inner_plan);
4612  matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
4613 
4614  inner_plan = matplan;
4615  }
4616 
4617  /*
4618  * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
4619  * executor. The information is in the pathkeys for the two inputs, but
4620  * we need to be careful about the possibility of mergeclauses sharing a
4621  * pathkey, as well as the possibility that the inner pathkeys are not in
4622  * an order matching the mergeclauses.
4623  */
4624  nClauses = list_length(mergeclauses);
4625  Assert(nClauses == list_length(best_path->path_mergeclauses));
4626  mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
4627  mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
4628  mergereversals = (bool *) palloc(nClauses * sizeof(bool));
4629  mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
4630 
4631  opathkey = NULL;
4632  opeclass = NULL;
4633  lop = list_head(outerpathkeys);
4634  lip = list_head(innerpathkeys);
4635  i = 0;
4636  foreach(lc, best_path->path_mergeclauses)
4637  {
4638  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc);
4639  EquivalenceClass *oeclass;
4640  EquivalenceClass *ieclass;
4641  PathKey *ipathkey = NULL;
4642  EquivalenceClass *ipeclass = NULL;
4643  bool first_inner_match = false;
4644 
4645  /* fetch outer/inner eclass from mergeclause */
4646  if (rinfo->outer_is_left)
4647  {
4648  oeclass = rinfo->left_ec;
4649  ieclass = rinfo->right_ec;
4650  }
4651  else
4652  {
4653  oeclass = rinfo->right_ec;
4654  ieclass = rinfo->left_ec;
4655  }
4656  Assert(oeclass != NULL);
4657  Assert(ieclass != NULL);
4658 
4659  /*
4660  * We must identify the pathkey elements associated with this clause
4661  * by matching the eclasses (which should give a unique match, since
4662  * the pathkey lists should be canonical). In typical cases the merge
4663  * clauses are one-to-one with the pathkeys, but when dealing with
4664  * partially redundant query conditions, things are more complicated.
4665  *
4666  * lop and lip reference the first as-yet-unmatched pathkey elements.
4667  * If they're NULL then all pathkey elements have been matched.
4668  *
4669  * The ordering of the outer pathkeys should match the mergeclauses,
4670  * by construction (see find_mergeclauses_for_outer_pathkeys()). There
4671  * could be more than one mergeclause for the same outer pathkey, but
4672  * no pathkey may be entirely skipped over.
4673  */
4674  if (oeclass != opeclass) /* multiple matches are not interesting */
4675  {
4676  /* doesn't match the current opathkey, so must match the next */
4677  if (lop == NULL)
4678  elog(ERROR, "outer pathkeys do not match mergeclauses");
4679  opathkey = (PathKey *) lfirst(lop);
4680  opeclass = opathkey->pk_eclass;
4681  lop = lnext(outerpathkeys, lop);
4682  if (oeclass != opeclass)
4683  elog(ERROR, "outer pathkeys do not match mergeclauses");
4684  }
4685 
4686  /*
4687  * The inner pathkeys likewise should not have skipped-over keys, but
4688  * it's possible for a mergeclause to reference some earlier inner
4689  * pathkey if we had redundant pathkeys. For example we might have
4690  * mergeclauses like "o.a = i.x AND o.b = i.y AND o.c = i.x". The
4691  * implied inner ordering is then "ORDER BY x, y, x", but the pathkey
4692  * mechanism drops the second sort by x as redundant, and this code
4693  * must cope.
4694  *
4695  * It's also possible for the implied inner-rel ordering to be like
4696  * "ORDER BY x, y, x DESC". We still drop the second instance of x as
4697  * redundant; but this means that the sort ordering of a redundant
4698  * inner pathkey should not be considered significant. So we must
4699  * detect whether this is the first clause matching an inner pathkey.
4700  */
4701  if (lip)
4702  {
4703  ipathkey = (PathKey *) lfirst(lip);
4704  ipeclass = ipathkey->pk_eclass;
4705  if (ieclass == ipeclass)
4706  {
4707  /* successful first match to this inner pathkey */
4708  lip = lnext(innerpathkeys, lip);
4709  first_inner_match = true;
4710  }
4711  }
4712  if (!first_inner_match)
4713  {
4714  /* redundant clause ... must match something before lip */
4715  ListCell *l2;
4716 
4717  foreach(l2, innerpathkeys)
4718  {
4719  if (l2 == lip)
4720  break;
4721  ipathkey = (PathKey *) lfirst(l2);
4722  ipeclass = ipathkey->pk_eclass;
4723  if (ieclass == ipeclass)
4724  break;
4725  }
4726  if (ieclass != ipeclass)
4727  elog(ERROR, "inner pathkeys do not match mergeclauses");
4728  }
4729 
4730  /*
4731  * The pathkeys should always match each other as to opfamily and
4732  * collation (which affect equality), but if we're considering a
4733  * redundant inner pathkey, its sort ordering might not match. In
4734  * such cases we may ignore the inner pathkey's sort ordering and use
4735  * the outer's. (In effect, we're lying to the executor about the
4736  * sort direction of this inner column, but it does not matter since
4737  * the run-time row comparisons would only reach this column when
4738  * there's equality for the earlier column containing the same eclass.
4739  * There could be only one value in this column for the range of inner
4740  * rows having a given value in the earlier column, so it does not
4741  * matter which way we imagine this column to be ordered.) But a
4742  * non-redundant inner pathkey had better match outer's ordering too.
4743  */
4744  if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
4745  opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
4746  elog(ERROR, "left and right pathkeys do not match in mergejoin");
4747  if (first_inner_match &&
4748  (opathkey->pk_strategy != ipathkey->pk_strategy ||
4749  opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
4750  elog(ERROR, "left and right pathkeys do not match in mergejoin");
4751 
4752  /* OK, save info for executor */
4753  mergefamilies[i] = opathkey->pk_opfamily;
4754  mergecollations[i] = opathkey->pk_eclass->ec_collation;
4755  mergereversals[i] = (opathkey->pk_strategy == BTGreaterStrategyNumber ? true : false);
4756  mergenullsfirst[i] = opathkey->pk_nulls_first;
4757  i++;
4758  }
4759 
4760  /*
4761  * Note: it is not an error if we have additional pathkey elements (i.e.,
4762  * lop or lip isn't NULL here). The input paths might be better-sorted
4763  * than we need for the current mergejoin.
4764  */
4765 
4766  /*
4767  * Now we can build the mergejoin node.
4768  */
4769  join_plan = make_mergejoin(tlist,
4770  joinclauses,
4771  otherclauses,
4772  mergeclauses,
4773  mergefamilies,
4774  mergecollations,
4775  mergereversals,
4776  mergenullsfirst,
4777  outer_plan,
4778  inner_plan,
4779  best_path->jpath.jointype,
4780  best_path->jpath.inner_unique,
4781  best_path->skip_mark_restore);
4782 
4783  /* Costs of sort and material steps are included in path cost already */
4784  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4785 
4786  return join_plan;
4787 }
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:197
double cpu_operator_cost
Definition: costsize.c:134
bool enable_incremental_sort
Definition: costsize.c:151
static MergeJoin * make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, bool *mergereversals, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, bool skip_mark_restore)
Definition: createplan.c:6101
static Sort * make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
Definition: createplan.c:6421
static void label_incrementalsort_with_costsize(PlannerInfo *root, IncrementalSort *plan, List *pathkeys, double limit_tuples)
Definition: createplan.c:5520
return true
Definition: isn.c:125
bool pathkeys_count_contained_in(List *keys1, List *keys2, int *n_common)
Definition: pathkeys.c:558
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
#define BTGreaterStrategyNumber
Definition: stratnum.h:33
Join join
Definition: plannodes.h:836
List * outersortkeys
Definition: pathnodes.h:2144
bool skip_mark_restore
Definition: pathnodes.h:2146
List * innersortkeys
Definition: pathnodes.h:2145
JoinPath jpath
Definition: pathnodes.h:2142
bool materialize_inner
Definition: pathnodes.h:2147
List * path_mergeclauses
Definition: pathnodes.h:2143
bool pk_nulls_first
Definition: pathnodes.h:1480

References Assert, BTGreaterStrategyNumber, build_path_tlist(), copy_generic_path_info(), copy_plan_costsize(), CP_SMALL_TLIST, cpu_operator_cost, create_plan_recurse(), elog, enable_incremental_sort, 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_incrementalsort_with_costsize(), label_sort_with_costsize(), lfirst, lfirst_node, list_difference(), list_head(), list_length(), lnext(), make_incrementalsort_from_pathkeys(), 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, pathkeys_count_contained_in(), PG_USED_FOR_ASSERTS_ONLY, PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, Plan::plan_rows, replace_nestloop_params(), root, MergePath::skip_mark_restore, sort(), Plan::total_cost, and true.

Referenced by create_join_plan().

◆ create_minmaxagg_plan()

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

Definition at line 2549 of file createplan.c.

2550 {
2551  Result *plan;
2552  List *tlist;
2553  ListCell *lc;
2554 
2555  /* Prepare an InitPlan for each aggregate's subquery. */
2556  foreach(lc, best_path->mmaggregates)
2557  {
2558  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2559  PlannerInfo *subroot = mminfo->subroot;
2560  Query *subparse = subroot->parse;
2561  Plan *plan;
2562 
2563  /*
2564  * Generate the plan for the subquery. We already have a Path, but we
2565  * have to convert it to a Plan and attach a LIMIT node above it.
2566  * Since we are entering a different planner context (subroot),
2567  * recurse to create_plan not create_plan_recurse.
2568  */
2569  plan = create_plan(subroot, mminfo->path);
2570 
2571  plan = (Plan *) make_limit(plan,
2572  subparse->limitOffset,
2573  subparse->limitCount,
2574  subparse->limitOption,
2575  0, NULL, NULL, NULL);
2576 
2577  /* Must apply correct cost/width data to Limit node */
2578  plan->disabled_nodes = mminfo->path->disabled_nodes;
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:340
Param * param
Definition: pathnodes.h:3143
List * quals
Definition: pathnodes.h:2320
List * mmaggregates
Definition: pathnodes.h:2319
Node * limitCount
Definition: parsenodes.h:216
Node * limitOffset
Definition: parsenodes.h:215
LimitOption limitOption
Definition: parsenodes.h:217
void SS_make_initplan_from_plan(PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
Definition: subselect.c:3041

References Assert, build_path_tlist(), copy_generic_path_info(), create_plan(), Path::disabled_nodes, 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:7105
bool partColsUpdated
Definition: pathnodes.h:2391
List * returningLists
Definition: pathnodes.h:2395
List * resultRelations
Definition: pathnodes.h:2392
List * withCheckOptionLists
Definition: pathnodes.h:2394
List * mergeJoinConditions
Definition: pathnodes.h:2401
List * updateColnosLists
Definition: pathnodes.h:2393
OnConflictExpr * onconflict
Definition: pathnodes.h:2397
CmdType operation
Definition: pathnodes.h:2387
Index rootRelation
Definition: pathnodes.h:2390
Index nominalRelation
Definition: pathnodes.h:2389
List * mergeActionLists
Definition: pathnodes.h:2399
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:5857
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1024
char * enrname
Definition: parsenodes.h:1231

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:6022
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:4212
Join join
Definition: plannodes.h:810
JoinPath jpath
Definition: pathnodes.h:2102

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

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

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

392 {
393  Plan *plan;
394 
395  /* Guard against stack overflow due to overly complex plans */
397 
398  switch (best_path->pathtype)
399  {
400  case T_SeqScan:
401  case T_SampleScan:
402  case T_IndexScan:
403  case T_IndexOnlyScan:
404  case T_BitmapHeapScan:
405  case T_TidScan:
406  case T_TidRangeScan:
407  case T_SubqueryScan:
408  case T_FunctionScan:
409  case T_TableFuncScan:
410  case T_ValuesScan:
411  case T_CteScan:
412  case T_WorkTableScan:
413  case T_NamedTuplestoreScan:
414  case T_ForeignScan:
415  case T_CustomScan:
416  plan = create_scan_plan(root, best_path, flags);
417  break;
418  case T_HashJoin:
419  case T_MergeJoin:
420  case T_NestLoop:
422  (JoinPath *) best_path);
423  break;
424  case T_Append:
426  (AppendPath *) best_path,
427  flags);
428  break;
429  case T_MergeAppend:
431  (MergeAppendPath *) best_path,
432  flags);
433  break;
434  case T_Result:
435  if (IsA(best_path, ProjectionPath))
436  {
438  (ProjectionPath *) best_path,
439  flags);
440  }
441  else if (IsA(best_path, MinMaxAggPath))
442  {
444  (MinMaxAggPath *) best_path);
445  }
446  else if (IsA(best_path, GroupResultPath))
447  {
449  (GroupResultPath *) best_path);
450  }
451  else
452  {
453  /* Simple RTE_RESULT base relation */
454  Assert(IsA(best_path, Path));
455  plan = create_scan_plan(root, best_path, flags);
456  }
457  break;
458  case T_ProjectSet:
460  (ProjectSetPath *) best_path);
461  break;
462  case T_Material:
464  (MaterialPath *) best_path,
465  flags);
466  break;
467  case T_Memoize:
469  (MemoizePath *) best_path,
470  flags);
471  break;
472  case T_Unique:
473  if (IsA(best_path, UpperUniquePath))
474  {
476  (UpperUniquePath *) best_path,
477  flags);
478  }
479  else
480  {
481  Assert(IsA(best_path, UniquePath));
483  (UniquePath *) best_path,
484  flags);
485  }
486  break;
487  case T_Gather:
489  (GatherPath *) best_path);
490  break;
491  case T_Sort:
493  (SortPath *) best_path,
494  flags);
495  break;
496  case T_IncrementalSort:
498  (IncrementalSortPath *) best_path,
499  flags);
500  break;
501  case T_Group:
503  (GroupPath *) best_path);
504  break;
505  case T_Agg:
506  if (IsA(best_path, GroupingSetsPath))
508  (GroupingSetsPath *) best_path);
509  else
510  {
511  Assert(IsA(best_path, AggPath));
513  (AggPath *) best_path);
514  }
515  break;
516  case T_WindowAgg:
518  (WindowAggPath *) best_path);
519  break;
520  case T_SetOp:
522  (SetOpPath *) best_path,
523  flags);
524  break;
525  case T_RecursiveUnion:
527  (RecursiveUnionPath *) best_path);
528  break;
529  case T_LockRows:
531  (LockRowsPath *) best_path,
532  flags);
533  break;
534  case T_ModifyTable:
536  (ModifyTablePath *) best_path);
537  break;
538  case T_Limit:
540  (LimitPath *) best_path,
541  flags);
542  break;
543  case T_GatherMerge:
545  (GatherMergePath *) best_path);
546  break;
547  default:
548  elog(ERROR, "unrecognized node type: %d",
549  (int) best_path->pathtype);
550  plan = NULL; /* keep compiler quiet */
551  break;
552  }
553 
554  return plan;
555 }
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
Definition: createplan.c:1084
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, int flags)
Definition: createplan.c:1440
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
Definition: createplan.c:1961
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
Definition: createplan.c:1219
static Result * create_group_result_plan(PlannerInfo *root, GroupResultPath *best_path)
Definition: createplan.c:1590
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:2307
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:2179
static Unique * create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
Definition: createplan.c:2279
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
Definition: createplan.c:1923
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
Definition: createplan.c:1615
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
Definition: createplan.c:2240
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:2549
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:1641
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:562
static IncrementalSort * create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path, int flags)
Definition: createplan.c:2213
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
Definition: createplan.c:2017
static Memoize * create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
Definition: createplan.c:1669
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:2391
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:1723
void check_stack_depth(void)
Definition: postgres.c:3563
NodeTag pathtype
Definition: pathnodes.h:1635

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

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

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

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

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 }
@ RTE_RESULT
Definition: parsenodes.h:1025

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:5599
struct TableSampleClause * tablesample
Definition: parsenodes.h:1098
Scan scan
Definition: plannodes.h:408

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

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

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:5582
Scan scan
Definition: plannodes.h:399

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:6960
List * distinctList
Definition: pathnodes.h:2346
Cardinality numGroups
Definition: pathnodes.h:2349
int firstFlag
Definition: pathnodes.h:2348
Path * subpath
Definition: pathnodes.h:2343
SetOpCmd cmd
Definition: pathnodes.h:2344
SetOpStrategy strategy
Definition: pathnodes.h:2345
AttrNumber flagColIdx
Definition: pathnodes.h:2347

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

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

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:5757
void process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
Definition: paramassign.c:480
@ RTE_SUBQUERY
Definition: parsenodes.h:1018
List * subplan_params
Definition: pathnodes.h:954
PlannerInfo * subroot
Definition: pathnodes.h:953

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:5798
@ RTE_TABLEFUNC
Definition: parsenodes.h:1021
TableFunc * tablefunc
Definition: parsenodes.h:1184

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:5738
List * tidrangequals
Definition: pathnodes.h:1846

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:5719
bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)
Definition: equivclass.c:3324
List * tidquals
Definition: pathnodes.h:1834
Path path
Definition: pathnodes.h:1833
Scan scan
Definition: plannodes.h:555

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

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

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

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:5817
@ RTE_VALUES
Definition: parsenodes.h:1022
List * values_lists
Definition: parsenodes.h:1190
Scan scan
Definition: plannodes.h:623

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  best_path->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:6704
List * runCondition
Definition: pathnodes.h:2332
Path * subpath
Definition: pathnodes.h:2329
WindowClause * winclause
Definition: pathnodes.h:2330
Node * startOffset
Definition: parsenodes.h:1547
List * partitionClause
Definition: parsenodes.h:1543
Node * endOffset
Definition: parsenodes.h:1548
List * orderClause
Definition: parsenodes.h:1545

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

Referenced by create_plan_recurse().

◆ create_worktablescan_plan()

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

Definition at line 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:5877
int wt_param_id
Definition: pathnodes.h:536

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

5108 {
5109  IndexOptInfo *index = index_path->indexinfo;
5110  List *fixed_indexorderbys;
5111  ListCell *lcc,
5112  *lci;
5113 
5114  fixed_indexorderbys = NIL;
5115 
5116  forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5117  {
5118  Node *clause = (Node *) lfirst(lcc);
5119  int indexcol = lfirst_int(lci);
5120 
5121  clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5122  fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5123  }
5124 
5125  return fixed_indexorderbys;
5126 }
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
Definition: createplan.c:5136
#define lfirst_int(lc)
Definition: pg_list.h:173
List * indexorderbycols
Definition: pathnodes.h:1723
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 5136 of file createplan.c.

5138 {
5139  /*
5140  * Replace any outer-relation variables with nestloop params.
5141  *
5142  * This also makes a copy of the clause, so it's safe to modify it
5143  * in-place below.
5144  */
5145  clause = replace_nestloop_params(root, clause);
5146 
5147  if (IsA(clause, OpExpr))
5148  {
5149  OpExpr *op = (OpExpr *) clause;
5150 
5151  /* Replace the indexkey expression with an index Var. */
5153  index,
5154  indexcol);
5155  }
5156  else if (IsA(clause, RowCompareExpr))
5157  {
5158  RowCompareExpr *rc = (RowCompareExpr *) clause;
5159  ListCell *lca,
5160  *lcai;
5161 
5162  /* Replace the indexkey expressions with index Vars. */
5163  Assert(list_length(rc->largs) == list_length(indexcolnos));
5164  forboth(lca, rc->largs, lcai, indexcolnos)
5165  {
5167  index,
5168  lfirst_int(lcai));
5169  }
5170  }
5171  else if (IsA(clause, ScalarArrayOpExpr))
5172  {
5173  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5174 
5175  /* Replace the indexkey expression with an index Var. */
5177  index,
5178  indexcol);
5179  }
5180  else if (IsA(clause, NullTest))
5181  {
5182  NullTest *nt = (NullTest *) clause;
5183 
5184  /* Replace the indexkey expression with an index Var. */
5185  nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5186  index,
5187  indexcol);
5188  }
5189  else
5190  elog(ERROR, "unsupported indexqual type: %d",
5191  (int) nodeTag(clause));
5192 
5193  return clause;
5194 }
static Node * fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
Definition: createplan.c:5207
Datum lca(PG_FUNCTION_ARGS)
Definition: ltree_op.c:568
Expr * arg
Definition: primnodes.h:1958

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

5208 {
5209  Var *result;
5210  int pos;
5211  ListCell *indexpr_item;
5212 
5213  /*
5214  * Remove any binary-compatible relabeling of the indexkey
5215  */
5216  if (IsA(node, RelabelType))
5217  node = (Node *) ((RelabelType *) node)->arg;
5218 
5219  Assert(indexcol >= 0 && indexcol < index->ncolumns);
5220 
5221  if (index->indexkeys[indexcol] != 0)
5222  {
5223  /* It's a simple index column */
5224  if (IsA(node, Var) &&
5225  ((Var *) node)->varno == index->rel->relid &&
5226  ((Var *) node)->varattno == index->indexkeys[indexcol])
5227  {
5228  result = (Var *) copyObject(node);
5229  result->varno = INDEX_VAR;
5230  result->varattno = indexcol + 1;
5231  return (Node *) result;
5232  }
5233  else
5234  elog(ERROR, "index key does not match expected index column");
5235  }
5236 
5237  /* It's an index expression, so find and cross-check the expression */
5238  indexpr_item = list_head(index->indexprs);
5239  for (pos = 0; pos < index->ncolumns; pos++)
5240  {
5241  if (index->indexkeys[pos] == 0)
5242  {
5243  if (indexpr_item == NULL)
5244  elog(ERROR, "too few entries in indexprs list");
5245  if (pos == indexcol)
5246  {
5247  Node *indexkey;
5248 
5249  indexkey = (Node *) lfirst(indexpr_item);
5250  if (indexkey && IsA(indexkey, RelabelType))
5251  indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5252  if (equal(node, indexkey))
5253  {
5254  result = makeVar(INDEX_VAR, indexcol + 1,
5255  exprType(lfirst(indexpr_item)), -1,
5256  exprCollation(lfirst(indexpr_item)),
5257  0);
5258  return (Node *) result;
5259  }
5260  else
5261  elog(ERROR, "index key does not match expected index column");
5262  }
5263  indexpr_item = lnext(index->indexprs, indexpr_item);
5264  }
5265  }
5266 
5267  /* Oops... */
5268  elog(ERROR, "index key does not match expected index column");
5269  return NULL; /* keep compiler quiet */
5270 }
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 5066 of file createplan.c.

5068 {
5069  IndexOptInfo *index = index_path->indexinfo;
5070  List *stripped_indexquals;
5071  List *fixed_indexquals;
5072  ListCell *lc;
5073 
5074  stripped_indexquals = fixed_indexquals = NIL;
5075 
5076  foreach(lc, index_path->indexclauses)
5077  {
5078  IndexClause *iclause = lfirst_node(IndexClause, lc);
5079  int indexcol = iclause->indexcol;
5080  ListCell *lc2;
5081 
5082  foreach(lc2, iclause->indexquals)
5083  {
5084  RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
5085  Node *clause = (Node *) rinfo->clause;
5086 
5087  stripped_indexquals = lappend(stripped_indexquals, clause);
5088  clause = fix_indexqual_clause(root, index, indexcol,
5089  clause, iclause->indexcols);
5090  fixed_indexquals = lappend(fixed_indexquals, clause);
5091  }
5092  }
5093 
5094  *stripped_indexquals_p = stripped_indexquals;
5095  *fixed_indexquals_p = fixed_indexquals;
5096 }
AttrNumber indexcol
Definition: pathnodes.h:1771
List * indexcols
Definition: pathnodes.h:1772

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

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

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

5283 {
5284  List *t_list = NIL;
5285  ListCell *l;
5286 
5287  foreach(l, clauses)
5288  {
5289  RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
5290  OpExpr *clause = (OpExpr *) restrictinfo->clause;
5291 
5292  Assert(is_opclause(clause));
5293  if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5294  {
5295  /*
5296  * Duplicate just enough of the structure to allow commuting the
5297  * clause without changing the original list. Could use
5298  * copyObject, but a complete deep copy is overkill.
5299  */
5300  OpExpr *temp = makeNode(OpExpr);
5301 
5302  temp->opno = clause->opno;
5303  temp->opfuncid = InvalidOid;
5304  temp->opresulttype = clause->opresulttype;
5305  temp->opretset = clause->opretset;
5306  temp->opcollid = clause->opcollid;
5307  temp->inputcollid = clause->inputcollid;
5308  temp->args = list_copy(clause->args);
5309  temp->location = clause->location;
5310  /* Commute it --- note this modifies the temp node in-place. */
5311  CommuteOpExpr(temp);
5312  t_list = lappend(t_list, temp);
5313  restrictinfo->outer_is_left = false;
5314  }
5315  else
5316  {
5317  Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5318  t_list = lappend(t_list, clause);
5319  restrictinfo->outer_is_left = true;
5320  }
5321  }
5322  return t_list;
5323 }
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:412
void CommuteOpExpr(OpExpr *clause)
Definition: clauses.c:2147
List * list_copy(const List *oldlist)
Definition: list.c:1573
ParseLoc location
Definition: primnodes.h:839

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

Referenced by create_hashjoin_plan(), and create_mergejoin_plan().

◆ inject_projection_plan()

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

Definition at line 2119 of file createplan.c.

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

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

7297 {
7298  /* Most plan types can project, so just list the ones that can't */
7299  switch (path->pathtype)
7300  {
7301  case T_Hash:
7302  case T_Material:
7303  case T_Memoize:
7304  case T_Sort:
7305  case T_IncrementalSort:
7306  case T_Unique:
7307  case T_SetOp:
7308  case T_LockRows:
7309  case T_Limit:
7310  case T_ModifyTable:
7311  case T_MergeAppend:
7312  case T_RecursiveUnion:
7313  return false;
7314  case T_CustomScan:
7316  return true;
7317  return false;
7318  case T_Append:
7319 
7320  /*
7321  * Append can't project, but if an AppendPath is being used to
7322  * represent a dummy path, what will actually be generated is a
7323  * Result which can project.
7324  */
7325  return IS_DUMMY_APPEND(path);
7326  case T_ProjectSet:
7327 
7328  /*
7329  * Although ProjectSet certainly projects, say "no" because we
7330  * don't want the planner to randomly replace its tlist with
7331  * something else; the SRFs have to stay at top level. This might
7332  * get relaxed later.
7333  */
7334  return false;
7335  default:
7336  break;
7337  }
7338  return true;
7339 }
#define CUSTOMPATH_SUPPORT_PROJECTION
Definition: extensible.h:86
#define IS_DUMMY_APPEND(p)
Definition: pathnodes.h:1948

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

7347 {
7348  /* Most plan types can project, so just list the ones that can't */
7349  switch (nodeTag(plan))
7350  {
7351  case T_Hash:
7352  case T_Material:
7353  case T_Memoize:
7354  case T_Sort:
7355  case T_Unique:
7356  case T_SetOp:
7357  case T_LockRows:
7358  case T_Limit:
7359  case T_ModifyTable:
7360  case T_Append:
7361  case T_MergeAppend:
7362  case T_RecursiveUnion:
7363  return false;
7364  case T_CustomScan:
7365  if (((CustomScan *) plan)->flags & CUSTOMPATH_SUPPORT_PROJECTION)
7366  return true;
7367  return false;
7368  case T_ProjectSet:
7369 
7370  /*
7371  * Although ProjectSet certainly projects, say "no" because we
7372  * don't want the planner to randomly replace its tlist with
7373  * something else; the SRFs have to stay at top level. This might
7374  * get relaxed later.
7375  */
7376  return false;
7377  default:
7378  break;
7379  }
7380  return true;
7381 }

References CUSTOMPATH_SUPPORT_PROJECTION, nodeTag, and plan.

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

◆ label_incrementalsort_with_costsize()

static void label_incrementalsort_with_costsize ( PlannerInfo root,
IncrementalSort plan,
List pathkeys,
double  limit_tuples 
)
static

Definition at line 5520 of file createplan.c.

5522 {
5523  Plan *lefttree = plan->sort.plan.lefttree;
5524  Path sort_path; /* dummy for result of cost_incremental_sort */
5525 
5527 
5528  cost_incremental_sort(&sort_path, root, pathkeys,
5529  plan->nPresortedCols,
5530  plan->sort.plan.disabled_nodes,
5531  lefttree->startup_cost,
5532  lefttree->total_cost,
5533  lefttree->plan_rows,
5534  lefttree->plan_width,
5535  0.0,
5536  work_mem,
5537  limit_tuples);
5538  plan->sort.plan.startup_cost = sort_path.startup_cost;
5539  plan->sort.plan.total_cost = sort_path.total_cost;
5540  plan->sort.plan.plan_rows = lefttree->plan_rows;
5541  plan->sort.plan.plan_width = lefttree->plan_width;
5542  plan->sort.plan.parallel_aware = false;
5543  plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5544 }
void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2000
int work_mem
Definition: globals.c:130

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

Referenced by create_mergejoin_plan().

◆ label_sort_with_costsize()

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

Definition at line 5492 of file createplan.c.

5493 {
5494  Plan *lefttree = plan->plan.lefttree;
5495  Path sort_path; /* dummy for result of cost_sort */
5496 
5497  Assert(IsA(plan, Sort));
5498 
5499  cost_sort(&sort_path, root, NIL,
5500  plan->plan.disabled_nodes,
5501  lefttree->total_cost,
5502  lefttree->plan_rows,
5503  lefttree->plan_width,
5504  0.0,
5505  work_mem,
5506  limit_tuples);
5507  plan->plan.startup_cost = sort_path.startup_cost;
5508  plan->plan.total_cost = sort_path.total_cost;
5509  plan->plan.plan_rows = lefttree->plan_rows;
5510  plan->plan.plan_width = lefttree->plan_width;
5511  plan->plan.parallel_aware = false;
5512  plan->plan.parallel_safe = lefttree->parallel_safe;
5513 }
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, int input_disabled_nodes, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2144

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

6675 {
6676  Agg *node = makeNode(Agg);
6677  Plan *plan = &node->plan;
6678  long numGroups;
6679 
6680  /* Reduce to long, but 'ware overflow! */
6681  numGroups = clamp_cardinality_to_long(dNumGroups);
6682 
6683  node->aggstrategy = aggstrategy;
6684  node->aggsplit = aggsplit;
6685  node->numCols = numGroupCols;
6686  node->grpColIdx = grpColIdx;
6687  node->grpOperators = grpOperators;
6688  node->grpCollations = grpCollations;
6689  node->numGroups = numGroups;
6690  node->transitionSpace = transitionSpace;
6691  node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6692  node->groupingSets = groupingSets;
6693  node->chain = chain;
6694 
6695  plan->qual = qual;
6696  plan->targetlist = tlist;
6697  plan->lefttree = lefttree;
6698  plan->righttree = NULL;
6699 
6700  return node;
6701 }
AggSplit aggsplit
Definition: plannodes.h:1005
List * chain
Definition: plannodes.h:1032
long numGroups
Definition: plannodes.h:1018
List * groupingSets
Definition: plannodes.h:1029
Bitmapset * aggParams
Definition: plannodes.h:1024
Plan plan
Definition: plannodes.h:999
int numCols
Definition: plannodes.h:1008
uint64 transitionSpace
Definition: plannodes.h:1021
AggStrategy aggstrategy
Definition: plannodes.h:1002

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

5993 {
5994  BitmapAnd *node = makeNode(BitmapAnd);
5995  Plan *plan = &node->plan;
5996 
5997  plan->targetlist = NIL;
5998  plan->qual = NIL;
5999  plan->lefttree = NULL;
6000  plan->righttree = NULL;
6001  node->bitmapplans = bitmapplans;
6002 
6003  return node;
6004 }
Plan plan
Definition: plannodes.h:359
List * bitmapplans
Definition: plannodes.h:360

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

5704 {
5706  Plan *plan = &node->scan.plan;
5707 
5708  plan->targetlist = qptlist;
5709  plan->qual = qpqual;
5710  plan->lefttree = lefttree;
5711  plan->righttree = NULL;
5712  node->scan.scanrelid = scanrelid;
5713  node->bitmapqualorig = bitmapqualorig;
5714 
5715  return node;
5716 }
List * bitmapqualorig
Definition: plannodes.h:542

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

5682 {
5684  Plan *plan = &node->scan.plan;
5685 
5686  plan->targetlist = NIL; /* not used */
5687  plan->qual = NIL; /* not used */
5688  plan->lefttree = NULL;
5689  plan->righttree = NULL;
5690  node->scan.scanrelid = scanrelid;
5691  node->indexid = indexid;
5692  node->indexqual = indexqual;
5693  node->indexqualorig = indexqualorig;
5694 
5695  return node;
5696 }
List * indexqualorig
Definition: plannodes.h:527
List * indexqual
Definition: plannodes.h:526

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

6008 {
6009  BitmapOr *node = makeNode(BitmapOr);
6010  Plan *plan = &node->plan;
6011 
6012  plan->targetlist = NIL;
6013  plan->qual = NIL;
6014  plan->lefttree = NULL;
6015  plan->righttree = NULL;
6016  node->bitmapplans = bitmapplans;
6017 
6018  return node;
6019 }
List * bitmapplans
Definition: plannodes.h:375
Plan plan
Definition: plannodes.h:373

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

5841 {
5842  CteScan *node = makeNode(CteScan);
5843  Plan *plan = &node->scan.plan;
5844 
5845  plan->targetlist = qptlist;
5846  plan->qual = qpqual;
5847  plan->lefttree = NULL;
5848  plan->righttree = NULL;
5849  node->scan.scanrelid = scanrelid;
5850  node->ctePlanId = ctePlanId;
5851  node->cteParam = cteParam;
5852 
5853  return node;
5854 }
int ctePlanId
Definition: plannodes.h:644
int cteParam
Definition: plannodes.h:645

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

5904 {
5905  ForeignScan *node = makeNode(ForeignScan);
5906  Plan *plan = &node->scan.plan;
5907 
5908  /* cost will be filled in by create_foreignscan_plan */
5909  plan->targetlist = qptlist;
5910  plan->qual = qpqual;
5911  plan->lefttree = outer_plan;
5912  plan->righttree = NULL;
5913  node->scan.scanrelid = scanrelid;
5914 
5915  /* these may be overridden by the FDW's PlanDirectModify callback. */
5916  node->operation = CMD_SELECT;
5917  node->resultRelation = 0;
5918 
5919  /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5920  node->checkAsUser = InvalidOid;
5921  node->fs_server = InvalidOid;
5922  node->fdw_exprs = fdw_exprs;
5923  node->fdw_private = fdw_private;
5924  node->fdw_scan_tlist = fdw_scan_tlist;
5925  node->fdw_recheck_quals = fdw_recheck_quals;
5926  /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5927  node->fs_relids = NULL;
5928  node->fs_base_relids = NULL;
5929  /* fsSystemCol will be filled in by create_foreignscan_plan */
5930  node->fsSystemCol = false;
5931 
5932  return node;
5933 }
@ CMD_SELECT
Definition: nodes.h:265
CmdType operation
Definition: plannodes.h:711
List * fdw_private
Definition: plannodes.h:717
Index resultRelation
Definition: plannodes.h:712
List * fdw_scan_tlist
Definition: plannodes.h:718

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

5782 {
5784  Plan *plan = &node->scan.plan;
5785 
5786  plan->targetlist = qptlist;
5787  plan->qual = qpqual;
5788  plan->lefttree = NULL;
5789  plan->righttree = NULL;
5790  node->scan.scanrelid = scanrelid;
5791  node->functions = functions;
5792  node->funcordinality = funcordinality;
5793 
5794  return node;
5795 }
List * functions
Definition: plannodes.h:613
bool funcordinality
Definition: plannodes.h:614

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

6937 {
6938  Gather *node = makeNode(Gather);
6939  Plan *plan = &node->plan;
6940 
6941  plan->targetlist = qptlist;
6942  plan->qual = qpqual;
6943  plan->lefttree = subplan;
6944  plan->righttree = NULL;
6945  node->num_workers = nworkers;
6946  node->rescan_param = rescan_param;
6947  node->single_copy = single_copy;
6948  node->invisible = false;
6949  node->initParam = NULL;
6950 
6951  return node;
6952 }
int num_workers
Definition: plannodes.h:1144
bool invisible
Definition: plannodes.h:1147
Bitmapset * initParam
Definition: plannodes.h:1148
bool single_copy
Definition: plannodes.h:1146
int rescan_param
Definition: plannodes.h:1145

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

6753 {
6754  Group *node = makeNode(Group);
6755  Plan *plan = &node->plan;
6756 
6757  node->numCols = numGroupCols;
6758  node->grpColIdx = grpColIdx;
6759  node->grpOperators = grpOperators;
6760  node->grpCollations = grpCollations;
6761 
6762  plan->qual = qual;
6763  plan->targetlist = tlist;
6764  plan->lefttree = lefttree;
6765  plan->righttree = NULL;
6766 
6767  return node;
6768 }
int numCols
Definition: plannodes.h:973
Plan plan
Definition: plannodes.h:970

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

6083 {
6084  Hash *node = makeNode(Hash);
6085  Plan *plan = &node->plan;
6086 
6087  plan->targetlist = lefttree->targetlist;
6088  plan->qual = NIL;
6089  plan->lefttree = lefttree;
6090  plan->righttree = NULL;
6091 
6092  node->hashkeys = hashkeys;
6093  node->skewTable = skewTable;
6094  node->skewColumn = skewColumn;
6095  node->skewInherit = skewInherit;
6096 
6097  return node;
6098 }
AttrNumber skewColumn
Definition: plannodes.h:1208
List * hashkeys
Definition: plannodes.h:1206
Oid skewTable
Definition: plannodes.h:1207
bool skewInherit
Definition: plannodes.h:1209

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

6058 {
6059  HashJoin *node = makeNode(HashJoin);
6060  Plan *plan = &node->join.plan;
6061 
6062  plan->targetlist = tlist;
6063  plan->qual = otherclauses;
6064  plan->lefttree = lefttree;
6065  plan->righttree = righttree;
6066  node->hashclauses = hashclauses;
6067  node->hashoperators = hashoperators;
6068  node->hashcollations = hashcollations;
6069  node->hashkeys = hashkeys;
6070  node->join.jointype = jointype;
6071  node->join.inner_unique = inner_unique;
6072  node->join.joinqual = joinclauses;
6073 
6074  return node;
6075 }
List * hashcollations
Definition: plannodes.h:868
List * hashclauses
Definition: plannodes.h:866
List * hashoperators
Definition: plannodes.h:867
List * hashkeys
Definition: plannodes.h:874
List * joinqual
Definition: plannodes.h:794
JoinType jointype
Definition: plannodes.h:792
bool inner_unique
Definition: plannodes.h:793

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

6176 {
6177  IncrementalSort *node;
6178  Plan *plan;
6179 
6180  node = makeNode(IncrementalSort);
6181 
6182  plan = &node->sort.plan;
6183  plan->targetlist = lefttree->targetlist;
6184  plan->qual = NIL;
6185  plan->lefttree = lefttree;
6186  plan->righttree = NULL;
6187  node->nPresortedCols = nPresortedCols;
6188  node->sort.numCols = numCols;
6189  node->sort.sortColIdx = sortColIdx;
6190  node->sort.sortOperators = sortOperators;
6191  node->sort.collations = collations;
6192  node->sort.nullsFirst = nullsFirst;
6193 
6194  return node;
6195 }
int numCols
Definition: plannodes.h:937
Plan plan
Definition: plannodes.h:934

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

6458 {
6459  int numsortkeys;
6460  AttrNumber *sortColIdx;
6461  Oid *sortOperators;
6462  Oid *collations;
6463  bool *nullsFirst;
6464 
6465  /* Compute sort column info, and adjust lefttree as needed */
6466  lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6467  relids,
6468  NULL,
6469  false,
6470  &numsortkeys,
6471  &sortColIdx,
6472  &sortOperators,
6473  &collations,
6474  &nullsFirst);
6475 
6476  /* Now build the Sort node */
6477  return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6478  sortColIdx, sortOperators,
6479  collations, nullsFirst);
6480 }
static IncrementalSort * make_incrementalsort(Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:6173

References make_incrementalsort(), and prepare_sort_from_pathkeys().

Referenced by create_incrementalsort_plan(), and create_mergejoin_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 5649 of file createplan.c.

5658 {
5660  Plan *plan = &node->scan.plan;
5661 
5662  plan->targetlist = qptlist;
5663  plan->qual = qpqual;
5664  plan->lefttree = NULL;
5665  plan->righttree = NULL;
5666  node->scan.scanrelid = scanrelid;
5667  node->indexid = indexid;
5668  node->indexqual = indexqual;
5669  node->recheckqual = recheckqual;
5670  node->indexorderby = indexorderby;
5671  node->indextlist = indextlist;
5672  node->indexorderdir = indexscandir;
5673 
5674  return node;
5675 }
List * indexqual
Definition: plannodes.h:497
List * recheckqual
Definition: plannodes.h:498
List * indextlist
Definition: plannodes.h:500
ScanDirection indexorderdir
Definition: plannodes.h:501
List * indexorderby
Definition: plannodes.h:499

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

5628 {
5629  IndexScan *node = makeNode(IndexScan);
5630  Plan *plan = &node->scan.plan;
5631 
5632  plan->targetlist = qptlist;
5633  plan->qual = qpqual;
5634  plan->lefttree = NULL;
5635  plan->righttree = NULL;
5636  node->scan.scanrelid = scanrelid;
5637  node->indexid = indexid;
5638  node->indexqual = indexqual;
5639  node->indexqualorig = indexqualorig;
5640  node->indexorderby = indexorderby;
5641  node->indexorderbyorig = indexorderbyorig;
5642  node->indexorderbyops = indexorderbyops;
5643  node->indexorderdir = indexscandir;
5644 
5645  return node;
5646 }
List * indexorderby
Definition: plannodes.h:456
List * indexorderbyops
Definition: plannodes.h:458
ScanDirection indexorderdir
Definition: plannodes.h:459
List * indexorderbyorig
Definition: plannodes.h:457

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

7040 {
7041  Limit *node = makeNode(Limit);
7042  Plan *plan = &node->plan;
7043 
7044  plan->targetlist = lefttree->targetlist;
7045  plan->qual = NIL;
7046  plan->lefttree = lefttree;
7047  plan->righttree = NULL;
7048 
7049  node->limitOffset = limitOffset;
7050  node->limitCount = limitCount;
7051  node->limitOption = limitOption;
7052  node->uniqNumCols = uniqNumCols;
7053  node->uniqColIdx = uniqColIdx;
7054  node->uniqOperators = uniqOperators;
7055  node->uniqCollations = uniqCollations;
7056 
7057  return node;
7058 }
LimitOption limitOption
Definition: plannodes.h:1282
Plan plan
Definition: plannodes.h:1273
Node * limitCount
Definition: plannodes.h:1279
int uniqNumCols
Definition: plannodes.h:1285
Node * limitOffset
Definition: plannodes.h:1276

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

7017 {
7018  LockRows *node = makeNode(LockRows);
7019  Plan *plan = &node->plan;
7020 
7021  plan->targetlist = lefttree->targetlist;
7022  plan->qual = NIL;
7023  plan->lefttree = lefttree;
7024  plan->righttree = NULL;
7025 
7026  node->rowMarks = rowMarks;
7027  node->epqParam = epqParam;
7028 
7029  return node;
7030 }
int epqParam
Definition: plannodes.h:1261
List * rowMarks
Definition: plannodes.h:1260
Plan plan
Definition: plannodes.h:1259

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

6581 {
6582  Material *node = makeNode(Material);
6583  Plan *plan = &node->plan;
6584 
6585  plan->targetlist = lefttree->targetlist;
6586  plan->qual = NIL;
6587  plan->lefttree = lefttree;
6588  plan->righttree = NULL;
6589 
6590  return node;
6591 }
Plan plan
Definition: plannodes.h:883

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

6648 {
6649  Memoize *node = makeNode(Memoize);
6650  Plan *plan = &node->plan;
6651 
6652  plan->targetlist = lefttree->targetlist;
6653  plan->qual = NIL;
6654  plan->lefttree = lefttree;
6655  plan->righttree = NULL;
6656 
6657  node->numKeys = list_length(param_exprs);
6658  node->hashOperators = hashoperators;
6659  node->collations = collations;
6660  node->param_exprs = param_exprs;
6661  node->singlerow = singlerow;
6662  node->binary_mode = binary_mode;
6663  node->est_entries = est_entries;
6664  node->keyparamids = keyparamids;
6665 
6666  return node;
6667 }
Plan plan
Definition: plannodes.h:892
bool singlerow
Definition: plannodes.h:910
Bitmapset * keyparamids
Definition: plannodes.h:925
bool binary_mode
Definition: plannodes.h:916
int numKeys
Definition: plannodes.h:895
List * param_exprs
Definition: plannodes.h:904
uint32 est_entries
Definition: plannodes.h:922

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,
bool mergereversals,
bool mergenullsfirst,
Plan lefttree,
Plan righttree,
JoinType  jointype,
bool  inner_unique,
bool  skip_mark_restore 
)
static

Definition at line 6101 of file createplan.c.

6114 {
6115  MergeJoin *node = makeNode(MergeJoin);
6116  Plan *plan = &node->join.plan;
6117 
6118  plan->targetlist = tlist;
6119  plan->qual = otherclauses;
6120  plan->lefttree = lefttree;
6121  plan->righttree = righttree;
6122  node->skip_mark_restore = skip_mark_restore;
6123  node->mergeclauses = mergeclauses;
6124  node->mergeFamilies = mergefamilies;
6125  node->mergeCollations = mergecollations;
6126  node->mergeReversals = mergereversals;
6127  node->mergeNullsFirst = mergenullsfirst;
6128  node->join.jointype = jointype;
6129  node->join.inner_unique = inner_unique;
6130  node->join.joinqual = joinclauses;
6131 
6132  return node;
6133 }
List * mergeclauses
Definition: plannodes.h:842
bool skip_mark_restore
Definition: plannodes.h:839

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

7115 {
7116  ModifyTable *node = makeNode(ModifyTable);
7117  List *fdw_private_list;
7118  Bitmapset *direct_modify_plans;
7119  ListCell *lc;
7120  int i;
7121 
7122  Assert(operation == CMD_MERGE ||
7123  (operation == CMD_UPDATE ?
7124  list_length(resultRelations) == list_length(updateColnosLists) :
7125  updateColnosLists == NIL));
7126  Assert(withCheckOptionLists == NIL ||
7127  list_length(resultRelations) == list_length(withCheckOptionLists));
7128  Assert(returningLists == NIL ||
7129  list_length(resultRelations) == list_length(returningLists));
7130 
7131  node->plan.lefttree = subplan;
7132  node->plan.righttree = NULL;
7133  node->plan.qual = NIL;
7134  /* setrefs.c will fill in the targetlist, if needed */
7135  node->plan.targetlist = NIL;
7136 
7137  node->operation = operation;
7138  node->canSetTag = canSetTag;
7139  node->nominalRelation = nominalRelation;
7140  node->rootRelation = rootRelation;
7141  node->partColsUpdated = partColsUpdated;
7142  node->resultRelations = resultRelations;
7143  if (!onconflict)
7144  {
7146  node->onConflictSet = NIL;
7147  node->onConflictCols = NIL;
7148  node->onConflictWhere = NULL;
7149  node->arbiterIndexes = NIL;
7150  node->exclRelRTI = 0;
7151  node->exclRelTlist = NIL;
7152  }
7153  else
7154  {
7155  node->onConflictAction = onconflict->action;
7156 
7157  /*
7158  * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7159  * executor's convention of having consecutive resno's. The actual
7160  * target column numbers are saved in node->onConflictCols. (This
7161  * could be done earlier, but there seems no need to.)
7162  */
7163  node->onConflictSet = onconflict->onConflictSet;
7164  node->onConflictCols =
7166  node->onConflictWhere = onconflict->onConflictWhere;
7167 
7168  /*
7169  * If a set of unique index inference elements was provided (an
7170  * INSERT...ON CONFLICT "inference specification"), then infer
7171  * appropriate unique indexes (or throw an error if none are
7172  * available).
7173  */
7175 
7176  node->exclRelRTI = onconflict->exclRelIndex;
7177  node->exclRelTlist = onconflict->exclRelTlist;
7178  }
7179  node->updateColnosLists = updateColnosLists;
7180  node->withCheckOptionLists = withCheckOptionLists;
7181  node->returningLists = returningLists;
7182  node->rowMarks = rowMarks;
7183  node->mergeActionLists = mergeActionLists;
7184  node->mergeJoinConditions = mergeJoinConditions;
7185  node->epqParam = epqParam;
7186 
7187  /*
7188  * For each result relation that is a foreign table, allow the FDW to
7189  * construct private plan data, and accumulate it all into a list.
7190  */
7191  fdw_private_list = NIL;
7192  direct_modify_plans = NULL;
7193  i = 0;
7194  foreach(lc, resultRelations)
7195  {
7196  Index rti = lfirst_int(lc);
7197  FdwRoutine *fdwroutine;
7198  List *fdw_private;
7199  bool direct_modify;
7200 
7201  /*
7202  * If possible, we want to get the FdwRoutine from our RelOptInfo for
7203  * the table. But sometimes we don't have a RelOptInfo and must get
7204  * it the hard way. (In INSERT, the target relation is not scanned,
7205  * so it's not a baserel; and there are also corner cases for
7206  * updatable views where the target rel isn't a baserel.)
7207  */
7208  if (rti < root->simple_rel_array_size &&
7209  root->simple_rel_array[rti] != NULL)
7210  {
7211  RelOptInfo *resultRel = root->simple_rel_array[rti];
7212 
7213  fdwroutine = resultRel->fdwroutine;
7214  }
7215  else
7216  {
7217  RangeTblEntry *rte = planner_rt_fetch(rti, root);
7218 
7219  if (rte->rtekind == RTE_RELATION &&
7220  rte->relkind == RELKIND_FOREIGN_TABLE)
7221  {
7222  /* Check if the access to foreign tables is restricted */
7224  {
7225  /* there must not be built-in foreign tables */
7226  Assert(rte->relid >= FirstNormalObjectId);
7227  ereport(ERROR,
7228  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7229  errmsg("access to non-system foreign table is restricted")));
7230  }
7231 
7232  fdwroutine = GetFdwRoutineByRelId(rte->relid);
7233  }
7234  else
7235  fdwroutine = NULL;
7236  }
7237 
7238  /*
7239  * MERGE is not currently supported for foreign tables. We already
7240  * checked that when the table mentioned in the query is foreign; but
7241  * we can still get here if a partitioned table has a foreign table as
7242  * partition. Disallow that now, to avoid an uglier error message
7243  * later.
7244  */
7245  if (operation == CMD_MERGE && fdwroutine != NULL)
7246  {
7247  RangeTblEntry *rte = planner_rt_fetch(rti, root);
7248 
7249  ereport(ERROR,
7250  errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7251  errmsg("cannot execute MERGE on relation \"%s\"",
7252  get_rel_name(rte->relid)),
7253  errdetail_relkind_not_supported(rte->relkind));
7254  }
7255 
7256  /*
7257  * Try to modify the foreign table directly if (1) the FDW provides
7258  * callback functions needed for that and (2) there are no local
7259  * structures that need to be run for each modified row: row-level
7260  * triggers on the foreign table, stored generated columns, WITH CHECK
7261  * OPTIONs from parent views.
7262  */
7263  direct_modify = false;
7264  if (fdwroutine != NULL &&
7265  fdwroutine->PlanDirectModify != NULL &&
7266  fdwroutine->BeginDirectModify != NULL &&
7267  fdwroutine->IterateDirectModify != NULL &&
7268  fdwroutine->EndDirectModify != NULL &&
7269  withCheckOptionLists == NIL &&
7270  !has_row_triggers(root, rti, operation) &&
7272  direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
7273  if (direct_modify)
7274  direct_modify_plans = bms_add_member(direct_modify_plans, i);
7275 
7276  if (!direct_modify &&
7277  fdwroutine != NULL &&
7278  fdwroutine->PlanForeignModify != NULL)
7279  fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7280  else
7281  fdw_private = NIL;
7282  fdw_private_list = lappend(fdw_private_list, fdw_private);
7283  i++;
7284  }
7285  node->fdwPrivLists = fdw_private_list;
7286  node->fdwDirectModifyPlans = direct_modify_plans;
7287 
7288  return node;
7289 }
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define unlikely(x)
Definition: c.h:326
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereport(elevel,...)
Definition: elog.h:149
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:419
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1928
@ ONCONFLICT_NONE
Definition: nodes.h:418
@ CMD_MERGE
Definition: nodes.h:269
@ CMD_UPDATE
Definition: nodes.h:266
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
bool has_stored_generated_columns(PlannerInfo *root, Index rti)
Definition: plancat.c:2298
bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
Definition: plancat.c:2248
List * infer_arbiter_indexes(PlannerInfo *root)
Definition: plancat.c:704
int restrict_nonsystem_relation_kind
Definition: postgres.c:107
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:239
Index nominalRelation
Definition: plannodes.h:235
List * arbiterIndexes
Definition: plannodes.h:247
List * onConflictCols
Definition: plannodes.h:249
List * mergeJoinConditions
Definition: plannodes.h:255
CmdType operation
Definition: plannodes.h:233
int epqParam
Definition: plannodes.h:245
List * resultRelations
Definition: plannodes.h:238
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:243
List * onConflictSet
Definition: plannodes.h:248
List * exclRelTlist
Definition: plannodes.h:252
List * mergeActionLists
Definition: plannodes.h:253
bool canSetTag
Definition: plannodes.h:234
List * fdwPrivLists
Definition: plannodes.h:242
bool partColsUpdated
Definition: plannodes.h:237
List * returningLists
Definition: plannodes.h:241
List * withCheckOptionLists
Definition: plannodes.h:240
Index rootRelation
Definition: plannodes.h:236
Node * onConflictWhere
Definition: plannodes.h:250
List * rowMarks
Definition: plannodes.h:244
OnConflictAction onConflictAction
Definition: plannodes.h:246
Index exclRelRTI
Definition: plannodes.h:251
OnConflictAction action
Definition: primnodes.h:2324
List * onConflictSet
Definition: primnodes.h:2333
List * exclRelTlist
Definition: primnodes.h:2336
Node * onConflictWhere
Definition: primnodes.h:2334
struct Plan * righttree
Definition: plannodes.h:156
List * qual
Definition: plannodes.h:154
#define RESTRICT_RELKIND_FOREIGN_TABLE
Definition: tcopprot.h:48
#define FirstNormalObjectId
Definition: transam.h:197

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, FirstNormalObjectId, 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, restrict_nonsystem_relation_kind, RESTRICT_RELKIND_FOREIGN_TABLE, ModifyTable::resultRelations, ModifyTable::returningLists, Plan::righttree, root, ModifyTable::rootRelation, ModifyTable::rowMarks, RTE_RELATION, RangeTblEntry::rtekind, Plan::targetlist, unlikely, 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 5857 of file createplan.c.

5861 {
5863  Plan *plan = &node->scan.plan;
5864 
5865  /* cost should be inserted by caller */
5866  plan->targetlist = qptlist;
5867  plan->qual = qpqual;
5868  plan->lefttree = NULL;
5869  plan->righttree = NULL;
5870  node->scan.scanrelid = scanrelid;
5871  node->enrname = enrname;
5872 
5873  return node;
5874 }

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

6030 {
6031  NestLoop *node = makeNode(NestLoop);
6032  Plan *plan = &node->join.plan;
6033 
6034  plan->targetlist = tlist;
6035  plan->qual = otherclauses;
6036  plan->lefttree = lefttree;
6037  plan->righttree = righttree;
6038  node->join.jointype = jointype;
6039  node->join.inner_unique = inner_unique;
6040  node->join.joinqual = joinclauses;
6041  node->nestParams = nestParams;
6042 
6043  return node;
6044 }
List * nestParams
Definition: plannodes.h:811

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

7088 {
7089  ProjectSet *node = makeNode(ProjectSet);
7090  Plan *plan = &node->plan;
7091 
7092  plan->targetlist = tlist;
7093  plan->qual = NIL;
7094  plan->lefttree = subplan;
7095  plan->righttree = NULL;
7096 
7097  return node;
7098 }
Plan plan
Definition: plannodes.h:211

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

5942 {
5944  Plan *plan = &node->plan;
5945  int numCols = list_length(distinctList);
5946 
5947  plan->targetlist = tlist;
5948  plan->qual = NIL;
5949  plan->lefttree = lefttree;
5950  plan->righttree = righttree;
5951  node->wtParam = wtParam;
5952 
5953  /*
5954  * convert SortGroupClause list into arrays of attr indexes and equality
5955  * operators, as wanted by executor
5956  */
5957  node->numCols = numCols;
5958  if (numCols > 0)
5959  {
5960  int keyno = 0;
5961  AttrNumber *dupColIdx;
5962  Oid *dupOperators;
5963  Oid *dupCollations;
5964  ListCell *slitem;
5965 
5966  dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5967  dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5968  dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
5969 
5970  foreach(slitem, distinctList)
5971  {
5972  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5973  TargetEntry *tle = get_sortgroupclause_tle(sortcl,
5974  plan->targetlist);
5975 
5976  dupColIdx[keyno] = tle->resno;
5977  dupOperators[keyno] = sortcl->eqop;
5978  dupCollations[keyno] = exprCollation((Node *) tle->expr);
5979  Assert(OidIsValid(dupOperators[keyno]));
5980  keyno++;
5981  }
5982  node->dupColIdx = dupColIdx;
5983  node->dupOperators = dupOperators;
5984  node->dupCollations = dupCollations;
5985  }
5986  node->numGroups = numGroups;
5987 
5988  return node;
5989 }

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

7068 {
7069  Result *node = makeNode(Result);
7070  Plan *plan = &node->plan;
7071 
7072  plan->targetlist = tlist;
7073  plan->qual = NIL;
7074  plan->lefttree = subplan;
7075  plan->righttree = NULL;
7076  node->resconstantqual = resconstantqual;
7077 
7078  return node;
7079 }

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

5603 {
5604  SampleScan *node = makeNode(SampleScan);
5605  Plan *plan = &node->scan.plan;
5606 
5607  plan->targetlist = qptlist;
5608  plan->qual = qpqual;
5609  plan->lefttree = NULL;
5610  plan->righttree = NULL;
5611  node->scan.scanrelid = scanrelid;
5612  node->tablesample = tsc;
5613 
5614  return node;
5615 }
struct TableSampleClause * tablesample
Definition: plannodes.h:410

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

5585 {
5586  SeqScan *node = makeNode(SeqScan);
5587  Plan *plan = &node->scan.plan;
5588 
5589  plan->targetlist = qptlist;
5590  plan->qual = qpqual;
5591  plan->lefttree = NULL;
5592  plan->righttree = NULL;
5593  node->scan.scanrelid = scanrelid;
5594 
5595  return node;
5596 }

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

6963 {
6964  SetOp *node = makeNode(SetOp);
6965  Plan *plan = &node->plan;
6966  int numCols = list_length(distinctList);
6967  int keyno = 0;
6968  AttrNumber *dupColIdx;
6969  Oid *dupOperators;
6970  Oid *dupCollations;
6971  ListCell *slitem;
6972 
6973  plan->targetlist = lefttree->targetlist;
6974  plan->qual = NIL;
6975  plan->lefttree = lefttree;
6976  plan->righttree = NULL;
6977 
6978  /*
6979  * convert SortGroupClause list into arrays of attr indexes and equality
6980  * operators, as wanted by executor
6981  */
6982  dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6983  dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6984  dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6985 
6986  foreach(slitem, distinctList)
6987  {
6988  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6989  TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6990 
6991  dupColIdx[keyno] = tle->resno;
6992  dupOperators[keyno] = sortcl->eqop;
6993  dupCollations[keyno] = exprCollation((Node *) tle->expr);
6994  Assert(OidIsValid(dupOperators[keyno]));
6995  keyno++;
6996  }
6997 
6998  node->cmd = cmd;
6999  node->strategy = strategy;
7000  node->numCols = numCols;
7001  node->dupColIdx = dupColIdx;
7002  node->dupOperators = dupOperators;
7003  node->dupCollations = dupCollations;
7004  node->flagColIdx = flagColIdx;
7005  node->firstFlag = firstFlag;
7006  node->numGroups = numGroups;
7007 
7008  return node;
7009 }
SetOpStrategy strategy
Definition: plannodes.h:1226
AttrNumber flagColIdx
Definition: plannodes.h:1239
SetOpCmd cmd
Definition: plannodes.h:1223
int numCols
Definition: plannodes.h:1229
int firstFlag
Definition: plannodes.h:1242
Plan plan
Definition: plannodes.h:1220
long numGroups
Definition: plannodes.h:1245

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

6145 {
6146  Sort *node;
6147  Plan *plan;
6148 
6149  node = makeNode(Sort);
6150 
6151  plan = &node->plan;
6152  plan->targetlist = lefttree->targetlist;
6153  plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
6154  plan->qual = NIL;
6155  plan->lefttree = lefttree;
6156  plan->righttree = NULL;
6157  node->numCols = numCols;
6158  node->sortColIdx = sortColIdx;
6159  node->sortOperators = sortOperators;
6160  node->collations = collations;
6161  node->nullsFirst = nullsFirst;
6162 
6163  return node;
6164 }
bool enable_sort
Definition: costsize.c:150

References Plan::disabled_nodes, enable_sort, 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 6539 of file createplan.c.

6542 {
6543  List *sub_tlist = lefttree->targetlist;
6544  ListCell *l;
6545  int numsortkeys;
6546  AttrNumber *sortColIdx;
6547  Oid *sortOperators;
6548  Oid *collations;
6549  bool *nullsFirst;
6550 
6551  /* Convert list-ish representation to arrays wanted by executor */
6552  numsortkeys = list_length(groupcls);
6553  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6554  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6555  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6556  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6557 
6558  numsortkeys = 0;
6559  foreach(l, groupcls)
6560  {
6561  SortGroupClause *grpcl = (SortGroupClause *) lfirst(l);
6562  TargetEntry *tle = get_tle_by_resno(sub_tlist, grpColIdx[numsortkeys]);
6563 
6564  if (!tle)
6565  elog(ERROR, "could not retrieve tle for sort-from-groupcols");
6566 
6567  sortColIdx[numsortkeys] = tle->resno;
6568  sortOperators[numsortkeys] = grpcl->sortop;
6569  collations[numsortkeys] = exprCollation((Node *) tle->expr);
6570  nullsFirst[numsortkeys] = grpcl->nulls_first;
6571  numsortkeys++;
6572  }
6573 
6574  return make_sort(lefttree, numsortkeys,
6575  sortColIdx, sortOperators,
6576  collations, nullsFirst);
6577 }

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

6422 {
6423  int numsortkeys;
6424  AttrNumber *sortColIdx;
6425  Oid *sortOperators;
6426  Oid *collations;
6427  bool *nullsFirst;
6428 
6429  /* Compute sort column info, and adjust lefttree as needed */
6430  lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6431  relids,
6432  NULL,
6433  false,
6434  &numsortkeys,
6435  &sortColIdx,
6436  &sortOperators,
6437  &collations,
6438  &nullsFirst);
6439 
6440  /* Now build the Sort node */
6441  return make_sort(lefttree, numsortkeys,
6442  sortColIdx, sortOperators,
6443  collations, nullsFirst);
6444 }

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

6491 {
6492  List *sub_tlist = lefttree->targetlist;
6493  ListCell *l;
6494  int numsortkeys;
6495  AttrNumber *sortColIdx;
6496  Oid *sortOperators;
6497  Oid *collations;
6498  bool *nullsFirst;
6499 
6500  /* Convert list-ish representation to arrays wanted by executor */
6501  numsortkeys = list_length(sortcls);
6502  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6503  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6504  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6505  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6506 
6507  numsortkeys = 0;
6508  foreach(l, sortcls)
6509  {
6510  SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
6511  TargetEntry *tle = get_sortgroupclause_tle(sortcl, sub_tlist);
6512 
6513  sortColIdx[numsortkeys] = tle->resno;
6514  sortOperators[numsortkeys] = sortcl->sortop;
6515  collations[numsortkeys] = exprCollation((Node *) tle->expr);
6516  nullsFirst[numsortkeys] = sortcl->nulls_first;
6517  numsortkeys++;
6518  }
6519 
6520  return make_sort(lefttree, numsortkeys,
6521  sortColIdx, sortOperators,
6522  collations, nullsFirst);
6523 }

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

5761 {
5763  Plan *plan = &node->scan.plan;
5764 
5765  plan->targetlist = qptlist;
5766  plan->qual = qpqual;
5767  plan->lefttree = NULL;
5768  plan->righttree = NULL;
5769  node->scan.scanrelid = scanrelid;
5770  node->subplan = subplan;
5772 
5773  return node;
5774 }
@ SUBQUERY_SCAN_UNKNOWN
Definition: plannodes.h:594
SubqueryScanStatus scanstatus
Definition: plannodes.h:603
Plan * subplan
Definition: plannodes.h:602

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

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

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

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

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

5723 {
5724  TidScan *node = makeNode(TidScan);
5725  Plan *plan = &node->scan.plan;
5726 
5727  plan->targetlist = qptlist;
5728  plan->qual = qpqual;
5729  plan->lefttree = NULL;
5730  plan->righttree = NULL;
5731  node->scan.scanrelid = scanrelid;
5732  node->tidquals = tidquals;
5733 
5734  return node;
5735 }
List * tidquals
Definition: plannodes.h:556

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

6826 {
6827  Unique *node = makeNode(Unique);
6828  Plan *plan = &node->plan;
6829  int keyno = 0;
6830  AttrNumber *uniqColIdx;
6831  Oid *uniqOperators;
6832  Oid *uniqCollations;
6833  ListCell *lc;
6834 
6835  plan->targetlist = lefttree->targetlist;
6836  plan->qual = NIL;
6837  plan->lefttree = lefttree;
6838  plan->righttree = NULL;
6839 
6840  /*
6841  * Convert pathkeys list into arrays of attr indexes and equality
6842  * operators, as wanted by executor. This has a lot in common with
6843  * prepare_sort_from_pathkeys ... maybe unify sometime?
6844  */
6845  Assert(numCols >= 0 && numCols <= list_length(pathkeys));
6846  uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6847  uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6848  uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6849 
6850  foreach(lc, pathkeys)
6851  {
6852  PathKey *pathkey = (PathKey *) lfirst(lc);
6853  EquivalenceClass *ec = pathkey->pk_eclass;
6854  EquivalenceMember *em;
6855  TargetEntry *tle = NULL;
6856  Oid pk_datatype = InvalidOid;
6857  Oid eqop;
6858  ListCell *j;
6859 
6860  /* Ignore pathkeys beyond the specified number of columns */
6861  if (keyno >= numCols)
6862  break;
6863 
6864  if (ec->ec_has_volatile)
6865  {
6866  /*
6867  * If the pathkey's EquivalenceClass is volatile, then it must
6868  * have come from an ORDER BY clause, and we have to match it to
6869  * that same targetlist entry.
6870  */
6871  if (ec->ec_sortref == 0) /* can't happen */
6872  elog(ERROR, "volatile EquivalenceClass has no sortref");
6873  tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
6874  Assert(tle);
6875  Assert(list_length(ec->ec_members) == 1);
6876  pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6877  }
6878  else
6879  {
6880  /*
6881  * Otherwise, we can use any non-constant expression listed in the
6882  * pathkey's EquivalenceClass. For now, we take the first tlist
6883  * item found in the EC.
6884  */
6885  foreach(j, plan->targetlist)
6886  {
6887  tle = (TargetEntry *) lfirst(j);
6888  em = find_ec_member_matching_expr(ec, tle->expr, NULL);
6889  if (em)
6890  {
6891  /* found expr already in tlist */
6892  pk_datatype = em->em_datatype;
6893  break;
6894  }
6895  tle = NULL;
6896  }
6897  }
6898 
6899  if (!tle)
6900  elog(ERROR, "could not find pathkey item to sort");
6901 
6902  /*
6903  * Look up the correct equality operator from the PathKey's slightly
6904  * abstracted representation.
6905  */
6906  eqop = get_opfamily_member(pathkey->pk_opfamily,
6907  pk_datatype,
6908  pk_datatype,
6910  if (!OidIsValid(eqop)) /* should not happen */
6911  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6912  BTEqualStrategyNumber, pk_datatype, pk_datatype,
6913  pathkey->pk_opfamily);
6914 
6915  uniqColIdx[keyno] = tle->resno;
6916  uniqOperators[keyno] = eqop;
6917  uniqCollations[keyno] = ec->ec_collation;
6918 
6919  keyno++;
6920  }
6921 
6922  node->numCols = numCols;
6923  node->uniqColIdx = uniqColIdx;
6924  node->uniqOperators = uniqOperators;
6925  node->uniqCollations = uniqCollations;
6926 
6927  return node;
6928 }
EquivalenceMember * find_ec_member_matching_expr(EquivalenceClass *ec, Expr *expr, Relids relids)
Definition: equivclass.c:763
int j
Definition: isn.c:73
#define BTEqualStrategyNumber
Definition: stratnum.h:31
Plan plan
Definition: plannodes.h:1115
int numCols
Definition: plannodes.h:1118
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 6776 of file createplan.c.

6777 {
6778  Unique *node = makeNode(Unique);
6779  Plan *plan = &node->plan;
6780  int numCols = list_length(distinctList);
6781  int keyno = 0;
6782  AttrNumber *uniqColIdx;
6783  Oid *uniqOperators;
6784  Oid *uniqCollations;
6785  ListCell *slitem;
6786 
6787  plan->targetlist = lefttree->targetlist;
6788  plan->qual = NIL;
6789  plan->lefttree = lefttree;
6790  plan->righttree = NULL;
6791 
6792  /*
6793  * convert SortGroupClause list into arrays of attr indexes and equality
6794  * operators, as wanted by executor
6795  */
6796  Assert(numCols > 0);
6797  uniqColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6798  uniqOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6799  uniqCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6800 
6801  foreach(slitem, distinctList)
6802  {
6803  SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6804  TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6805 
6806  uniqColIdx[keyno] = tle->resno;
6807  uniqOperators[keyno] = sortcl->eqop;
6808  uniqCollations[keyno] = exprCollation((Node *) tle->expr);
6809  Assert(OidIsValid(uniqOperators[keyno]));
6810  keyno++;
6811  }
6812 
6813  node->numCols = numCols;
6814  node->uniqColIdx = uniqColIdx;
6815  node->uniqOperators = uniqOperators;
6816  node->uniqCollations = uniqCollations;
6817 
6818  return node;
6819 }

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

5821 {
5822  ValuesScan *node = makeNode(ValuesScan);
5823  Plan *plan = &node->scan.plan;
5824 
5825  plan->targetlist = qptlist;
5826  plan->qual = qpqual;
5827  plan->lefttree = NULL;
5828  plan->righttree = NULL;
5829  node->scan.scanrelid = scanrelid;
5830  node->values_lists = values_lists;
5831 
5832  return node;
5833 }
List * values_lists
Definition: plannodes.h:624

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

6711 {
6712  WindowAgg *node = makeNode(WindowAgg);
6713  Plan *plan = &node->plan;
6714 
6715  node->winref = winref;
6716  node->partNumCols = partNumCols;
6717  node->partColIdx = partColIdx;
6718  node->partOperators = partOperators;
6719  node->partCollations = partCollations;
6720  node->ordNumCols = ordNumCols;
6721  node->ordColIdx = ordColIdx;
6722  node->ordOperators = ordOperators;
6723  node->ordCollations = ordCollations;
6724  node->frameOptions = frameOptions;
6725  node->startOffset = startOffset;
6726  node->endOffset = endOffset;
6727  node->runCondition = runCondition;
6728  /* a duplicate of the above for EXPLAIN */
6729  node->runConditionOrig = runCondition;
6730  node->startInRangeFunc = startInRangeFunc;
6731  node->endInRangeFunc = endInRangeFunc;
6732  node->inRangeColl = inRangeColl;
6733  node->inRangeAsc = inRangeAsc;
6734  node->inRangeNullsFirst = inRangeNullsFirst;
6735  node->topWindow = topWindow;
6736 
6737  plan->targetlist = tlist;
6738  plan->lefttree = lefttree;
6739  plan->righttree = NULL;
6740  plan->qual = qual;
6741 
6742  return node;
6743 }
int partNumCols
Definition: plannodes.h:1047
Oid endInRangeFunc
Definition: plannodes.h:1091
Node * endOffset
Definition: plannodes.h:1077
bool topWindow
Definition: plannodes.h:1106
Plan plan
Definition: plannodes.h:1041
List * runConditionOrig
Definition: plannodes.h:1083
Oid inRangeColl
Definition: plannodes.h:1094
Node * startOffset
Definition: plannodes.h:1074
List * runCondition
Definition: plannodes.h:1080
Oid startInRangeFunc
Definition: plannodes.h:1088
bool inRangeAsc
Definition: plannodes.h:1097
Index winref
Definition: plannodes.h:1044
bool inRangeNullsFirst
Definition: plannodes.h:1100
int ordNumCols
Definition: plannodes.h:1059
int frameOptions
Definition: plannodes.h:1071

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

5881 {
5883  Plan *plan = &node->scan.plan;
5884 
5885  plan->targetlist = qptlist;
5886  plan->qual = qpqual;
5887  plan->lefttree = NULL;
5888  plan->righttree = NULL;
5889  node->scan.scanrelid = scanrelid;
5890  node->wtParam = wtParam;
5891 
5892  return node;
5893 }

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

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

6603 {
6604  Plan *matplan;
6605  Path matpath; /* dummy for result of cost_material */
6606  Cost initplan_cost;
6607  bool unsafe_initplans;
6608 
6609  matplan = (Plan *) make_material(subplan);
6610 
6611  /*
6612  * XXX horrid kluge: if there are any initPlans attached to the subplan,
6613  * move them up to the Material node, which is now effectively the top
6614  * plan node in its query level. This prevents failure in
6615  * SS_finalize_plan(), which see for comments.
6616  */
6617  matplan->initPlan = subplan->initPlan;
6618  subplan->initPlan = NIL;
6619 
6620  /* Move the initplans' cost delta, as well */
6622  &initplan_cost, &unsafe_initplans);
6623  subplan->startup_cost -= initplan_cost;
6624  subplan->total_cost -= initplan_cost;
6625 
6626  /* Set cost data */
6627  cost_material(&matpath,
6628  subplan->disabled_nodes,
6629  subplan->startup_cost,
6630  subplan->total_cost,
6631  subplan->plan_rows,
6632  subplan->plan_width);
6633  matplan->disabled_nodes = subplan->disabled_nodes;
6634  matplan->startup_cost = matpath.startup_cost + initplan_cost;
6635  matplan->total_cost = matpath.total_cost + initplan_cost;
6636  matplan->plan_rows = subplan->plan_rows;
6637  matplan->plan_width = subplan->plan_width;
6638  matplan->parallel_aware = false;
6639  matplan->parallel_safe = subplan->parallel_safe;
6640 
6641  return matplan;
6642 }
void cost_material(Path *path, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition: costsize.c:2483
double Cost
Definition: nodes.h:251
List * initPlan
Definition: plannodes.h:157
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition: subselect.c:2222

References cost_material(), Plan::disabled_nodes, 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 5359 of file createplan.c.

5360 {
5361  typedef struct
5362  {
5363  Node *clause;
5364  Cost cost;
5365  Index security_level;
5366  } QualItem;
5367  int nitems = list_length(clauses);
5368  QualItem *items;
5369  ListCell *lc;
5370  int i;
5371  List *result;
5372 
5373  /* No need to work hard for 0 or 1 clause */
5374  if (nitems <= 1)
5375  return clauses;
5376 
5377  /*
5378  * Collect the items and costs into an array. This is to avoid repeated
5379  * cost_qual_eval work if the inputs aren't RestrictInfos.
5380  */
5381  items = (QualItem *) palloc(nitems * sizeof(QualItem));
5382  i = 0;
5383  foreach(lc, clauses)
5384  {
5385  Node *clause = (Node *) lfirst(lc);
5386  QualCost qcost;
5387 
5388  cost_qual_eval_node(&qcost, clause, root);
5389  items[i].clause = clause;
5390  items[i].cost = qcost.per_tuple;
5391  if (IsA(clause, RestrictInfo))
5392  {
5393  RestrictInfo *rinfo = (RestrictInfo *) clause;
5394 
5395  /*
5396  * If a clause is leakproof, it doesn't have to be constrained by
5397  * its nominal security level. If it's also reasonably cheap
5398  * (here defined as 10X cpu_operator_cost), pretend it has
5399  * security_level 0, which will allow it to go in front of
5400  * more-expensive quals of lower security levels. Of course, that
5401  * will also force it to go in front of cheaper quals of its own
5402  * security level, which is not so great, but we can alleviate
5403  * that risk by applying the cost limit cutoff.
5404  */
5405  if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
5406  items[i].security_level = 0;
5407  else
5408  items[i].security_level = rinfo->security_level;
5409  }
5410  else
5411  items[i].security_level = 0;
5412  i++;
5413  }
5414 
5415  /*
5416  * Sort. We don't use qsort() because it's not guaranteed stable for
5417  * equal keys. The expected number of entries is small enough that a
5418  * simple insertion sort should be good enough.
5419  */
5420  for (i = 1; i < nitems; i++)
5421  {
5422  QualItem newitem = items[i];
5423  int j;
5424 
5425  /* insert newitem into the already-sorted subarray */
5426  for (j = i; j > 0; j--)
5427  {
5428  QualItem *olditem = &items[j - 1];
5429 
5430  if (newitem.security_level > olditem->security_level ||
5431  (newitem.security_level == olditem->security_level &&
5432  newitem.cost >= olditem->cost))
5433  break;
5434  items[j] = *olditem;
5435  }
5436  items[j] = newitem;
5437  }
5438 
5439  /* Convert back to a list */
5440  result = NIL;
5441  for (i = 0; i < nitems; i++)
5442  result = lappend(result, items[i].clause);
5443 
5444  return result;
5445 }
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4758
#define nitems(x)
Definition: indent.h:31
Cost per_tuple
Definition: pathnodes.h:48
Index security_level
Definition: pathnodes.h:2596
static ItemArray items
Definition: test_tidstore.c:48

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

6248 {
6249  List *tlist = lefttree->targetlist;
6250  ListCell *i;
6251  int numsortkeys;
6252  AttrNumber *sortColIdx;
6253  Oid *sortOperators;
6254  Oid *collations;
6255  bool *nullsFirst;
6256 
6257  /*
6258  * We will need at most list_length(pathkeys) sort columns; possibly less
6259  */
6260  numsortkeys = list_length(pathkeys);
6261  sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6262  sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6263  collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6264  nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6265 
6266  numsortkeys = 0;
6267 
6268  foreach(i, pathkeys)
6269  {
6270  PathKey *pathkey = (PathKey *) lfirst(i);
6271  EquivalenceClass *ec = pathkey->pk_eclass;
6272  EquivalenceMember *em;
6273  TargetEntry *tle = NULL;
6274  Oid pk_datatype = InvalidOid;
6275  Oid sortop;
6276  ListCell *j;
6277 
6278  if (ec->ec_has_volatile)
6279  {
6280  /*
6281  * If the pathkey's EquivalenceClass is volatile, then it must
6282  * have come from an ORDER BY clause, and we have to match it to
6283  * that same targetlist entry.
6284  */
6285  if (ec->ec_sortref == 0) /* can't happen */
6286  elog(ERROR, "volatile EquivalenceClass has no sortref");
6287  tle = get_sortgroupref_tle(ec->ec_sortref, tlist);
6288  Assert(tle);
6289  Assert(list_length(ec->ec_members) == 1);
6290  pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6291  }
6292  else if (reqColIdx != NULL)
6293  {
6294  /*
6295  * If we are given a sort column number to match, only consider
6296  * the single TLE at that position. It's possible that there is
6297  * no such TLE, in which case fall through and generate a resjunk
6298  * targetentry (we assume this must have happened in the parent
6299  * plan as well). If there is a TLE but it doesn't match the
6300  * pathkey's EC, we do the same, which is probably the wrong thing
6301  * but we'll leave it to caller to complain about the mismatch.
6302  */
6303  tle = get_tle_by_resno(tlist, reqColIdx[numsortkeys]);
6304  if (tle)
6305  {
6306  em = find_ec_member_matching_expr(ec, tle->expr, relids);
6307  if (em)
6308  {
6309  /* found expr at right place in tlist */
6310  pk_datatype = em->em_datatype;
6311  }
6312  else
6313  tle = NULL;
6314  }
6315  }
6316  else
6317  {
6318  /*
6319  * Otherwise, we can sort by any non-constant expression listed in
6320  * the pathkey's EquivalenceClass. For now, we take the first
6321  * tlist item found in the EC. If there's no match, we'll generate
6322  * a resjunk entry using the first EC member that is an expression
6323  * in the input's vars.
6324  *
6325  * XXX if we have a choice, is there any way of figuring out which
6326  * might be cheapest to execute? (For example, int4lt is likely
6327  * much cheaper to execute than numericlt, but both might appear
6328  * in the same equivalence class...) Not clear that we ever will
6329  * have an interesting choice in practice, so it may not matter.
6330  */
6331  foreach(j, tlist)
6332  {
6333  tle = (TargetEntry *) lfirst(j);
6334  em = find_ec_member_matching_expr(ec, tle->expr, relids);
6335  if (em)
6336  {
6337  /* found expr already in tlist */
6338  pk_datatype = em->em_datatype;
6339  break;
6340  }
6341  tle = NULL;
6342  }
6343  }
6344 
6345  if (!tle)
6346  {
6347  /*
6348  * No matching tlist item; look for a computable expression.
6349  */
6350  em = find_computable_ec_member(NULL, ec, tlist, relids, false);
6351  if (!em)
6352  elog(ERROR, "could not find pathkey item to sort");
6353  pk_datatype = em->em_datatype;
6354 
6355  /*
6356  * Do we need to insert a Result node?
6357  */
6358  if (!adjust_tlist_in_place &&
6359  !is_projection_capable_plan(lefttree))
6360  {
6361  /* copy needed so we don't modify input's tlist below */
6362  tlist = copyObject(tlist);
6363  lefttree = inject_projection_plan(lefttree, tlist,
6364  lefttree->parallel_safe);
6365  }
6366 
6367  /* Don't bother testing is_projection_capable_plan again */
6368  adjust_tlist_in_place = true;
6369 
6370  /*
6371  * Add resjunk entry to input's tlist
6372  */
6373  tle = makeTargetEntry(copyObject(em->em_expr),
6374  list_length(tlist) + 1,
6375  NULL,
6376  true);
6377  tlist = lappend(tlist, tle);
6378  lefttree->targetlist = tlist; /* just in case NIL before */
6379  }
6380 
6381  /*
6382  * Look up the correct sort operator from the PathKey's slightly
6383  * abstracted representation.
6384  */
6385  sortop = get_opfamily_member(pathkey->pk_opfamily,
6386  pk_datatype,
6387  pk_datatype,
6388  pathkey->pk_strategy);
6389  if (!OidIsValid(sortop)) /* should not happen */
6390  elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6391  pathkey->pk_strategy, pk_datatype, pk_datatype,
6392  pathkey->pk_opfamily);
6393 
6394  /* Add the column to the sort arrays */
6395  sortColIdx[numsortkeys] = tle->resno;
6396  sortOperators[numsortkeys] = sortop;
6397  collations[numsortkeys] = ec->ec_collation;
6398  nullsFirst[numsortkeys] = pathkey->pk_nulls_first;
6399  numsortkeys++;
6400  }
6401 
6402  /* Return results */
6403  *p_numsortkeys = numsortkeys;
6404  *p_sortColIdx = sortColIdx;
6405  *p_sortOperators = sortOperators;
6406  *p_collations = collations;
6407  *p_nullsFirst = nullsFirst;
6408 
6409  return lefttree;
6410 }
EquivalenceMember * find_computable_ec_member(PlannerInfo *root, EquivalenceClass *ec, List *exprs, Relids relids, bool require_parallel_safe)
Definition: equivclass.c:837

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

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

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

4987 {
4988  if (node == NULL)
4989  return NULL;
4990  if (IsA(node, Var))
4991  {
4992  Var *var = (Var *) node;
4993 
4994  /* Upper-level Vars should be long gone at this point */
4995  Assert(var->varlevelsup == 0);
4996  /* If not to be replaced, we can just return the Var unmodified */
4997  if (IS_SPECIAL_VARNO(var->varno) ||
4998  !bms_is_member(var->varno, root->curOuterRels))
4999  return node;
5000  /* Replace the Var with a nestloop Param */
5001  return (Node *) replace_nestloop_param_var(root, var);
5002  }
5003  if (IsA(node, PlaceHolderVar))
5004  {
5005  PlaceHolderVar *phv = (PlaceHolderVar *) node;
5006 
5007  /* Upper-level PlaceHolderVars should be long gone at this point */
5008  Assert(phv->phlevelsup == 0);
5009 
5010  /* Check whether we need to replace the PHV */
5011  if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
5012  root->curOuterRels))
5013  {
5014  /*
5015  * We can't replace the whole PHV, but we might still need to
5016  * replace Vars or PHVs within its expression, in case it ends up
5017  * actually getting evaluated here. (It might get evaluated in
5018  * this plan node, or some child node; in the latter case we don't
5019  * really need to process the expression here, but we haven't got
5020  * enough info to tell if that's the case.) Flat-copy the PHV
5021  * node and then recurse on its expression.
5022  *
5023  * Note that after doing this, we might have different
5024  * representations of the contents of the same PHV in different
5025  * parts of the plan tree. This is OK because equal() will just
5026  * match on phid/phlevelsup, so setrefs.c will still recognize an
5027  * upper-level reference to a lower-level copy of the same PHV.
5028  */
5030 
5031  memcpy(newphv, phv, sizeof(PlaceHolderVar));
5032  newphv->phexpr = (Expr *)
5033  replace_nestloop_params_mutator((Node *) phv->phexpr,
5034  root);
5035  return (Node *) newphv;
5036  }
5037  /* Replace the PlaceHolderVar with a nestloop Param */
5039  }
5040  return expression_tree_mutator(node,
5042  (void *) root);
5043 }
#define expression_tree_mutator(n, m, c)
Definition: nodeFuncs.h:155
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:2807
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 868 of file createplan.c.

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

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