PostgreSQL Source Code git master
Loading...
Searching...
No Matches
createplan.c File Reference
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 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_unique_plan (PlannerInfo *root, UniquePath *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, Cardinality 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, Cardinality est_calls, Cardinality est_unique_keys, double est_hit_ratio)
 
static WindowAggmake_windowagg (List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, 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_pathkeys (Plan *lefttree, List *pathkeys, int numCols, Relids relids)
 
static Gathermake_gather (List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)
 
static SetOpmake_setop (SetOpCmd cmd, SetOpStrategy strategy, List *tlist, Plan *lefttree, Plan *righttree, List *groupList, Cardinality numGroups)
 
static LockRowsmake_lockrows (Plan *lefttree, List *rowMarks, int epqParam)
 
static Resultmake_gating_result (List *tlist, Node *resconstantqual, Plan *subplan)
 
static Resultmake_one_row_result (List *tlist, Node *resconstantqual, RelOptInfo *rel)
 
static ProjectSetmake_project_set (List *tlist, Plan *subplan)
 
static ModifyTablemake_modifytable (PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, ForPortionOfExpr *forPortionOf, 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, Cardinality numGroups, Size transitionSpace, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 

Macro Definition Documentation

◆ CP_EXACT_TLIST

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

Definition at line 69 of file createplan.c.

◆ CP_IGNORE_TLIST

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

Definition at line 72 of file createplan.c.

◆ CP_LABEL_TLIST

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

Definition at line 71 of file createplan.c.

◆ CP_SMALL_TLIST

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

Definition at line 70 of file createplan.c.

Function Documentation

◆ bitmap_subplan_mark_shared()

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 5459 of file createplan.c.

5460{
5461 if (IsA(plan, BitmapAnd))
5463 else if (IsA(plan, BitmapOr))
5464 {
5465 ((BitmapOr *) plan)->isshared = true;
5466 bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5467 }
5468 else if (IsA(plan, BitmapIndexScan))
5469 ((BitmapIndexScan *) plan)->isshared = true;
5470 else
5471 elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5472}
static void bitmap_subplan_mark_shared(Plan *plan)
#define ERROR
Definition elog.h:40
#define elog(elevel,...)
Definition elog.h:228
#define IsA(nodeptr, _type_)
Definition nodes.h:164
#define nodeTag(nodeptr)
Definition nodes.h:139
#define linitial(l)
Definition pg_list.h:178
#define plan(x)
Definition pg_regress.c:164

References bitmap_subplan_mark_shared(), elog, ERROR, IsA, linitial, nodeTag, and plan.

Referenced by bitmap_subplan_mark_shared(), and create_bitmap_scan_plan().

◆ build_path_tlist()

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

Definition at line 817 of file createplan.c.

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

References fb(), lappend(), lfirst, makeTargetEntry(), NIL, replace_nestloop_params(), 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_setop_plan(), and create_windowagg_plan().

◆ change_plan_targetlist()

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

Definition at line 1992 of file createplan.c.

1993{
1994 /*
1995 * If the top plan node can't do projections and its existing target list
1996 * isn't already what we need, we need to add a Result node to help it
1997 * along.
1998 */
1999 if (!is_projection_capable_plan(subplan) &&
2000 !tlist_same_exprs(tlist, subplan->targetlist))
2001 subplan = inject_projection_plan(subplan, tlist,
2002 subplan->parallel_safe &&
2004 else
2005 {
2006 /* Else we can just replace the plan node's tlist */
2007 subplan->targetlist = tlist;
2009 }
2010 return subplan;
2011}
bool is_projection_capable_plan(Plan *plan)
static Plan * inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
bool parallel_safe
Definition plannodes.h:221
List * targetlist
Definition plannodes.h:235
bool tlist_same_exprs(List *tlist1, List *tlist2)
Definition tlist.c:227

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

Referenced by create_nestloop_plan(), and postgresGetForeignPlan().

◆ copy_generic_path_info()

static void copy_generic_path_info ( Plan dest,
Path src 
)
static

Definition at line 5360 of file createplan.c.

5361{
5362 dest->disabled_nodes = src->disabled_nodes;
5363 dest->startup_cost = src->startup_cost;
5364 dest->total_cost = src->total_cost;
5365 dest->plan_rows = src->rows;
5366 dest->plan_width = src->pathtarget->width;
5367 dest->parallel_aware = src->parallel_aware;
5368 dest->parallel_safe = src->parallel_safe;
5369}
Cardinality rows
Definition pathnodes.h:2005
Cost startup_cost
Definition pathnodes.h:2007
int disabled_nodes
Definition pathnodes.h:2006
Cost total_cost
Definition pathnodes.h:2008
bool parallel_aware
Definition pathnodes.h:1998
bool parallel_safe
Definition pathnodes.h:2000

References 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_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 5376 of file createplan.c.

5377{
5378 dest->disabled_nodes = src->disabled_nodes;
5379 dest->startup_cost = src->startup_cost;
5380 dest->total_cost = src->total_cost;
5381 dest->plan_rows = src->plan_rows;
5382 dest->plan_width = src->plan_width;
5383 /* Assume the inserted node is not parallel-aware. */
5384 dest->parallel_aware = false;
5385 /* Assume the inserted node is parallel-safe, if child plan is. */
5386 dest->parallel_safe = src->parallel_safe;
5387}
Cost total_cost
Definition plannodes.h:205
Cost startup_cost
Definition plannodes.h:203
int plan_width
Definition plannodes.h:213
Cardinality plan_rows
Definition plannodes.h:211
int disabled_nodes
Definition plannodes.h:201

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

2157{
2158 Agg *plan;
2159 Plan *subplan;
2160 List *tlist;
2161 List *quals;
2162
2163 /*
2164 * Agg can project, so no need to be terribly picky about child tlist, but
2165 * we do need grouping columns to be available
2166 */
2167 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2168
2169 tlist = build_path_tlist(root, &best_path->path);
2170
2171 quals = order_qual_clauses(root, best_path->qual);
2172
2173 plan = make_agg(tlist, quals,
2174 best_path->aggstrategy,
2175 best_path->aggsplit,
2176 list_length(best_path->groupClause),
2177 extract_grouping_cols(best_path->groupClause,
2178 subplan->targetlist),
2179 extract_grouping_ops(best_path->groupClause),
2181 subplan->targetlist),
2182 NIL,
2183 NIL,
2184 best_path->numGroups,
2185 best_path->transitionSpace,
2186 subplan);
2187
2189
2190 return plan;
2191}
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
static void copy_generic_path_info(Plan *dest, Path *src)
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition createplan.c:390
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition createplan.c:817
Agg * make_agg(List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, List *groupingSets, List *chain, Cardinality numGroups, Size transitionSpace, Plan *lefttree)
#define CP_LABEL_TLIST
Definition createplan.c:71
static int list_length(const List *l)
Definition pg_list.h:152
Oid * extract_grouping_ops(List *groupClause)
Definition tlist.c:472
AttrNumber * extract_grouping_cols(List *groupClause, List *tlist)
Definition tlist.c:523
Oid * extract_grouping_collations(List *groupClause, List *tlist)
Definition tlist.c:498

References build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_cols(), extract_grouping_ops(), fb(), list_length(), make_agg(), NIL, order_qual_clauses(), plan, root, and Plan::targetlist.

Referenced by create_plan_recurse().

◆ create_append_plan()

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

Definition at line 1208 of file createplan.c.

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

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_incremental_sort, enable_partition_pruning, ERROR, extract_actual_clauses(), fb(), inject_projection_plan(), label_incrementalsort_with_costsize(), label_sort_with_costsize(), lappend(), lfirst, list_concat(), list_copy_head(), list_length(), list_make1, make_incrementalsort(), make_one_row_result(), make_partition_pruneinfo(), make_sort(), makeBoolConst(), makeNode, mark_async_capable_plan(), NIL, pathkeys_count_contained_in(), plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, replace_nestloop_params(), root, and subpath().

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

3044{
3045 Index baserelid = best_path->path.parent->relid;
3047 List *bitmapqualorig;
3048 List *indexquals;
3049 List *indexECs;
3050 List *qpqual;
3051 ListCell *l;
3053
3054 /* it should be a base rel... */
3055 Assert(baserelid > 0);
3056 Assert(best_path->path.parent->rtekind == RTE_RELATION);
3057
3058 /* Process the bitmapqual tree into a Plan tree and qual lists */
3060 &bitmapqualorig, &indexquals,
3061 &indexECs);
3062
3063 if (best_path->path.parallel_aware)
3065
3066 /*
3067 * The qpqual list must contain all restrictions not automatically handled
3068 * by the index, other than pseudoconstant clauses which will be handled
3069 * by a separate gating plan node. All the predicates in the indexquals
3070 * will be checked (either by the index itself, or by
3071 * nodeBitmapHeapscan.c), but if there are any "special" operators
3072 * involved then they must be added to qpqual. The upshot is that qpqual
3073 * must contain scan_clauses minus whatever appears in indexquals.
3074 *
3075 * This loop is similar to the comparable code in create_indexscan_plan(),
3076 * but with some differences because it has to compare the scan clauses to
3077 * stripped (no RestrictInfos) indexquals. See comments there for more
3078 * info.
3079 *
3080 * In normal cases simple equal() checks will be enough to spot duplicate
3081 * clauses, so we try that first. We next see if the scan clause is
3082 * redundant with any top-level indexqual by virtue of being generated
3083 * from the same EC. After that, try predicate_implied_by().
3084 *
3085 * Unlike create_indexscan_plan(), the predicate_implied_by() test here is
3086 * useful for getting rid of qpquals that are implied by index predicates,
3087 * because the predicate conditions are included in the "indexquals"
3088 * returned by create_bitmap_subplan(). Bitmap scans have to do it that
3089 * way because predicate conditions need to be rechecked if the scan
3090 * becomes lossy, so they have to be included in bitmapqualorig.
3091 */
3092 qpqual = NIL;
3093 foreach(l, scan_clauses)
3094 {
3096 Node *clause = (Node *) rinfo->clause;
3097
3098 if (rinfo->pseudoconstant)
3099 continue; /* we may drop pseudoconstants here */
3100 if (list_member(indexquals, clause))
3101 continue; /* simple duplicate */
3102 if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
3103 continue; /* derived from same EquivalenceClass */
3104 if (!contain_mutable_functions(clause) &&
3105 predicate_implied_by(list_make1(clause), indexquals, false))
3106 continue; /* provably implied by indexquals */
3107 qpqual = lappend(qpqual, rinfo);
3108 }
3109
3110 /* Sort clauses into best execution order */
3112
3113 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3115
3116 /*
3117 * When dealing with special operators, we will at this point have
3118 * duplicate clauses in qpqual and bitmapqualorig. We may as well drop
3119 * 'em from bitmapqualorig, since there's no point in making the tests
3120 * twice.
3121 */
3122 bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
3123
3124 /*
3125 * We have to replace any outer-relation variables with nestloop params in
3126 * the qpqual and bitmapqualorig expressions. (This was already done for
3127 * expressions attached to plan nodes in the bitmapqualplan tree.)
3128 */
3129 if (best_path->path.param_info)
3130 {
3131 qpqual = (List *)
3133 bitmapqualorig = (List *)
3134 replace_nestloop_params(root, (Node *) bitmapqualorig);
3135 }
3136
3137 /* Finally ready to build the plan node */
3139 qpqual,
3141 bitmapqualorig,
3142 baserelid);
3143
3144 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3145
3146 return scan_plan;
3147}
bool contain_mutable_functions(Node *clause)
Definition clauses.c:381
static Plan * create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
static BitmapHeapScan * make_bitmap_heapscan(List *qptlist, List *qpqual, Plan *lefttree, List *bitmapqualorig, Index scanrelid)
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
#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:154
Expr * clause
Definition pathnodes.h:2901

References Assert, bitmap_subplan_mark_shared(), RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), create_bitmap_subplan(), extract_actual_clauses(), fb(), lappend(), lfirst_node, list_difference_ptr(), list_make1, list_member(), list_member_ptr(), make_bitmap_heapscan(), NIL, order_qual_clauses(), predicate_implied_by(), replace_nestloop_params(), root, and RTE_RELATION.

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

3172{
3173 Plan *plan;
3174
3175 if (IsA(bitmapqual, BitmapAndPath))
3176 {
3177 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
3178 List *subplans = NIL;
3179 List *subquals = NIL;
3181 List *subindexECs = NIL;
3182 ListCell *l;
3183
3184 /*
3185 * There may well be redundant quals among the subplans, since a
3186 * top-level WHERE qual might have gotten used to form several
3187 * different index quals. We don't try exceedingly hard to eliminate
3188 * redundancies, but we do eliminate obvious duplicates by using
3189 * list_concat_unique.
3190 */
3191 foreach(l, apath->bitmapquals)
3192 {
3193 Plan *subplan;
3194 List *subqual;
3197
3198 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3200 &subindexEC);
3201 subplans = lappend(subplans, subplan);
3204 /* Duplicates in indexECs aren't worth getting rid of */
3206 }
3207 plan = (Plan *) make_bitmap_and(subplans);
3208 plan->startup_cost = apath->path.startup_cost;
3209 plan->total_cost = apath->path.total_cost;
3210 plan->plan_rows =
3211 clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
3212 plan->plan_width = 0; /* meaningless */
3213 plan->parallel_aware = false;
3214 plan->parallel_safe = apath->path.parallel_safe;
3215 *qual = subquals;
3216 *indexqual = subindexquals;
3218 }
3219 else if (IsA(bitmapqual, BitmapOrPath))
3220 {
3221 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
3222 List *subplans = NIL;
3223 List *subquals = NIL;
3225 bool const_true_subqual = false;
3226 bool const_true_subindexqual = false;
3227 ListCell *l;
3228
3229 /*
3230 * Here, we only detect qual-free subplans. A qual-free subplan would
3231 * cause us to generate "... OR true ..." which we may as well reduce
3232 * to just "true". We do not try to eliminate redundant subclauses
3233 * because (a) it's not as likely as in the AND case, and (b) we might
3234 * well be working with hundreds or even thousands of OR conditions,
3235 * perhaps from a long IN list. The performance of list_append_unique
3236 * would be unacceptable.
3237 */
3238 foreach(l, opath->bitmapquals)
3239 {
3240 Plan *subplan;
3241 List *subqual;
3244
3245 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3247 &subindexEC);
3248 subplans = lappend(subplans, subplan);
3249 if (subqual == NIL)
3250 const_true_subqual = true;
3251 else if (!const_true_subqual)
3254 if (subindexqual == NIL)
3256 else if (!const_true_subindexqual)
3259 }
3260
3261 /*
3262 * In the presence of ScalarArrayOpExpr quals, we might have built
3263 * BitmapOrPaths with just one subpath; don't add an OR step.
3264 */
3265 if (list_length(subplans) == 1)
3266 {
3267 plan = (Plan *) linitial(subplans);
3268 }
3269 else
3270 {
3271 plan = (Plan *) make_bitmap_or(subplans);
3272 plan->startup_cost = opath->path.startup_cost;
3273 plan->total_cost = opath->path.total_cost;
3274 plan->plan_rows =
3275 clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
3276 plan->plan_width = 0; /* meaningless */
3277 plan->parallel_aware = false;
3278 plan->parallel_safe = opath->path.parallel_safe;
3279 }
3280
3281 /*
3282 * If there were constant-TRUE subquals, the OR reduces to constant
3283 * TRUE. Also, avoid generating one-element ORs, which could happen
3284 * due to redundancy elimination or ScalarArrayOpExpr quals.
3285 */
3287 *qual = NIL;
3288 else if (list_length(subquals) <= 1)
3289 *qual = subquals;
3290 else
3293 *indexqual = NIL;
3294 else if (list_length(subindexquals) <= 1)
3295 *indexqual = subindexquals;
3296 else
3297 *indexqual = list_make1(make_orclause(subindexquals));
3298 *indexECs = NIL;
3299 }
3300 else if (IsA(bitmapqual, IndexPath))
3301 {
3302 IndexPath *ipath = (IndexPath *) bitmapqual;
3303 IndexScan *iscan;
3304 List *subquals;
3307 ListCell *l;
3308
3309 /* Use the regular indexscan plan build machinery... */
3310 iscan = castNode(IndexScan,
3312 NIL, NIL, false));
3313 /* then convert to a bitmap indexscan */
3315 iscan->indexid,
3316 iscan->indexqual,
3317 iscan->indexqualorig);
3318 /* and set its cost/width fields appropriately */
3319 plan->startup_cost = 0.0;
3320 plan->total_cost = ipath->indextotalcost;
3321 plan->plan_rows =
3322 clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
3323 plan->plan_width = 0; /* meaningless */
3324 plan->parallel_aware = false;
3325 plan->parallel_safe = ipath->path.parallel_safe;
3326 /* Extract original index clauses, actual index quals, relevant ECs */
3327 subquals = NIL;
3329 subindexECs = NIL;
3330 foreach(l, ipath->indexclauses)
3331 {
3333 RestrictInfo *rinfo = iclause->rinfo;
3334
3335 Assert(!rinfo->pseudoconstant);
3336 subquals = lappend(subquals, rinfo->clause);
3338 get_actual_clauses(iclause->indexquals));
3339 if (rinfo->parent_ec)
3340 subindexECs = lappend(subindexECs, rinfo->parent_ec);
3341 }
3342 /* We can add any index predicate conditions, too */
3343 foreach(l, ipath->indexinfo->indpred)
3344 {
3345 Expr *pred = (Expr *) lfirst(l);
3346
3347 /*
3348 * We know that the index predicate must have been implied by the
3349 * query condition as a whole, but it may or may not be implied by
3350 * the conditions that got pushed into the bitmapqual. Avoid
3351 * generating redundant conditions.
3352 */
3353 if (!predicate_implied_by(list_make1(pred), subquals, false))
3354 {
3355 subquals = lappend(subquals, pred);
3357 }
3358 }
3359 *qual = subquals;
3360 *indexqual = subindexquals;
3362 }
3363 else
3364 {
3365 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
3366 plan = NULL; /* keep compiler quiet */
3367 }
3368
3369 return plan;
3370}
double clamp_row_est(double nrows)
Definition costsize.c:214
static BitmapOr * make_bitmap_or(List *bitmapplans)
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
static BitmapAnd * make_bitmap_and(List *bitmapplans)
static Scan * create_indexscan_plan(PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, bool indexonly)
List * list_concat_unique(List *list1, const List *list2)
Definition list.c:1405
Expr * make_orclause(List *orclauses)
Definition makefuncs.c:743
Expr * make_ands_explicit(List *andclauses)
Definition makefuncs.c:799
#define castNode(_type_, nodeptr)
Definition nodes.h:182
List * get_actual_clauses(List *restrictinfo_list)
Scan scan
Definition plannodes.h:606
List * indexqualorig
Definition plannodes.h:612
Oid indexid
Definition plannodes.h:608
List * indexqual
Definition plannodes.h:610
Index scanrelid
Definition plannodes.h:544

References Assert, castNode, clamp_row_est(), RestrictInfo::clause, create_bitmap_subplan(), create_indexscan_plan(), elog, ERROR, fb(), get_actual_clauses(), IndexScan::indexid, IndexScan::indexqual, IndexScan::indexqualorig, 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, plan, predicate_implied_by(), root, IndexScan::scan, and Scan::scanrelid.

Referenced by create_bitmap_scan_plan(), and create_bitmap_subplan().

◆ create_ctescan_plan()

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

Definition at line 3729 of file createplan.c.

3731{
3733 Index scan_relid = best_path->parent->relid;
3736 int plan_id;
3737 int cte_param_id;
3739 Index levelsup;
3740 int ndx;
3741 ListCell *lc;
3742
3743 Assert(scan_relid > 0);
3745 Assert(rte->rtekind == RTE_CTE);
3746 Assert(!rte->self_reference);
3747
3748 /*
3749 * Find the referenced CTE, and locate the SubPlan previously made for it.
3750 */
3751 levelsup = rte->ctelevelsup;
3752 cteroot = root;
3753 while (levelsup-- > 0)
3754 {
3755 cteroot = cteroot->parent_root;
3756 if (!cteroot) /* shouldn't happen */
3757 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3758 }
3759
3760 /*
3761 * Note: cte_plan_ids can be shorter than cteList, if we are still working
3762 * on planning the CTEs (ie, this is a side-reference from another CTE).
3763 * So we mustn't use forboth here.
3764 */
3765 ndx = 0;
3766 foreach(lc, cteroot->parse->cteList)
3767 {
3769
3770 if (strcmp(cte->ctename, rte->ctename) == 0)
3771 break;
3772 ndx++;
3773 }
3774 if (lc == NULL) /* shouldn't happen */
3775 elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
3776 if (ndx >= list_length(cteroot->cte_plan_ids))
3777 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3778 plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
3779 if (plan_id <= 0)
3780 elog(ERROR, "no plan was made for CTE \"%s\"", rte->ctename);
3781 foreach(lc, cteroot->init_plans)
3782 {
3783 ctesplan = (SubPlan *) lfirst(lc);
3784 if (ctesplan->plan_id == plan_id)
3785 break;
3786 }
3787 if (lc == NULL) /* shouldn't happen */
3788 elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3789
3790 /*
3791 * We need the CTE param ID, which is the sole member of the SubPlan's
3792 * setParam list.
3793 */
3794 cte_param_id = linitial_int(ctesplan->setParam);
3795
3796 /* Sort clauses into best execution order */
3798
3799 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3801
3802 /* Replace any outer-relation variables with nestloop params */
3803 if (best_path->param_info)
3804 {
3805 scan_clauses = (List *)
3807 }
3808
3810 plan_id, cte_param_id);
3811
3813
3814 return scan_plan;
3815}
static CteScan * make_ctescan(List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
@ RTE_CTE
#define planner_rt_fetch(rti, root)
Definition pathnodes.h:704
#define linitial_int(l)
Definition pg_list.h:179
static int list_nth_int(const List *list, int n)
Definition pg_list.h:342

References Assert, copy_generic_path_info(), CommonTableExpr::ctename, elog, ERROR, extract_actual_clauses(), fb(), lfirst, linitial_int, list_length(), list_nth_int(), make_ctescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_CTE.

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

4118{
4119 CustomScan *cplan;
4120 RelOptInfo *rel = best_path->path.parent;
4121 List *custom_plans = NIL;
4122 ListCell *lc;
4123
4124 /* Recursively transform child paths. */
4125 foreach(lc, best_path->custom_paths)
4126 {
4129
4130 custom_plans = lappend(custom_plans, plan);
4131 }
4132
4133 /*
4134 * Sort clauses into the best execution order, although custom-scan
4135 * provider can reorder them again.
4136 */
4138
4139 /*
4140 * Invoke custom plan provider to create the Plan node represented by the
4141 * CustomPath.
4142 */
4143 cplan = castNode(CustomScan,
4144 best_path->methods->PlanCustomPath(root,
4145 rel,
4146 best_path,
4147 tlist,
4149 custom_plans));
4150
4151 /*
4152 * Copy cost data from Path to Plan; no need to make custom-plan providers
4153 * do this
4154 */
4155 copy_generic_path_info(&cplan->scan.plan, &best_path->path);
4156
4157 /* Likewise, copy the relids that are represented by this custom scan */
4158 cplan->custom_relids = best_path->path.parent->relids;
4159
4160 /*
4161 * Replace any outer-relation variables with nestloop params in the qual
4162 * and custom_exprs expressions. We do this last so that the custom-plan
4163 * provider doesn't have to be involved. (Note that parts of custom_exprs
4164 * could have come from join clauses, so doing this beforehand on the
4165 * scan_clauses wouldn't work.) We assume custom_scan_tlist contains no
4166 * such variables.
4167 */
4168 if (best_path->path.param_info)
4169 {
4170 cplan->scan.plan.qual = (List *)
4171 replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
4172 cplan->custom_exprs = (List *)
4174 }
4175
4176 return cplan;
4177}
Bitmapset * custom_relids
Definition plannodes.h:946
List * custom_exprs
Definition plannodes.h:940
const struct CustomScanMethods * methods
Definition plannodes.h:953

References castNode, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), CustomScan::custom_exprs, CustomScan::custom_relids, fb(), lappend(), lfirst, CustomScan::methods, NIL, order_qual_clauses(), plan, 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 3961 of file createplan.c.

3963{
3965 RelOptInfo *rel = best_path->path.parent;
3966 Index scan_relid = rel->relid;
3968 Plan *outer_plan = NULL;
3969
3970 Assert(rel->fdwroutine != NULL);
3971
3972 /* transform the child path if any */
3973 if (best_path->fdw_outerpath)
3974 outer_plan = create_plan_recurse(root, best_path->fdw_outerpath,
3976
3977 /*
3978 * If we're scanning a base relation, fetch its OID. (Irrelevant if
3979 * scanning a join relation.)
3980 */
3981 if (scan_relid > 0)
3982 {
3984
3985 Assert(rel->rtekind == RTE_RELATION);
3987 Assert(rte->rtekind == RTE_RELATION);
3988 rel_oid = rte->relid;
3989 }
3990
3991 /*
3992 * Sort clauses into best execution order. We do this first since the FDW
3993 * might have more info than we do and wish to adjust the ordering.
3994 */
3996
3997 /*
3998 * Let the FDW perform its processing on the restriction clauses and
3999 * generate the plan node. Note that the FDW might remove restriction
4000 * clauses that it intends to execute remotely, or even add more (if it
4001 * has selected some join clauses for remote use but also wants them
4002 * rechecked locally).
4003 */
4004 scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid,
4005 best_path,
4006 tlist, scan_clauses,
4007 outer_plan);
4008
4009 /* Copy cost data from Path to Plan; no need to make FDW do this */
4010 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
4011
4012 /* Copy user OID to access as; likewise no need to make FDW do this */
4013 scan_plan->checkAsUser = rel->userid;
4014
4015 /* Copy foreign server OID; likewise, no need to make FDW do this */
4016 scan_plan->fs_server = rel->serverid;
4017
4018 /*
4019 * Likewise, copy the relids that are represented by this foreign scan. An
4020 * upper rel doesn't have relids set, but it covers all the relations
4021 * participating in the underlying scan/join, so use root->all_query_rels.
4022 */
4023 if (rel->reloptkind == RELOPT_UPPER_REL)
4024 scan_plan->fs_relids = root->all_query_rels;
4025 else
4026 scan_plan->fs_relids = best_path->path.parent->relids;
4027
4028 /*
4029 * Join relid sets include relevant outer joins, but FDWs may need to know
4030 * which are the included base rels. That's a bit tedious to get without
4031 * access to the plan-time data structures, so compute it here.
4032 */
4033 scan_plan->fs_base_relids = bms_difference(scan_plan->fs_relids,
4034 root->outer_join_rels);
4035
4036 /*
4037 * If this is a foreign join, and to make it valid to push down we had to
4038 * assume that the current user is the same as some user explicitly named
4039 * in the query, mark the finished plan as depending on the current user.
4040 */
4041 if (rel->useridiscurrent)
4042 root->glob->dependsOnRole = true;
4043
4044 /*
4045 * Replace any outer-relation variables with nestloop params in the qual,
4046 * fdw_exprs and fdw_recheck_quals expressions. We do this last so that
4047 * the FDW doesn't have to be involved. (Note that parts of fdw_exprs or
4048 * fdw_recheck_quals could have come from join clauses, so doing this
4049 * beforehand on the scan_clauses wouldn't work.) We assume
4050 * fdw_scan_tlist contains no such variables.
4051 */
4052 if (best_path->path.param_info)
4053 {
4054 scan_plan->scan.plan.qual = (List *)
4055 replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
4056 scan_plan->fdw_exprs = (List *)
4057 replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
4058 scan_plan->fdw_recheck_quals = (List *)
4060 (Node *) scan_plan->fdw_recheck_quals);
4061 }
4062
4063 /*
4064 * If rel is a base relation, detect whether any system columns are
4065 * requested from the rel. (If rel is a join relation, rel->relid will be
4066 * 0, but there can be no Var with relid 0 in the rel's targetlist or the
4067 * restriction clauses, so we skip this in that case. Note that any such
4068 * columns in base relations that were joined are assumed to be contained
4069 * in fdw_scan_tlist.) This is a bit of a kluge and might go away
4070 * someday, so we intentionally leave it out of the API presented to FDWs.
4071 */
4072 scan_plan->fsSystemCol = false;
4073 if (scan_relid > 0)
4074 {
4075 Bitmapset *attrs_used = NULL;
4076 ListCell *lc;
4077 int i;
4078
4079 /*
4080 * First, examine all the attributes needed for joins or final output.
4081 * Note: we must look at rel's targetlist, not the attr_needed data,
4082 * because attr_needed isn't computed for inheritance child rels.
4083 */
4084 pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used);
4085
4086 /* Add all the attributes used by restriction clauses. */
4087 foreach(lc, rel->baserestrictinfo)
4088 {
4089 RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
4090
4091 pull_varattnos((Node *) rinfo->clause, scan_relid, &attrs_used);
4092 }
4093
4094 /* Now, are any system columns requested from rel? */
4095 for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
4096 {
4098 {
4099 scan_plan->fsSystemCol = true;
4100 break;
4101 }
4102 }
4103
4104 bms_free(attrs_used);
4105 }
4106
4107 return scan_plan;
4108}
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:346
void bms_free(Bitmapset *a)
Definition bitmapset.c:239
bool bms_is_member(int x, const Bitmapset *a)
Definition bitmapset.c:510
int i
Definition isn.c:77
@ RELOPT_UPPER_REL
Definition pathnodes.h:981
#define InvalidOid
List * exprs
Definition pathnodes.h:1878
bool useridiscurrent
Definition pathnodes.h:1115
struct PathTarget * reltarget
Definition pathnodes.h:1045
Index relid
Definition pathnodes.h:1069
RelOptKind reloptkind
Definition pathnodes.h:1015
RTEKind rtekind
Definition pathnodes.h:1073
#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(), RestrictInfo::clause, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), PathTarget::exprs, fb(), FirstLowInvalidHeapAttributeNumber, i, InvalidOid, lfirst, order_qual_clauses(), planner_rt_fetch, pull_varattnos(), RelOptInfo::relid, RELOPT_UPPER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, replace_nestloop_params(), root, RTE_RELATION, RelOptInfo::rtekind, 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 3599 of file createplan.c.

3601{
3603 Index scan_relid = best_path->parent->relid;
3605 List *functions;
3606
3607 /* it should be a function base rel... */
3608 Assert(scan_relid > 0);
3610 Assert(rte->rtekind == RTE_FUNCTION);
3611 functions = rte->functions;
3612
3613 /* Sort clauses into best execution order */
3615
3616 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3618
3619 /* Replace any outer-relation variables with nestloop params */
3620 if (best_path->param_info)
3621 {
3622 scan_clauses = (List *)
3624 /* The function expressions could contain nestloop params, too */
3626 }
3627
3629 functions, rte->funcordinality);
3630
3632
3633 return scan_plan;
3634}
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
@ RTE_FUNCTION
static const struct fns functions
Definition regcomp.c:358

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), functions, make_functionscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_FUNCTION.

Referenced by create_scan_plan().

◆ create_gather_merge_plan()

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

Definition at line 1803 of file createplan.c.

1804{
1806 Plan *subplan;
1807 List *pathkeys = best_path->path.pathkeys;
1808 List *tlist = build_path_tlist(root, &best_path->path);
1809
1810 /* As with Gather, project away columns in the workers. */
1811 subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1812
1813 /* Create a shell for a GatherMerge plan. */
1815 gm_plan->plan.targetlist = tlist;
1816 gm_plan->num_workers = best_path->num_workers;
1818
1819 /* Assign the rescan Param. */
1820 gm_plan->rescan_param = assign_special_exec_param(root);
1821
1822 /* Gather Merge is pointless with no pathkeys; use Gather instead. */
1823 Assert(pathkeys != NIL);
1824
1825 /* Compute sort column info, and adjust subplan's tlist as needed */
1826 subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1827 best_path->subpath->parent->relids,
1828 gm_plan->sortColIdx,
1829 false,
1830 &gm_plan->numCols,
1831 &gm_plan->sortColIdx,
1832 &gm_plan->sortOperators,
1833 &gm_plan->collations,
1834 &gm_plan->nullsFirst);
1835
1836 /*
1837 * All gather merge paths should have already guaranteed the necessary
1838 * sort order. See create_gather_merge_path.
1839 */
1840 Assert(pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys));
1841
1842 /* Now insert the subplan under GatherMerge. */
1843 gm_plan->plan.lefttree = subplan;
1844
1845 /* use parallel mode for parallel plans. */
1846 root->glob->parallelModeNeeded = true;
1847
1848 return gm_plan;
1849}
int assign_special_exec_param(PlannerInfo *root)
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition pathkeys.c:343

References Assert, assign_special_exec_param(), build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), fb(), makeNode, NIL, pathkeys_contained_in(), prepare_sort_from_pathkeys(), and root.

Referenced by create_plan_recurse().

◆ create_gather_plan()

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

Definition at line 1765 of file createplan.c.

1766{
1768 Plan *subplan;
1769 List *tlist;
1770
1771 /*
1772 * Push projection down to the child node. That way, the projection work
1773 * is parallelized, and there can be no system columns in the result (they
1774 * can't travel through a tuple queue because it uses MinimalTuple
1775 * representation).
1776 */
1777 subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1778
1779 tlist = build_path_tlist(root, &best_path->path);
1780
1781 gather_plan = make_gather(tlist,
1782 NIL,
1783 best_path->num_workers,
1785 best_path->single_copy,
1786 subplan);
1787
1789
1790 /* use parallel mode for parallel plans. */
1791 root->glob->parallelModeNeeded = true;
1792
1793 return gather_plan;
1794}
static Gather * make_gather(List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)

References assign_special_exec_param(), build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), fb(), make_gather(), NIL, and root.

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

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

References Assert, build_path_tlist(), copy_plan_costsize(), fb(), IsA, Plan::lefttree, make_gating_result(), Path::parallel_safe, Plan::parallel_safe, Result::plan, plan, Result::relids, Result::result_type, and root.

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

2082{
2083 Group *plan;
2084 Plan *subplan;
2085 List *tlist;
2086 List *quals;
2087
2088 /*
2089 * Group can project, so no need to be terribly picky about child tlist,
2090 * but we do need grouping columns to be available
2091 */
2092 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2093
2094 tlist = build_path_tlist(root, &best_path->path);
2095
2096 quals = order_qual_clauses(root, best_path->qual);
2097
2098 plan = make_group(tlist,
2099 quals,
2100 list_length(best_path->groupClause),
2101 extract_grouping_cols(best_path->groupClause,
2102 subplan->targetlist),
2103 extract_grouping_ops(best_path->groupClause),
2105 subplan->targetlist),
2106 subplan);
2107
2109
2110 return plan;
2111}
static Group * make_group(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, Plan *lefttree)

References build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_cols(), extract_grouping_ops(), fb(), list_length(), make_group(), order_qual_clauses(), plan, root, 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 1632 of file createplan.c.

1633{
1634 Result *plan;
1635 List *tlist;
1636 List *quals;
1637
1638 tlist = build_path_tlist(root, &best_path->path);
1639
1640 /* best_path->quals is just bare clauses */
1641 quals = order_qual_clauses(root, best_path->quals);
1642
1643 plan = make_one_row_result(tlist, (Node *) quals, best_path->path.parent);
1644
1646
1647 return plan;
1648}

References build_path_tlist(), copy_generic_path_info(), fb(), make_one_row_result(), order_qual_clauses(), plan, and root.

Referenced by create_plan_recurse().

◆ create_groupingsets_plan()

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

Definition at line 2240 of file createplan.c.

2241{
2242 Agg *plan;
2243 Plan *subplan;
2244 List *rollups = best_path->rollups;
2246 int maxref;
2247 List *chain;
2248 ListCell *lc;
2249
2250 /* Shouldn't get here without grouping sets */
2251 Assert(root->parse->groupingSets);
2252 Assert(rollups != NIL);
2253
2254 /*
2255 * Agg can project, so no need to be terribly picky about child tlist, but
2256 * we do need grouping columns to be available
2257 */
2258 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2259
2260 /*
2261 * Compute the mapping from tleSortGroupRef to column index in the child's
2262 * tlist. First, identify max SortGroupRef in groupClause, for array
2263 * sizing.
2264 */
2265 maxref = 0;
2266 foreach(lc, root->processed_groupClause)
2267 {
2269
2270 if (gc->tleSortGroupRef > maxref)
2272 }
2273
2274 grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
2275
2276 /* Now look up the column numbers in the child's tlist */
2277 foreach(lc, root->processed_groupClause)
2278 {
2281
2282 grouping_map[gc->tleSortGroupRef] = tle->resno;
2283 }
2284
2285 /*
2286 * During setrefs.c, we'll need the grouping_map to fix up the cols lists
2287 * in GroupingFunc nodes. Save it for setrefs.c to use.
2288 */
2289 Assert(root->grouping_map == NULL);
2290 root->grouping_map = grouping_map;
2291
2292 /*
2293 * Generate the side nodes that describe the other sort and group
2294 * operations besides the top one. Note that we don't worry about putting
2295 * accurate cost estimates in the side nodes; only the topmost Agg node's
2296 * costs will be shown by EXPLAIN.
2297 */
2298 chain = NIL;
2299 if (list_length(rollups) > 1)
2300 {
2301 bool is_first_sort = ((RollupData *) linitial(rollups))->is_hashed;
2302
2303 for_each_from(lc, rollups, 1)
2304 {
2307 Plan *sort_plan = NULL;
2308 Plan *agg_plan;
2310
2311 new_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2312
2313 if (!rollup->is_hashed && !is_first_sort)
2314 {
2315 sort_plan = (Plan *)
2316 make_sort_from_groupcols(rollup->groupClause,
2318 subplan);
2319 }
2320
2321 if (!rollup->is_hashed)
2322 is_first_sort = false;
2323
2324 if (rollup->is_hashed)
2325 strat = AGG_HASHED;
2326 else if (linitial(rollup->gsets) == NIL)
2327 strat = AGG_PLAIN;
2328 else
2329 strat = AGG_SORTED;
2330
2331 agg_plan = (Plan *) make_agg(NIL,
2332 NIL,
2333 strat,
2335 list_length((List *) linitial(rollup->gsets)),
2337 extract_grouping_ops(rollup->groupClause),
2338 extract_grouping_collations(rollup->groupClause, subplan->targetlist),
2339 rollup->gsets,
2340 NIL,
2341 rollup->numGroups,
2342 best_path->transitionSpace,
2343 sort_plan);
2344
2345 /*
2346 * Remove stuff we don't need to avoid bloating debug output.
2347 */
2348 if (sort_plan)
2349 {
2350 sort_plan->targetlist = NIL;
2351 sort_plan->lefttree = NULL;
2352 }
2353
2354 chain = lappend(chain, agg_plan);
2355 }
2356 }
2357
2358 /*
2359 * Now make the real Agg node
2360 */
2361 {
2362 RollupData *rollup = linitial(rollups);
2364 int numGroupCols;
2365
2366 top_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2367
2369
2371 best_path->qual,
2372 best_path->aggstrategy,
2376 extract_grouping_ops(rollup->groupClause),
2377 extract_grouping_collations(rollup->groupClause, subplan->targetlist),
2378 rollup->gsets,
2379 chain,
2380 rollup->numGroups,
2381 best_path->transitionSpace,
2382 subplan);
2383
2384 /* Copy cost data from Path to Plan */
2385 copy_generic_path_info(&plan->plan, &best_path->path);
2386 }
2387
2388 return (Plan *) plan;
2389}
static AttrNumber * remap_groupColIdx(PlannerInfo *root, List *groupClause)
static Sort * make_sort_from_groupcols(List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
void * palloc0(Size size)
Definition mcxt.c:1417
AggStrategy
Definition nodes.h:363
@ AGG_SORTED
Definition nodes.h:365
@ AGG_HASHED
Definition nodes.h:366
@ AGG_PLAIN
Definition nodes.h:364
@ AGGSPLIT_SIMPLE
Definition nodes.h:387
#define for_each_from(cell, lst, N)
Definition pg_list.h:446
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition tlist.c:376

References AGG_HASHED, AGG_PLAIN, AGG_SORTED, AGGSPLIT_SIMPLE, Assert, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_collations(), extract_grouping_ops(), fb(), for_each_from, get_sortgroupclause_tle(), lappend(), lfirst, linitial, list_length(), make_agg(), make_sort_from_groupcols(), NIL, palloc0(), plan, remap_groupColIdx(), root, Plan::targetlist, and SortGroupClause::tleSortGroupRef.

Referenced by create_plan_recurse().

◆ create_hashjoin_plan()

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

Definition at line 4693 of file createplan.c.

4695{
4697 Hash *hash_plan;
4698 Plan *outer_plan;
4699 Plan *inner_plan;
4700 List *tlist = build_path_tlist(root, &best_path->jpath.path);
4701 List *joinclauses;
4703 List *hashclauses;
4704 List *hashoperators = NIL;
4705 List *hashcollations = NIL;
4708 Oid skewTable = InvalidOid;
4709 AttrNumber skewColumn = InvalidAttrNumber;
4710 bool skewInherit = false;
4711 ListCell *lc;
4712
4713 /*
4714 * HashJoin can project, so we don't have to demand exact tlists from the
4715 * inputs. However, it's best to request a small tlist from the inner
4716 * side, so that we aren't storing more data than necessary. Likewise, if
4717 * we anticipate batching, request a small tlist from the outer side so
4718 * that we don't put extra data in the outer batch files.
4719 */
4720 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4721 (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
4722
4723 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4725
4726 /* Sort join qual clauses into best execution order */
4727 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4728 /* There's no point in sorting the hash clauses ... */
4729
4730 /* Get the join qual clauses (in plain expression form) */
4731 /* Any pseudoconstant clauses are ignored here */
4732 if (IS_OUTER_JOIN(best_path->jpath.jointype))
4733 {
4734 extract_actual_join_clauses(joinclauses,
4735 best_path->jpath.path.parent->relids,
4736 &joinclauses, &otherclauses);
4737 }
4738 else
4739 {
4740 /* We can treat all clauses alike for an inner join */
4741 joinclauses = extract_actual_clauses(joinclauses, false);
4742 otherclauses = NIL;
4743 }
4744
4745 /*
4746 * Remove the hashclauses from the list of join qual clauses, leaving the
4747 * list of quals that must be checked as qpquals.
4748 */
4749 hashclauses = get_actual_clauses(best_path->path_hashclauses);
4750 joinclauses = list_difference(joinclauses, hashclauses);
4751
4752 /*
4753 * Replace any outer-relation variables with nestloop params. There
4754 * should not be any in the hashclauses.
4755 */
4756 if (best_path->jpath.path.param_info)
4757 {
4758 joinclauses = (List *)
4759 replace_nestloop_params(root, (Node *) joinclauses);
4760 otherclauses = (List *)
4762 }
4763
4764 /*
4765 * Rearrange hashclauses, if needed, so that the outer variable is always
4766 * on the left.
4767 */
4768 hashclauses = get_switched_clauses(best_path->path_hashclauses,
4769 best_path->jpath.outerjoinpath->parent->relids);
4770
4771 /*
4772 * If there is a single join clause and we can identify the outer variable
4773 * as a simple column reference, supply its identity for possible use in
4774 * skew optimization. (Note: in principle we could do skew optimization
4775 * with multiple join clauses, but we'd have to be able to determine the
4776 * most common combinations of outer values, which we don't currently have
4777 * enough stats for.)
4778 */
4779 if (list_length(hashclauses) == 1)
4780 {
4781 OpExpr *clause = (OpExpr *) linitial(hashclauses);
4782 Node *node;
4783
4784 Assert(is_opclause(clause));
4785 node = (Node *) linitial(clause->args);
4786 if (IsA(node, RelabelType))
4787 node = (Node *) ((RelabelType *) node)->arg;
4788 if (IsA(node, Var))
4789 {
4790 Var *var = (Var *) node;
4792
4793 rte = root->simple_rte_array[var->varno];
4794 if (rte->rtekind == RTE_RELATION)
4795 {
4796 skewTable = rte->relid;
4797 skewColumn = var->varattno;
4798 skewInherit = rte->inh;
4799 }
4800 }
4801 }
4802
4803 /*
4804 * Collect hash related information. The hashed expressions are
4805 * deconstructed into outer/inner expressions, so they can be computed
4806 * separately (inner expressions are used to build the hashtable via Hash,
4807 * outer expressions to perform lookups of tuples from HashJoin's outer
4808 * plan in the hashtable). Also collect operator information necessary to
4809 * build the hashtable.
4810 */
4811 foreach(lc, hashclauses)
4812 {
4814
4815 hashoperators = lappend_oid(hashoperators, hclause->opno);
4816 hashcollations = lappend_oid(hashcollations, hclause->inputcollid);
4819 }
4820
4821 /*
4822 * Build the hash node and hash join node.
4823 */
4824 hash_plan = make_hash(inner_plan,
4826 skewTable,
4827 skewColumn,
4828 skewInherit);
4829
4830 /*
4831 * Set Hash node's startup & total costs equal to total cost of input
4832 * plan; this only affects EXPLAIN display not decisions.
4833 */
4834 copy_plan_costsize(&hash_plan->plan, inner_plan);
4835 hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
4836
4837 /*
4838 * If parallel-aware, the executor will also need an estimate of the total
4839 * number of rows expected from all participants so that it can size the
4840 * shared hash table.
4841 */
4842 if (best_path->jpath.path.parallel_aware)
4843 {
4844 hash_plan->plan.parallel_aware = true;
4845 hash_plan->rows_total = best_path->inner_rows_total;
4846 }
4847
4848 join_plan = make_hashjoin(tlist,
4849 joinclauses,
4851 hashclauses,
4852 hashoperators,
4853 hashcollations,
4855 outer_plan,
4856 (Plan *) hash_plan,
4857 best_path->jpath.jointype,
4858 best_path->jpath.inner_unique);
4859
4860 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4861
4862 return join_plan;
4863}
#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)
static List * get_switched_clauses(List *clauses, Relids outerrelids)
static Hash * make_hash(Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
List * list_difference(const List *list1, const List *list2)
Definition list.c:1237
List * lappend_oid(List *list, Oid datum)
Definition list.c:375
static bool is_opclause(const void *clause)
Definition nodeFuncs.h:76
#define IS_OUTER_JOIN(jointype)
Definition nodes.h:348
#define lsecond(l)
Definition pg_list.h:183
void extract_actual_join_clauses(List *restrictinfo_list, Relids joinrelids, List **joinquals, List **otherquals)
List * args
Definition primnodes.h:869
AttrNumber varattno
Definition primnodes.h:275
int varno
Definition primnodes.h:270

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(), fb(), get_actual_clauses(), get_switched_clauses(), InvalidAttrNumber, InvalidOid, is_opclause(), IS_OUTER_JOIN, IsA, lappend(), lappend_oid(), lfirst_node, linitial, list_difference(), list_length(), lsecond, make_hash(), make_hashjoin(), NIL, order_qual_clauses(), replace_nestloop_params(), root, RTE_RELATION, 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 2054 of file createplan.c.

2056{
2058 Plan *subplan;
2059
2060 /* See comments in create_sort_plan() above */
2061 subplan = create_plan_recurse(root, best_path->spath.subpath,
2062 flags | CP_SMALL_TLIST);
2064 best_path->spath.path.pathkeys,
2065 IS_OTHER_REL(best_path->spath.subpath->parent) ?
2066 best_path->spath.path.parent->relids : NULL,
2067 best_path->nPresortedCols);
2068
2069 copy_generic_path_info(&plan->sort.plan, (Path *) best_path);
2070
2071 return plan;
2072}
static IncrementalSort * make_incrementalsort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
#define IS_OTHER_REL(rel)
Definition pathnodes.h:1004

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), fb(), IS_OTHER_REL, make_incrementalsort_from_pathkeys(), plan, and root.

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

2849{
2850 Scan *scan_plan;
2851 List *indexclauses = best_path->indexclauses;
2852 List *indexorderbys = best_path->indexorderbys;
2853 Index baserelid = best_path->path.parent->relid;
2854 IndexOptInfo *indexinfo = best_path->indexinfo;
2855 Oid indexoid = indexinfo->indexoid;
2856 List *qpqual;
2860 List *indexorderbyops = NIL;
2861 ListCell *l;
2862
2863 /* it should be a base rel... */
2864 Assert(baserelid > 0);
2865 Assert(best_path->path.parent->rtekind == RTE_RELATION);
2866 /* check the scan direction is valid */
2867 Assert(best_path->indexscandir == ForwardScanDirection ||
2868 best_path->indexscandir == BackwardScanDirection);
2869
2870 /*
2871 * Extract the index qual expressions (stripped of RestrictInfos) from the
2872 * IndexClauses list, and prepare a copy with index Vars substituted for
2873 * table Vars. (This step also does replace_nestloop_params on the
2874 * fixed_indexquals.)
2875 */
2879
2880 /*
2881 * Likewise fix up index attr references in the ORDER BY expressions.
2882 */
2884
2885 /*
2886 * The qpqual list must contain all restrictions not automatically handled
2887 * by the index, other than pseudoconstant clauses which will be handled
2888 * by a separate gating plan node. All the predicates in the indexquals
2889 * will be checked (either by the index itself, or by nodeIndexscan.c),
2890 * but if there are any "special" operators involved then they must be
2891 * included in qpqual. The upshot is that qpqual must contain
2892 * scan_clauses minus whatever appears in indexquals.
2893 *
2894 * is_redundant_with_indexclauses() detects cases where a scan clause is
2895 * present in the indexclauses list or is generated from the same
2896 * EquivalenceClass as some indexclause, and is therefore redundant with
2897 * it, though not equal. (The latter happens when indxpath.c prefers a
2898 * different derived equality than what generate_join_implied_equalities
2899 * picked for a parameterized scan's ppi_clauses.) Note that it will not
2900 * match to lossy index clauses, which is critical because we have to
2901 * include the original clause in qpqual in that case.
2902 *
2903 * In some situations (particularly with OR'd index conditions) we may
2904 * have scan_clauses that are not equal to, but are logically implied by,
2905 * the index quals; so we also try a predicate_implied_by() check to see
2906 * if we can discard quals that way. (predicate_implied_by assumes its
2907 * first input contains only immutable functions, so we have to check
2908 * that.)
2909 *
2910 * Note: if you change this bit of code you should also look at
2911 * extract_nonindex_conditions() in costsize.c.
2912 */
2913 qpqual = NIL;
2914 foreach(l, scan_clauses)
2915 {
2917
2918 if (rinfo->pseudoconstant)
2919 continue; /* we may drop pseudoconstants here */
2920 if (is_redundant_with_indexclauses(rinfo, indexclauses))
2921 continue; /* dup or derived from same EquivalenceClass */
2922 if (!contain_mutable_functions((Node *) rinfo->clause) &&
2924 false))
2925 continue; /* provably implied by indexquals */
2926 qpqual = lappend(qpqual, rinfo);
2927 }
2928
2929 /* Sort clauses into best execution order */
2931
2932 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2934
2935 /*
2936 * We have to replace any outer-relation variables with nestloop params in
2937 * the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
2938 * annoying to have to do this separately from the processing in
2939 * fix_indexqual_references --- rethink this when generalizing the inner
2940 * indexscan support. But note we can't really do this earlier because
2941 * it'd break the comparisons to predicates above ... (or would it? Those
2942 * wouldn't have outer refs)
2943 */
2944 if (best_path->path.param_info)
2945 {
2948 qpqual = (List *)
2950 indexorderbys = (List *)
2951 replace_nestloop_params(root, (Node *) indexorderbys);
2952 }
2953
2954 /*
2955 * If there are ORDER BY expressions, look up the sort operators for their
2956 * result datatypes.
2957 */
2958 if (indexorderbys)
2959 {
2961 *exprCell;
2962
2963 /*
2964 * PathKey contains OID of the btree opfamily we're sorting by, but
2965 * that's not quite enough because we need the expression's datatype
2966 * to look up the sort operator in the operator family.
2967 */
2968 Assert(list_length(best_path->path.pathkeys) == list_length(indexorderbys));
2969 forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
2970 {
2972 Node *expr = (Node *) lfirst(exprCell);
2973 Oid exprtype = exprType(expr);
2974 Oid sortop;
2975
2976 /* Get sort operator from opfamily */
2977 sortop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
2978 exprtype,
2979 exprtype,
2980 pathkey->pk_cmptype);
2981 if (!OidIsValid(sortop))
2982 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
2983 pathkey->pk_cmptype, exprtype, exprtype, pathkey->pk_opfamily);
2984 indexorderbyops = lappend_oid(indexorderbyops, sortop);
2985 }
2986 }
2987
2988 /*
2989 * For an index-only scan, we must mark indextlist entries as resjunk if
2990 * they are columns that the index AM can't return; this cues setrefs.c to
2991 * not generate references to those columns.
2992 */
2993 if (indexonly)
2994 {
2995 int i = 0;
2996
2997 foreach(l, indexinfo->indextlist)
2998 {
3000
3001 indextle->resjunk = !indexinfo->canreturn[i];
3002 i++;
3003 }
3004 }
3005
3006 /* Finally ready to build the plan node */
3007 if (indexonly)
3008 scan_plan = (Scan *) make_indexonlyscan(tlist,
3009 qpqual,
3010 baserelid,
3011 indexoid,
3015 indexinfo->indextlist,
3016 best_path->indexscandir);
3017 else
3018 scan_plan = (Scan *) make_indexscan(tlist,
3019 qpqual,
3020 baserelid,
3021 indexoid,
3025 indexorderbys,
3026 indexorderbyops,
3027 best_path->indexscandir);
3028
3030
3031 return scan_plan;
3032}
#define OidIsValid(objectId)
Definition c.h:858
static void fix_indexqual_references(PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
static IndexOnlyScan * make_indexonlyscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *recheckqual, List *indexorderby, List *indextlist, ScanDirection indexscandir)
static IndexScan * make_indexscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig, List *indexorderby, List *indexorderbyorig, List *indexorderbyops, ScanDirection indexscandir)
bool is_redundant_with_indexclauses(RestrictInfo *rinfo, List *indexclauses)
Oid get_opfamily_member_for_cmptype(Oid opfamily, Oid lefttype, Oid righttype, CompareType cmptype)
Definition lsyscache.c:199
Oid exprType(const Node *expr)
Definition nodeFuncs.c:42
#define forboth(cell1, list1, cell2, list2)
Definition pg_list.h:550
@ BackwardScanDirection
Definition sdir.h:26
@ ForwardScanDirection
Definition sdir.h:28
List * indextlist
Definition pathnodes.h:1410

References Assert, BackwardScanDirection, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), elog, ERROR, exprType(), extract_actual_clauses(), fb(), fix_indexorderby_references(), fix_indexqual_references(), forboth, ForwardScanDirection, get_opfamily_member_for_cmptype(), i, IndexOptInfo::indexoid, 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(), 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 1073 of file createplan.c.

1074{
1075 Plan *plan;
1077
1078 switch (best_path->path.pathtype)
1079 {
1080 case T_MergeJoin:
1082 (MergePath *) best_path);
1083 break;
1084 case T_HashJoin:
1086 (HashPath *) best_path);
1087 break;
1088 case T_NestLoop:
1090 (NestPath *) best_path);
1091 break;
1092 default:
1093 elog(ERROR, "unrecognized node type: %d",
1094 (int) best_path->path.pathtype);
1095 plan = NULL; /* keep compiler quiet */
1096 break;
1097 }
1098
1099 /*
1100 * If there are any pseudoconstant clauses attached to this node, insert a
1101 * gating Result node that evaluates the pseudoconstants as one-time
1102 * quals.
1103 */
1104 gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
1105 if (gating_clauses)
1108
1109#ifdef NOT_USED
1110
1111 /*
1112 * * Expensive function pullups may have pulled local predicates * into
1113 * this path node. Put them in the qpqual of the plan node. * JMH,
1114 * 6/15/92
1115 */
1120#endif
1121
1122 return plan;
1123}
static HashJoin * create_hashjoin_plan(PlannerInfo *root, HashPath *best_path)
static MergeJoin * create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
static Plan * create_gating_plan(PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
static List * get_gating_quals(PlannerInfo *root, List *quals)
Definition createplan.c:994
static NestLoop * create_nestloop_plan(PlannerInfo *root, NestPath *best_path)

References create_gating_plan(), create_hashjoin_plan(), create_mergejoin_plan(), create_nestloop_plan(), elog, ERROR, fb(), get_actual_clauses(), get_gating_quals(), 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 2694 of file createplan.c.

2695{
2696 Limit *plan;
2697 Plan *subplan;
2698 int numUniqkeys = 0;
2702
2703 /* Limit doesn't project, so tlist requirements pass through */
2704 subplan = create_plan_recurse(root, best_path->subpath, flags);
2705
2706 /* Extract information necessary for comparing rows for WITH TIES. */
2707 if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
2708 {
2709 Query *parse = root->parse;
2710 ListCell *l;
2711
2712 numUniqkeys = list_length(parse->sortClause);
2714 uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2715 uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2716
2717 numUniqkeys = 0;
2718 foreach(l, parse->sortClause)
2719 {
2722
2723 uniqColIdx[numUniqkeys] = tle->resno;
2726 numUniqkeys++;
2727 }
2728 }
2729
2730 plan = make_limit(subplan,
2731 best_path->limitOffset,
2732 best_path->limitCount,
2733 best_path->limitOption,
2735
2737
2738 return plan;
2739}
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
void parse(int)
Definition parse.c:49
void * palloc(Size size)
Definition mcxt.c:1387
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
@ LIMIT_OPTION_WITH_TIES
Definition nodes.h:443

References copy_generic_path_info(), create_plan_recurse(), exprCollation(), fb(), get_sortgroupclause_tle(), lfirst, LIMIT_OPTION_WITH_TIES, list_length(), make_limit(), palloc(), parse(), plan, and root.

Referenced by create_plan_recurse().

◆ create_lockrows_plan()

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

Definition at line 2630 of file createplan.c.

2632{
2633 LockRows *plan;
2634 Plan *subplan;
2635
2636 /* LockRows doesn't project, so tlist requirements pass through */
2637 subplan = create_plan_recurse(root, best_path->subpath, flags);
2638
2639 plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2640
2642
2643 return plan;
2644}
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)

References copy_generic_path_info(), create_plan_recurse(), fb(), make_lockrows(), plan, and root.

Referenced by create_plan_recurse().

◆ create_material_plan()

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

Definition at line 1683 of file createplan.c.

1684{
1685 Material *plan;
1686 Plan *subplan;
1687
1688 /*
1689 * We don't want any excess columns in the materialized tuples, so request
1690 * a smaller tlist. Otherwise, since Material doesn't project, tlist
1691 * requirements pass through.
1692 */
1693 subplan = create_plan_recurse(root, best_path->subpath,
1694 flags | CP_SMALL_TLIST);
1695
1696 plan = make_material(subplan);
1697
1699
1700 return plan;
1701}
static Material * make_material(Plan *lefttree)

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), fb(), make_material(), plan, and root.

Referenced by create_plan_recurse().

◆ create_memoize_plan()

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

Definition at line 1711 of file createplan.c.

1712{
1713 Memoize *plan;
1714 Bitmapset *keyparamids;
1715 Plan *subplan;
1716 Oid *operators;
1717 Oid *collations;
1718 List *param_exprs = NIL;
1719 ListCell *lc;
1720 ListCell *lc2;
1721 int nkeys;
1722 int i;
1723
1724 subplan = create_plan_recurse(root, best_path->subpath,
1725 flags | CP_SMALL_TLIST);
1726
1727 param_exprs = (List *) replace_nestloop_params(root, (Node *)
1728 best_path->param_exprs);
1729
1730 nkeys = list_length(param_exprs);
1731 Assert(nkeys > 0);
1732 operators = palloc(nkeys * sizeof(Oid));
1733 collations = palloc(nkeys * sizeof(Oid));
1734
1735 i = 0;
1736 forboth(lc, param_exprs, lc2, best_path->hash_operators)
1737 {
1738 Expr *param_expr = (Expr *) lfirst(lc);
1739 Oid opno = lfirst_oid(lc2);
1740
1741 operators[i] = opno;
1742 collations[i] = exprCollation((Node *) param_expr);
1743 i++;
1744 }
1745
1746 keyparamids = pull_paramids((Expr *) param_exprs);
1747
1748 plan = make_memoize(subplan, operators, collations, param_exprs,
1749 best_path->singlerow, best_path->binary_mode,
1750 best_path->est_entries, keyparamids, best_path->est_calls,
1751 best_path->est_unique_keys, best_path->est_hit_ratio);
1752
1754
1755 return plan;
1756}
Bitmapset * pull_paramids(Expr *expr)
Definition clauses.c:6212
static Memoize * make_memoize(Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids, Cardinality est_calls, Cardinality est_unique_keys, double est_hit_ratio)
#define lfirst_oid(lc)
Definition pg_list.h:174

References Assert, copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), exprCollation(), fb(), forboth, i, lfirst, lfirst_oid, list_length(), make_memoize(), NIL, palloc(), plan, pull_paramids(), replace_nestloop_params(), and root.

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

1457{
1459 Plan *plan = &node->plan;
1460 List *tlist = build_path_tlist(root, &best_path->path);
1461 int orig_tlist_length = list_length(tlist);
1462 bool tlist_was_changed;
1463 List *pathkeys = best_path->path.pathkeys;
1464 List *subplans = NIL;
1465 ListCell *subpaths;
1466 RelOptInfo *rel = best_path->path.parent;
1467
1468 /*
1469 * We don't have the actual creation of the MergeAppend node split out
1470 * into a separate make_xxx function. This is because we want to run
1471 * prepare_sort_from_pathkeys on it before we do so on the individual
1472 * child plans, to make cross-checking the sort info easier.
1473 */
1475 plan->targetlist = tlist;
1476 plan->qual = NIL;
1477 plan->lefttree = NULL;
1478 plan->righttree = NULL;
1479 node->apprelids = rel->relids;
1480 node->child_append_relid_sets = best_path->child_append_relid_sets;
1481
1482 /*
1483 * Compute sort column info, and adjust MergeAppend's tlist as needed.
1484 * Because we pass adjust_tlist_in_place = true, we may ignore the
1485 * function result; it must be the same plan node. However, we then need
1486 * to detect whether any tlist entries were added.
1487 */
1489 best_path->path.parent->relids,
1490 NULL,
1491 true,
1492 &node->numCols,
1493 &node->sortColIdx,
1494 &node->sortOperators,
1495 &node->collations,
1496 &node->nullsFirst);
1498
1499 /*
1500 * Now prepare the child plans. We must apply prepare_sort_from_pathkeys
1501 * even to subplans that don't need an explicit sort, to make sure they
1502 * are returning the same sort key columns the MergeAppend expects.
1503 */
1504 foreach(subpaths, best_path->subpaths)
1505 {
1506 Path *subpath = (Path *) lfirst(subpaths);
1507 Plan *subplan;
1508 int numsortkeys;
1509 AttrNumber *sortColIdx;
1510 Oid *sortOperators;
1511 Oid *collations;
1512 bool *nullsFirst;
1513 int presorted_keys;
1514
1515 /* Build the child plan */
1516 /* Must insist that all children return the same tlist */
1518
1519 /* Compute sort column info, and adjust subplan's tlist as needed */
1520 subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1521 subpath->parent->relids,
1522 node->sortColIdx,
1523 false,
1524 &numsortkeys,
1525 &sortColIdx,
1526 &sortOperators,
1527 &collations,
1528 &nullsFirst);
1529
1530 /*
1531 * Check that we got the same sort key information. We just Assert
1532 * that the sortops match, since those depend only on the pathkeys;
1533 * but it seems like a good idea to check the sort column numbers
1534 * explicitly, to ensure the tlists really do match up.
1535 */
1536 Assert(numsortkeys == node->numCols);
1537 if (memcmp(sortColIdx, node->sortColIdx,
1538 numsortkeys * sizeof(AttrNumber)) != 0)
1539 elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
1540 Assert(memcmp(sortOperators, node->sortOperators,
1541 numsortkeys * sizeof(Oid)) == 0);
1542 Assert(memcmp(collations, node->collations,
1543 numsortkeys * sizeof(Oid)) == 0);
1544 Assert(memcmp(nullsFirst, node->nullsFirst,
1545 numsortkeys * sizeof(bool)) == 0);
1546
1547 /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1548 if (!pathkeys_count_contained_in(pathkeys, subpath->pathkeys,
1549 &presorted_keys))
1550 {
1551 Plan *sort_plan;
1552
1553 /*
1554 * We choose to use incremental sort if it is enabled and there
1555 * are presorted keys; otherwise we use full sort.
1556 */
1557 if (enable_incremental_sort && presorted_keys > 0)
1558 {
1559 sort_plan = (Plan *)
1560 make_incrementalsort(subplan, numsortkeys, presorted_keys,
1561 sortColIdx, sortOperators,
1562 collations, nullsFirst);
1563
1566 pathkeys,
1567 best_path->limit_tuples);
1568 }
1569 else
1570 {
1571 sort_plan = (Plan *) make_sort(subplan, numsortkeys,
1572 sortColIdx, sortOperators,
1573 collations, nullsFirst);
1574
1576 best_path->limit_tuples);
1577 }
1578
1579 subplan = sort_plan;
1580 }
1581
1582 subplans = lappend(subplans, subplan);
1583 }
1584
1585 /* Set below if we find quals that we can use to run-time prune */
1586 node->part_prune_index = -1;
1587
1588 /*
1589 * If any quals exist, they may be useful to perform further partition
1590 * pruning during execution. Gather information needed by the executor to
1591 * do partition pruning.
1592 */
1594 {
1595 List *prunequal;
1596
1598
1599 /* We don't currently generate any parameterized MergeAppend paths */
1600 Assert(best_path->path.param_info == NULL);
1601
1602 if (prunequal != NIL)
1604 best_path->subpaths,
1605 prunequal);
1606 }
1607
1608 node->mergeplans = subplans;
1609
1610 /*
1611 * If prepare_sort_from_pathkeys added sort columns, but we were told to
1612 * produce either the exact tlist or a narrow tlist, we should get rid of
1613 * the sort columns again. We must inject a projection node to do so.
1614 */
1615 if (tlist_was_changed && (flags & (CP_EXACT_TLIST | CP_SMALL_TLIST)))
1616 {
1617 tlist = list_copy_head(plan->targetlist, orig_tlist_length);
1618 return inject_projection_plan(plan, tlist, plan->parallel_safe);
1619 }
1620 else
1621 return plan;
1622}
int part_prune_index
Definition plannodes.h:468
Bitmapset * apprelids
Definition plannodes.h:438
List * mergeplans
Definition plannodes.h:444
List * child_append_relid_sets
Definition plannodes.h:441

References MergeAppend::apprelids, Assert, RelOptInfo::baserestrictinfo, build_path_tlist(), MergeAppend::child_append_relid_sets, copy_generic_path_info(), CP_EXACT_TLIST, CP_SMALL_TLIST, create_plan_recurse(), elog, enable_incremental_sort, enable_partition_pruning, ERROR, extract_actual_clauses(), fb(), inject_projection_plan(), label_incrementalsort_with_costsize(), label_sort_with_costsize(), lappend(), lfirst, list_copy_head(), list_length(), make_incrementalsort(), make_partition_pruneinfo(), make_sort(), makeNode, MergeAppend::mergeplans, NIL, MergeAppend::numCols, MergeAppend::part_prune_index, pathkeys_count_contained_in(), MergeAppend::plan, plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, root, and subpath().

Referenced by create_plan_recurse().

◆ create_mergejoin_plan()

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

Definition at line 4339 of file createplan.c.

4341{
4343 Plan *outer_plan;
4344 Plan *inner_plan;
4345 List *tlist = build_path_tlist(root, &best_path->jpath.path);
4346 List *joinclauses;
4348 List *mergeclauses;
4351 int nClauses;
4354 bool *mergereversals;
4355 bool *mergenullsfirst;
4358 int i;
4359 ListCell *lc;
4360 ListCell *lop;
4361 ListCell *lip;
4362 Path *outer_path = best_path->jpath.outerjoinpath;
4363 Path *inner_path = best_path->jpath.innerjoinpath;
4364
4365 /*
4366 * MergeJoin can project, so we don't have to demand exact tlists from the
4367 * inputs. However, if we're intending to sort an input's result, it's
4368 * best to request a small tlist so we aren't sorting more data than
4369 * necessary.
4370 */
4371 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
4372 (best_path->outersortkeys != NIL) ? CP_SMALL_TLIST : 0);
4373
4374 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
4375 (best_path->innersortkeys != NIL) ? CP_SMALL_TLIST : 0);
4376
4377 /* Sort join qual clauses into best execution order */
4378 /* NB: do NOT reorder the mergeclauses */
4379 joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
4380
4381 /* Get the join qual clauses (in plain expression form) */
4382 /* Any pseudoconstant clauses are ignored here */
4383 if (IS_OUTER_JOIN(best_path->jpath.jointype))
4384 {
4385 extract_actual_join_clauses(joinclauses,
4386 best_path->jpath.path.parent->relids,
4387 &joinclauses, &otherclauses);
4388 }
4389 else
4390 {
4391 /* We can treat all clauses alike for an inner join */
4392 joinclauses = extract_actual_clauses(joinclauses, false);
4393 otherclauses = NIL;
4394 }
4395
4396 /*
4397 * Remove the mergeclauses from the list of join qual clauses, leaving the
4398 * list of quals that must be checked as qpquals.
4399 */
4400 mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
4401 joinclauses = list_difference(joinclauses, mergeclauses);
4402
4403 /*
4404 * Replace any outer-relation variables with nestloop params. There
4405 * should not be any in the mergeclauses.
4406 */
4407 if (best_path->jpath.path.param_info)
4408 {
4409 joinclauses = (List *)
4410 replace_nestloop_params(root, (Node *) joinclauses);
4411 otherclauses = (List *)
4413 }
4414
4415 /*
4416 * Rearrange mergeclauses, if needed, so that the outer variable is always
4417 * on the left; mark the mergeclause restrictinfos with correct
4418 * outer_is_left status.
4419 */
4420 mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
4421 best_path->jpath.outerjoinpath->parent->relids);
4422
4423 /*
4424 * Create explicit sort nodes for the outer and inner paths if necessary.
4425 */
4426 if (best_path->outersortkeys)
4427 {
4428 Relids outer_relids = outer_path->parent->relids;
4429 Plan *sort_plan;
4430
4431 /*
4432 * We can assert that the outer path is not already ordered
4433 * appropriately for the mergejoin; otherwise, outersortkeys would
4434 * have been set to NIL.
4435 */
4436 Assert(!pathkeys_contained_in(best_path->outersortkeys,
4437 outer_path->pathkeys));
4438
4439 /*
4440 * We choose to use incremental sort if it is enabled and there are
4441 * presorted keys; otherwise we use full sort.
4442 */
4443 if (enable_incremental_sort && best_path->outer_presorted_keys > 0)
4444 {
4445 sort_plan = (Plan *)
4447 best_path->outersortkeys,
4448 outer_relids,
4449 best_path->outer_presorted_keys);
4450
4453 best_path->outersortkeys,
4454 -1.0);
4455 }
4456 else
4457 {
4458 sort_plan = (Plan *)
4459 make_sort_from_pathkeys(outer_plan,
4460 best_path->outersortkeys,
4461 outer_relids);
4462
4464 }
4465
4466 outer_plan = sort_plan;
4467 outerpathkeys = best_path->outersortkeys;
4468 }
4469 else
4470 outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
4471
4472 if (best_path->innersortkeys)
4473 {
4474 /*
4475 * We do not consider incremental sort for inner path, because
4476 * incremental sort does not support mark/restore.
4477 */
4478
4479 Relids inner_relids = inner_path->parent->relids;
4480 Sort *sort;
4481
4482 /*
4483 * We can assert that the inner path is not already ordered
4484 * appropriately for the mergejoin; otherwise, innersortkeys would
4485 * have been set to NIL.
4486 */
4487 Assert(!pathkeys_contained_in(best_path->innersortkeys,
4488 inner_path->pathkeys));
4489
4490 sort = make_sort_from_pathkeys(inner_plan,
4491 best_path->innersortkeys,
4492 inner_relids);
4493
4495 inner_plan = (Plan *) sort;
4496 innerpathkeys = best_path->innersortkeys;
4497 }
4498 else
4499 innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
4500
4501 /*
4502 * If specified, add a materialize node to shield the inner plan from the
4503 * need to handle mark/restore.
4504 */
4505 if (best_path->materialize_inner)
4506 {
4507 Plan *matplan = (Plan *) make_material(inner_plan);
4508
4509 /*
4510 * We assume the materialize will not spill to disk, and therefore
4511 * charge just cpu_operator_cost per tuple. (Keep this estimate in
4512 * sync with final_cost_mergejoin.)
4513 */
4514 copy_plan_costsize(matplan, inner_plan);
4515 matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
4516
4517 inner_plan = matplan;
4518 }
4519
4520 /*
4521 * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
4522 * executor. The information is in the pathkeys for the two inputs, but
4523 * we need to be careful about the possibility of mergeclauses sharing a
4524 * pathkey, as well as the possibility that the inner pathkeys are not in
4525 * an order matching the mergeclauses.
4526 */
4527 nClauses = list_length(mergeclauses);
4528 Assert(nClauses == list_length(best_path->path_mergeclauses));
4529 mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
4530 mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
4531 mergereversals = (bool *) palloc(nClauses * sizeof(bool));
4532 mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
4533
4534 opathkey = NULL;
4535 opeclass = NULL;
4538 i = 0;
4539 foreach(lc, best_path->path_mergeclauses)
4540 {
4546 bool first_inner_match = false;
4547
4548 /* fetch outer/inner eclass from mergeclause */
4549 if (rinfo->outer_is_left)
4550 {
4551 oeclass = rinfo->left_ec;
4552 ieclass = rinfo->right_ec;
4553 }
4554 else
4555 {
4556 oeclass = rinfo->right_ec;
4557 ieclass = rinfo->left_ec;
4558 }
4559 Assert(oeclass != NULL);
4560 Assert(ieclass != NULL);
4561
4562 /*
4563 * We must identify the pathkey elements associated with this clause
4564 * by matching the eclasses (which should give a unique match, since
4565 * the pathkey lists should be canonical). In typical cases the merge
4566 * clauses are one-to-one with the pathkeys, but when dealing with
4567 * partially redundant query conditions, things are more complicated.
4568 *
4569 * lop and lip reference the first as-yet-unmatched pathkey elements.
4570 * If they're NULL then all pathkey elements have been matched.
4571 *
4572 * The ordering of the outer pathkeys should match the mergeclauses,
4573 * by construction (see find_mergeclauses_for_outer_pathkeys()). There
4574 * could be more than one mergeclause for the same outer pathkey, but
4575 * no pathkey may be entirely skipped over.
4576 */
4577 if (oeclass != opeclass) /* multiple matches are not interesting */
4578 {
4579 /* doesn't match the current opathkey, so must match the next */
4580 if (lop == NULL)
4581 elog(ERROR, "outer pathkeys do not match mergeclauses");
4582 opathkey = (PathKey *) lfirst(lop);
4583 opeclass = opathkey->pk_eclass;
4585 if (oeclass != opeclass)
4586 elog(ERROR, "outer pathkeys do not match mergeclauses");
4587 }
4588
4589 /*
4590 * The inner pathkeys likewise should not have skipped-over keys, but
4591 * it's possible for a mergeclause to reference some earlier inner
4592 * pathkey if we had redundant pathkeys. For example we might have
4593 * mergeclauses like "o.a = i.x AND o.b = i.y AND o.c = i.x". The
4594 * implied inner ordering is then "ORDER BY x, y, x", but the pathkey
4595 * mechanism drops the second sort by x as redundant, and this code
4596 * must cope.
4597 *
4598 * It's also possible for the implied inner-rel ordering to be like
4599 * "ORDER BY x, y, x DESC". We still drop the second instance of x as
4600 * redundant; but this means that the sort ordering of a redundant
4601 * inner pathkey should not be considered significant. So we must
4602 * detect whether this is the first clause matching an inner pathkey.
4603 */
4604 if (lip)
4605 {
4606 ipathkey = (PathKey *) lfirst(lip);
4607 ipeclass = ipathkey->pk_eclass;
4608 if (ieclass == ipeclass)
4609 {
4610 /* successful first match to this inner pathkey */
4612 first_inner_match = true;
4613 }
4614 }
4615 if (!first_inner_match)
4616 {
4617 /* redundant clause ... must match something before lip */
4618 ListCell *l2;
4619
4620 foreach(l2, innerpathkeys)
4621 {
4622 if (l2 == lip)
4623 break;
4624 ipathkey = (PathKey *) lfirst(l2);
4625 ipeclass = ipathkey->pk_eclass;
4626 if (ieclass == ipeclass)
4627 break;
4628 }
4629 if (ieclass != ipeclass)
4630 elog(ERROR, "inner pathkeys do not match mergeclauses");
4631 }
4632
4633 /*
4634 * The pathkeys should always match each other as to opfamily and
4635 * collation (which affect equality), but if we're considering a
4636 * redundant inner pathkey, its sort ordering might not match. In
4637 * such cases we may ignore the inner pathkey's sort ordering and use
4638 * the outer's. (In effect, we're lying to the executor about the
4639 * sort direction of this inner column, but it does not matter since
4640 * the run-time row comparisons would only reach this column when
4641 * there's equality for the earlier column containing the same eclass.
4642 * There could be only one value in this column for the range of inner
4643 * rows having a given value in the earlier column, so it does not
4644 * matter which way we imagine this column to be ordered.) But a
4645 * non-redundant inner pathkey had better match outer's ordering too.
4646 */
4647 if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
4648 opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation)
4649 elog(ERROR, "left and right pathkeys do not match in mergejoin");
4650 if (first_inner_match &&
4651 (opathkey->pk_cmptype != ipathkey->pk_cmptype ||
4652 opathkey->pk_nulls_first != ipathkey->pk_nulls_first))
4653 elog(ERROR, "left and right pathkeys do not match in mergejoin");
4654
4655 /* OK, save info for executor */
4656 mergefamilies[i] = opathkey->pk_opfamily;
4657 mergecollations[i] = opathkey->pk_eclass->ec_collation;
4658 mergereversals[i] = (opathkey->pk_cmptype == COMPARE_GT ? true : false);
4659 mergenullsfirst[i] = opathkey->pk_nulls_first;
4660 i++;
4661 }
4662
4663 /*
4664 * Note: it is not an error if we have additional pathkey elements (i.e.,
4665 * lop or lip isn't NULL here). The input paths might be better-sorted
4666 * than we need for the current mergejoin.
4667 */
4668
4669 /*
4670 * Now we can build the mergejoin node.
4671 */
4672 join_plan = make_mergejoin(tlist,
4673 joinclauses,
4675 mergeclauses,
4680 outer_plan,
4681 inner_plan,
4682 best_path->jpath.jointype,
4683 best_path->jpath.inner_unique,
4684 best_path->skip_mark_restore);
4685
4686 /* Costs of sort and material steps are included in path cost already */
4687 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4688
4689 return join_plan;
4690}
Datum sort(PG_FUNCTION_ARGS)
Definition _int_op.c:198
@ COMPARE_GT
Definition cmptype.h:38
double cpu_operator_cost
Definition costsize.c:135
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 Sort * make_sort_from_pathkeys(Plan *lefttree, List *pathkeys, Relids relids)
return true
Definition isn.c:130
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:375

References Assert, build_path_tlist(), COMPARE_GT, 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(), fb(), get_actual_clauses(), get_switched_clauses(), i, IS_OUTER_JOIN, 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(), NIL, order_qual_clauses(), palloc(), pathkeys_contained_in(), replace_nestloop_params(), root, sort(), and true.

Referenced by create_join_plan().

◆ create_minmaxagg_plan()

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

Definition at line 2398 of file createplan.c.

2399{
2400 Result *plan;
2401 List *tlist;
2402 ListCell *lc;
2403
2404 /* Prepare an InitPlan for each aggregate's subquery. */
2405 foreach(lc, best_path->mmaggregates)
2406 {
2408 PlannerInfo *subroot = mminfo->subroot;
2409 Query *subparse = subroot->parse;
2410 Plan *plan;
2411
2412 /*
2413 * Generate the plan for the subquery. We already have a Path, but we
2414 * have to convert it to a Plan and attach a LIMIT node above it.
2415 * Since we are entering a different planner context (subroot),
2416 * recurse to create_plan not create_plan_recurse.
2417 */
2418 plan = create_plan(subroot, mminfo->path);
2419
2420 plan = (Plan *) make_limit(plan,
2421 subparse->limitOffset,
2422 subparse->limitCount,
2423 subparse->limitOption,
2424 0, NULL, NULL, NULL);
2425
2426 /* Must apply correct cost/width data to Limit node */
2427 plan->disabled_nodes = mminfo->path->disabled_nodes;
2428 plan->startup_cost = mminfo->path->startup_cost;
2429 plan->total_cost = mminfo->pathcost;
2430 plan->plan_rows = 1;
2431 plan->plan_width = mminfo->path->pathtarget->width;
2432 plan->parallel_aware = false;
2433 plan->parallel_safe = mminfo->path->parallel_safe;
2434
2435 /* Convert the plan into an InitPlan in the outer query. */
2436 SS_make_initplan_from_plan(root, subroot, plan, mminfo->param);
2437 }
2438
2439 /* Generate the output plan --- basically just a Result */
2440 tlist = build_path_tlist(root, &best_path->path);
2441
2442 plan = make_one_row_result(tlist, (Node *) best_path->quals,
2443 best_path->path.parent);
2444 plan->result_type = RESULT_TYPE_MINMAX;
2445
2447
2448 /*
2449 * During setrefs.c, we'll need to replace references to the Agg nodes
2450 * with InitPlan output params. (We can't just do that locally in the
2451 * MinMaxAgg node, because path nodes above here may have Agg references
2452 * as well.) Save the mmaggregates list to tell setrefs.c to do that.
2453 */
2454 Assert(root->minmax_aggs == NIL);
2455 root->minmax_aggs = best_path->mmaggregates;
2456
2457 return plan;
2458}
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition createplan.c:339
@ RESULT_TYPE_MINMAX
Definition plannodes.h:281
Query * parse
Definition pathnodes.h:309
void SS_make_initplan_from_plan(PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
Definition subselect.c:3310

References Assert, build_path_tlist(), copy_generic_path_info(), create_plan(), fb(), lfirst, make_limit(), make_one_row_result(), NIL, PlannerInfo::parse, plan, RESULT_TYPE_MINMAX, root, and SS_make_initplan_from_plan().

Referenced by create_plan_recurse().

◆ create_modifytable_plan()

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

Definition at line 2653 of file createplan.c.

2654{
2656 Path *subpath = best_path->subpath;
2657 Plan *subplan;
2658
2659 /* Subplan must produce exactly the specified tlist */
2661
2662 /* Transfer resname/resjunk labeling, too, to keep executor happy */
2663 apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2664
2666 subplan,
2667 best_path->operation,
2668 best_path->canSetTag,
2669 best_path->nominalRelation,
2670 best_path->rootRelation,
2671 best_path->resultRelations,
2672 best_path->updateColnosLists,
2673 best_path->withCheckOptionLists,
2674 best_path->returningLists,
2675 best_path->rowMarks,
2676 best_path->onconflict,
2677 best_path->mergeActionLists,
2678 best_path->mergeJoinConditions,
2679 best_path->forPortionOf,
2680 best_path->epqParam);
2681
2682 copy_generic_path_info(&plan->plan, &best_path->path);
2683
2684 return plan;
2685}
static ModifyTable * make_modifytable(PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, ForPortionOfExpr *forPortionOf, int epqParam)
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition tlist.c:327

References apply_tlist_labeling(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), fb(), make_modifytable(), plan, root, subpath(), and Plan::targetlist.

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

3826{
3828 Index scan_relid = best_path->parent->relid;
3830
3831 Assert(scan_relid > 0);
3833 Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
3834
3835 /* Sort clauses into best execution order */
3837
3838 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3840
3841 /* Replace any outer-relation variables with nestloop params */
3842 if (best_path->param_info)
3843 {
3844 scan_clauses = (List *)
3846 }
3847
3849 rte->enrname);
3850
3852
3853 return scan_plan;
3854}
static NamedTuplestoreScan * make_namedtuplestorescan(List *qptlist, List *qpqual, Index scanrelid, char *enrname)
@ RTE_NAMEDTUPLESTORE

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_namedtuplestorescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_NAMEDTUPLESTORE.

Referenced by create_scan_plan().

◆ create_nestloop_plan()

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

Definition at line 4187 of file createplan.c.

4189{
4191 Plan *outer_plan;
4192 Plan *inner_plan;
4193 Relids outerrelids;
4194 List *tlist = build_path_tlist(root, &best_path->jpath.path);
4195 List *joinrestrictclauses = best_path->jpath.joinrestrictinfo;
4196 List *joinclauses;
4198 List *nestParams;
4199 List *outer_tlist;
4201 Relids saveOuterRels = root->curOuterRels;
4202 ListCell *lc;
4203
4204 /*
4205 * If the inner path is parameterized by the topmost parent of the outer
4206 * rel rather than the outer rel itself, fix that. (Nothing happens here
4207 * if it is not so parameterized.)
4208 */
4209 best_path->jpath.innerjoinpath =
4211 best_path->jpath.innerjoinpath,
4212 best_path->jpath.outerjoinpath->parent);
4213
4214 /*
4215 * Failure here probably means that reparameterize_path_by_child() is not
4216 * in sync with path_is_reparameterizable_by_child().
4217 */
4218 Assert(best_path->jpath.innerjoinpath != NULL);
4219
4220 /* NestLoop can project, so no need to be picky about child tlists */
4221 outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath, 0);
4222
4223 /* For a nestloop, include outer relids in curOuterRels for inner side */
4224 outerrelids = best_path->jpath.outerjoinpath->parent->relids;
4225 root->curOuterRels = bms_union(root->curOuterRels, outerrelids);
4226
4227 inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath, 0);
4228
4229 /* Restore curOuterRels */
4230 bms_free(root->curOuterRels);
4231 root->curOuterRels = saveOuterRels;
4232
4233 /* Sort join qual clauses into best execution order */
4235
4236 /* Get the join qual clauses (in plain expression form) */
4237 /* Any pseudoconstant clauses are ignored here */
4238 if (IS_OUTER_JOIN(best_path->jpath.jointype))
4239 {
4241 best_path->jpath.path.parent->relids,
4242 &joinclauses, &otherclauses);
4243 }
4244 else
4245 {
4246 /* We can treat all clauses alike for an inner join */
4247 joinclauses = extract_actual_clauses(joinrestrictclauses, false);
4248 otherclauses = NIL;
4249 }
4250
4251 /* Replace any outer-relation variables with nestloop params */
4252 if (best_path->jpath.path.param_info)
4253 {
4254 joinclauses = (List *)
4255 replace_nestloop_params(root, (Node *) joinclauses);
4256 otherclauses = (List *)
4258 }
4259
4260 /*
4261 * Identify any nestloop parameters that should be supplied by this join
4262 * node, and remove them from root->curOuterParams.
4263 */
4265 outerrelids,
4267
4268 /*
4269 * While nestloop parameters that are Vars had better be available from
4270 * the outer_plan already, there are edge cases where nestloop parameters
4271 * that are PHVs won't be. In such cases we must add them to the
4272 * outer_plan's tlist, since the executor's NestLoopParam machinery
4273 * requires the params to be simple outer-Var references to that tlist.
4274 * (This is cheating a little bit, because the outer path's required-outer
4275 * relids might not be enough to allow evaluating such a PHV. But in
4276 * practice, if we could have evaluated the PHV at the nestloop node, we
4277 * can do so in the outer plan too.)
4278 */
4279 outer_tlist = outer_plan->targetlist;
4280 outer_parallel_safe = outer_plan->parallel_safe;
4281 foreach(lc, nestParams)
4282 {
4286
4287 if (IsA(nlp->paramval, Var))
4288 continue; /* nothing to do for simple Vars */
4289 /* Otherwise it must be a PHV */
4290 phv = castNode(PlaceHolderVar, nlp->paramval);
4291
4292 if (tlist_member((Expr *) phv, outer_tlist))
4293 continue; /* already available */
4294
4295 /*
4296 * It's possible that nestloop parameter PHVs selected to evaluate
4297 * here contain references to surviving root->curOuterParams items
4298 * (that is, they reference values that will be supplied by some
4299 * higher-level nestloop). Those need to be converted to Params now.
4300 * Note: it's safe to do this after the tlist_member() check, because
4301 * equal() won't pay attention to phv->phexpr.
4302 */
4303 phv->phexpr = (Expr *) replace_nestloop_params(root,
4304 (Node *) phv->phexpr);
4305
4306 /* Make a shallow copy of outer_tlist, if we didn't already */
4307 if (outer_tlist == outer_plan->targetlist)
4308 outer_tlist = list_copy(outer_tlist);
4309 /* ... and add the needed expression */
4311 list_length(outer_tlist) + 1,
4312 NULL,
4313 true);
4314 outer_tlist = lappend(outer_tlist, tle);
4315 /* ... and track whether tlist is (still) parallel-safe */
4318 }
4319 if (outer_tlist != outer_plan->targetlist)
4320 outer_plan = change_plan_targetlist(outer_plan, outer_tlist,
4322
4323 /* And finally, we can build the join plan node */
4324 join_plan = make_nestloop(tlist,
4325 joinclauses,
4327 nestParams,
4328 outer_plan,
4329 inner_plan,
4330 best_path->jpath.jointype,
4331 best_path->jpath.inner_unique);
4332
4333 copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4334
4335 return join_plan;
4336}
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:251
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition clauses.c:764
Plan * change_plan_targetlist(Plan *subplan, List *tlist, bool tlist_parallel_safe)
static NestLoop * make_nestloop(List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
List * list_copy(const List *oldlist)
Definition list.c:1573
#define copyObject(obj)
Definition nodes.h:232
List * identify_current_nestloop_params(PlannerInfo *root, Relids leftrelids, Relids outerrelids)
Path * reparameterize_path_by_child(PlannerInfo *root, Path *path, RelOptInfo *child_rel)
Definition pathnode.c:4087
#define PATH_REQ_OUTER(path)
Definition pathnodes.h:2015
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition tlist.c:88

References Assert, bms_free(), bms_union(), build_path_tlist(), castNode, change_plan_targetlist(), copy_generic_path_info(), copyObject, create_plan_recurse(), extract_actual_clauses(), extract_actual_join_clauses(), fb(), identify_current_nestloop_params(), IS_OUTER_JOIN, is_parallel_safe(), IsA, lappend(), lfirst, list_copy(), list_length(), make_nestloop(), makeTargetEntry(), NIL, order_qual_clauses(), Plan::parallel_safe, PATH_REQ_OUTER, reparameterize_path_by_child(), replace_nestloop_params(), root, Plan::targetlist, and tlist_member().

Referenced by create_join_plan().

◆ create_plan()

Plan * create_plan ( PlannerInfo root,
Path best_path 
)

Definition at line 339 of file createplan.c.

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

References apply_tlist_labeling(), Assert, CP_EXACT_TLIST, create_plan_recurse(), elog, ERROR, fb(), 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 390 of file createplan.c.

391{
392 Plan *plan;
393
394 /* Guard against stack overflow due to overly complex plans */
396
397 switch (best_path->pathtype)
398 {
399 case T_SeqScan:
400 case T_SampleScan:
401 case T_IndexScan:
402 case T_IndexOnlyScan:
403 case T_BitmapHeapScan:
404 case T_TidScan:
405 case T_TidRangeScan:
406 case T_SubqueryScan:
407 case T_FunctionScan:
408 case T_TableFuncScan:
409 case T_ValuesScan:
410 case T_CteScan:
411 case T_WorkTableScan:
413 case T_ForeignScan:
414 case T_CustomScan:
416 break;
417 case T_HashJoin:
418 case T_MergeJoin:
419 case T_NestLoop:
421 (JoinPath *) best_path);
422 break;
423 case T_Append:
426 flags);
427 break;
428 case T_MergeAppend:
431 flags);
432 break;
433 case T_Result:
435 {
438 flags);
439 }
440 else if (IsA(best_path, MinMaxAggPath))
441 {
444 }
445 else if (IsA(best_path, GroupResultPath))
446 {
449 }
450 else
451 {
452 /* Simple RTE_RESULT base relation */
455 }
456 break;
457 case T_ProjectSet:
460 break;
461 case T_Material:
464 flags);
465 break;
466 case T_Memoize:
469 flags);
470 break;
471 case T_Unique:
474 flags);
475 break;
476 case T_Gather:
479 break;
480 case T_Sort:
483 flags);
484 break;
488 flags);
489 break;
490 case T_Group:
492 (GroupPath *) best_path);
493 break;
494 case T_Agg:
498 else
499 {
502 (AggPath *) best_path);
503 }
504 break;
505 case T_WindowAgg:
508 break;
509 case T_SetOp:
512 flags);
513 break;
514 case T_RecursiveUnion:
517 break;
518 case T_LockRows:
521 flags);
522 break;
523 case T_ModifyTable:
526 break;
527 case T_Limit:
530 flags);
531 break;
532 case T_GatherMerge:
535 break;
536 default:
537 elog(ERROR, "unrecognized node type: %d",
538 (int) best_path->pathtype);
539 plan = NULL; /* keep compiler quiet */
540 break;
541 }
542
543 return plan;
544}
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, int flags)
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
static Unique * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
static Result * create_group_result_plan(PlannerInfo *root, GroupResultPath *best_path)
static Limit * create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
static Material * create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition createplan.c:551
static IncrementalSort * create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path, int flags)
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
static Memoize * create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
static WindowAgg * create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
void check_stack_depth(void)
Definition stack_depth.c:95

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_windowagg_plan(), elog, ERROR, fb(), IsA, 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(), and create_windowagg_plan().

◆ create_project_set_plan()

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

Definition at line 1657 of file createplan.c.

1658{
1660 Plan *subplan;
1661 List *tlist;
1662
1663 /* Since we intend to project, we don't need to constrain child tlist */
1664 subplan = create_plan_recurse(root, best_path->subpath, 0);
1665
1666 tlist = build_path_tlist(root, &best_path->path);
1667
1668 plan = make_project_set(tlist, subplan);
1669
1671
1672 return plan;
1673}
static ProjectSet * make_project_set(List *tlist, Plan *subplan)

References build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), fb(), make_project_set(), plan, and root.

Referenced by create_plan_recurse().

◆ create_projection_plan()

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

Definition at line 1859 of file createplan.c.

1860{
1861 Plan *plan;
1862 Plan *subplan;
1863 List *tlist;
1864 bool needs_result_node = false;
1865
1866 /*
1867 * Convert our subpath to a Plan and determine whether we need a Result
1868 * node.
1869 *
1870 * In most cases where we don't need to project, create_projection_path
1871 * will have set dummypp, but not always. First, some createplan.c
1872 * routines change the tlists of their nodes. (An example is that
1873 * create_merge_append_plan might add resjunk sort columns to a
1874 * MergeAppend.) Second, create_projection_path has no way of knowing
1875 * what path node will be placed on top of the projection path and
1876 * therefore can't predict whether it will require an exact tlist. For
1877 * both of these reasons, we have to recheck here.
1878 */
1879 if (use_physical_tlist(root, &best_path->path, flags))
1880 {
1881 /*
1882 * Our caller doesn't really care what tlist we return, so we don't
1883 * actually need to project. However, we may still need to ensure
1884 * proper sortgroupref labels, if the caller cares about those.
1885 */
1886 subplan = create_plan_recurse(root, best_path->subpath, 0);
1887 tlist = subplan->targetlist;
1888 if (flags & CP_LABEL_TLIST)
1890 best_path->path.pathtarget);
1891 }
1892 else if (is_projection_capable_path(best_path->subpath))
1893 {
1894 /*
1895 * Our caller requires that we return the exact tlist, but no separate
1896 * result node is needed because the subpath is projection-capable.
1897 * Tell create_plan_recurse that we're going to ignore the tlist it
1898 * produces.
1899 */
1900 subplan = create_plan_recurse(root, best_path->subpath,
1903 tlist = build_path_tlist(root, &best_path->path);
1904 }
1905 else
1906 {
1907 /*
1908 * It looks like we need a result node, unless by good fortune the
1909 * requested tlist is exactly the one the child wants to produce.
1910 */
1911 subplan = create_plan_recurse(root, best_path->subpath, 0);
1912 tlist = build_path_tlist(root, &best_path->path);
1913 needs_result_node = !tlist_same_exprs(tlist, subplan->targetlist);
1914 }
1915
1916 /*
1917 * If we make a different decision about whether to include a Result node
1918 * than create_projection_path did, we'll have made slightly wrong cost
1919 * estimates; but label the plan with the cost estimates we actually used,
1920 * not "corrected" ones. (XXX this could be cleaned up if we moved more
1921 * of the sortcolumn setup logic into Path creation, but that would add
1922 * expense to creating Paths we might end up not using.)
1923 */
1924 if (!needs_result_node)
1925 {
1926 /* Don't need a separate Result, just assign tlist to subplan */
1927 plan = subplan;
1928 plan->targetlist = tlist;
1929
1930 /* Label plan with the estimated costs we actually used */
1931 plan->startup_cost = best_path->path.startup_cost;
1932 plan->total_cost = best_path->path.total_cost;
1933 plan->plan_rows = best_path->path.rows;
1934 plan->plan_width = best_path->path.pathtarget->width;
1935 plan->parallel_safe = best_path->path.parallel_safe;
1936 /* ... but don't change subplan's parallel_aware flag */
1937 }
1938 else
1939 {
1940 plan = (Plan *) make_gating_result(tlist, NULL, subplan);
1941
1943 }
1944
1945 return plan;
1946}
static bool use_physical_tlist(PlannerInfo *root, Path *path, int flags)
Definition createplan.c:857
bool is_projection_capable_path(Path *path)
#define CP_IGNORE_TLIST
Definition createplan.c:72
void apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
Definition tlist.c:783

References apply_pathtarget_labeling_to_tlist(), Assert, build_path_tlist(), copy_generic_path_info(), CP_IGNORE_TLIST, CP_LABEL_TLIST, create_plan_recurse(), fb(), is_projection_capable_path(), is_projection_capable_plan(), make_gating_result(), plan, root, Plan::targetlist, tlist_same_exprs(), 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 2598 of file createplan.c.

2599{
2601 Plan *leftplan;
2602 Plan *rightplan;
2603 List *tlist;
2604
2605 /* Need both children to produce same tlist, so force it */
2608
2609 tlist = build_path_tlist(root, &best_path->path);
2610
2611 plan = make_recursive_union(tlist,
2612 leftplan,
2613 rightplan,
2614 best_path->wtParam,
2615 best_path->distinctList,
2616 best_path->numGroups);
2617
2619
2620 return plan;
2621}
static RecursiveUnion * make_recursive_union(List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, Cardinality numGroups)

References build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), fb(), make_recursive_union(), plan, and root.

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

3865{
3867 Index scan_relid = best_path->parent->relid;
3869
3870 Assert(scan_relid > 0);
3872 Assert(rte->rtekind == RTE_RESULT);
3873
3874 /* Sort clauses into best execution order */
3876
3877 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3879
3880 /* Replace any outer-relation variables with nestloop params */
3881 if (best_path->param_info)
3882 {
3883 scan_clauses = (List *)
3885 }
3886
3888 best_path->parent);
3889
3891
3892 return scan_plan;
3893}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:249
@ RTE_RESULT

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_one_row_result(), order_qual_clauses(), PG_USED_FOR_ASSERTS_ONLY, 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 2793 of file createplan.c.

2795{
2797 Index scan_relid = best_path->parent->relid;
2800
2801 /* it should be a base rel with a tablesample clause... */
2802 Assert(scan_relid > 0);
2804 Assert(rte->rtekind == RTE_RELATION);
2805 tsc = rte->tablesample;
2806 Assert(tsc != NULL);
2807
2808 /* Sort clauses into best execution order */
2810
2811 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2813
2814 /* Replace any outer-relation variables with nestloop params */
2815 if (best_path->param_info)
2816 {
2817 scan_clauses = (List *)
2821 }
2822
2823 scan_plan = make_samplescan(tlist,
2825 scan_relid,
2826 tsc);
2827
2829
2830 return scan_plan;
2831}
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_samplescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_RELATION.

Referenced by create_scan_plan().

◆ create_scan_plan()

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

Definition at line 551 of file createplan.c.

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

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, fb(), get_gating_quals(), IS_JOIN_REL, list_concat_copy(), NIL, 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 2755 of file createplan.c.

2757{
2759 Index scan_relid = best_path->parent->relid;
2760
2761 /* it should be a base rel... */
2762 Assert(scan_relid > 0);
2763 Assert(best_path->parent->rtekind == RTE_RELATION);
2764
2765 /* Sort clauses into best execution order */
2767
2768 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2770
2771 /* Replace any outer-relation variables with nestloop params */
2772 if (best_path->param_info)
2773 {
2774 scan_clauses = (List *)
2776 }
2777
2778 scan_plan = make_seqscan(tlist,
2780 scan_relid);
2781
2783
2784 return scan_plan;
2785}
static SeqScan * make_seqscan(List *qptlist, List *qpqual, Index scanrelid)

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_seqscan(), order_qual_clauses(), replace_nestloop_params(), root, and RTE_RELATION.

Referenced by create_scan_plan().

◆ create_setop_plan()

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

Definition at line 2562 of file createplan.c.

2563{
2564 SetOp *plan;
2565 List *tlist = build_path_tlist(root, &best_path->path);
2566 Plan *leftplan;
2567 Plan *rightplan;
2568
2569 /*
2570 * SetOp doesn't project, so tlist requirements pass through; moreover we
2571 * need grouping columns to be labeled.
2572 */
2574 flags | CP_LABEL_TLIST);
2576 flags | CP_LABEL_TLIST);
2577
2578 plan = make_setop(best_path->cmd,
2579 best_path->strategy,
2580 tlist,
2581 leftplan,
2582 rightplan,
2583 best_path->groupList,
2584 best_path->numGroups);
2585
2587
2588 return plan;
2589}
static SetOp * make_setop(SetOpCmd cmd, SetOpStrategy strategy, List *tlist, Plan *lefttree, Plan *righttree, List *groupList, Cardinality numGroups)

References build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), fb(), make_setop(), plan, and root.

Referenced by create_plan_recurse().

◆ create_sort_plan()

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

Definition at line 2020 of file createplan.c.

2021{
2022 Sort *plan;
2023 Plan *subplan;
2024
2025 /*
2026 * We don't want any excess columns in the sorted tuples, so request a
2027 * smaller tlist. Otherwise, since Sort doesn't project, tlist
2028 * requirements pass through.
2029 */
2030 subplan = create_plan_recurse(root, best_path->subpath,
2031 flags | CP_SMALL_TLIST);
2032
2033 /*
2034 * make_sort_from_pathkeys indirectly calls find_ec_member_matching_expr,
2035 * which will ignore any child EC members that don't belong to the given
2036 * relids. Thus, if this sort path is based on a child relation, we must
2037 * pass its relids.
2038 */
2039 plan = make_sort_from_pathkeys(subplan, best_path->path.pathkeys,
2040 IS_OTHER_REL(best_path->subpath->parent) ?
2041 best_path->path.parent->relids : NULL);
2042
2044
2045 return plan;
2046}

References copy_generic_path_info(), CP_SMALL_TLIST, create_plan_recurse(), fb(), IS_OTHER_REL, make_sort_from_pathkeys(), plan, and root.

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

3542{
3544 RelOptInfo *rel = best_path->path.parent;
3545 Index scan_relid = rel->relid;
3546 Plan *subplan;
3547
3548 /* it should be a subquery base rel... */
3549 Assert(scan_relid > 0);
3550 Assert(rel->rtekind == RTE_SUBQUERY);
3551
3552 /*
3553 * Recursively create Plan from Path for subquery. Since we are entering
3554 * a different planner context (subroot), recurse to create_plan not
3555 * create_plan_recurse.
3556 */
3557 subplan = create_plan(rel->subroot, best_path->subpath);
3558
3559 /* Sort clauses into best execution order */
3561
3562 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3564
3565 /*
3566 * Replace any outer-relation variables with nestloop params.
3567 *
3568 * We must provide nestloop params for both lateral references of the
3569 * subquery and outer vars in the scan_clauses. It's better to assign the
3570 * former first, because that code path requires specific param IDs, while
3571 * replace_nestloop_params can adapt to the IDs assigned by
3572 * process_subquery_nestloop_params. This avoids possibly duplicating
3573 * nestloop params when the same Var is needed for both reasons.
3574 */
3575 if (best_path->path.param_info)
3576 {
3578 rel->subplan_params);
3579 scan_clauses = (List *)
3581 }
3582
3585 scan_relid,
3586 subplan);
3587
3588 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3589
3590 return scan_plan;
3591}
static SubqueryScan * make_subqueryscan(List *qptlist, List *qpqual, Index scanrelid, Plan *subplan)
void process_subquery_nestloop_params(PlannerInfo *root, List *subplan_params)
@ RTE_SUBQUERY
List * subplan_params
Definition pathnodes.h:1101
PlannerInfo * subroot
Definition pathnodes.h:1100

References Assert, copy_generic_path_info(), create_plan(), extract_actual_clauses(), fb(), make_subqueryscan(), order_qual_clauses(), process_subquery_nestloop_params(), RelOptInfo::relid, replace_nestloop_params(), root, RTE_SUBQUERY, RelOptInfo::rtekind, 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 3642 of file createplan.c.

3644{
3646 Index scan_relid = best_path->parent->relid;
3648 TableFunc *tablefunc;
3649
3650 /* it should be a function base rel... */
3651 Assert(scan_relid > 0);
3653 Assert(rte->rtekind == RTE_TABLEFUNC);
3654 tablefunc = rte->tablefunc;
3655
3656 /* Sort clauses into best execution order */
3658
3659 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3661
3662 /* Replace any outer-relation variables with nestloop params */
3663 if (best_path->param_info)
3664 {
3665 scan_clauses = (List *)
3667 /* The function expressions could contain nestloop params, too */
3668 tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
3669 }
3670
3672 tablefunc);
3673
3675
3676 return scan_plan;
3677}
static TableFuncScan * make_tablefuncscan(List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
@ RTE_TABLEFUNC

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_tablefuncscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_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 3475 of file createplan.c.

3477{
3479 Index scan_relid = best_path->path.parent->relid;
3480 List *tidrangequals = best_path->tidrangequals;
3481
3482 /* it should be a base rel... */
3483 Assert(scan_relid > 0);
3484 Assert(best_path->path.parent->rtekind == RTE_RELATION);
3485
3486 /*
3487 * The qpqual list must contain all restrictions not enforced by the
3488 * tidrangequals list. tidrangequals has AND semantics, so we can simply
3489 * remove any qual that appears in it.
3490 */
3491 {
3492 List *qpqual = NIL;
3493 ListCell *l;
3494
3495 foreach(l, scan_clauses)
3496 {
3498
3499 if (rinfo->pseudoconstant)
3500 continue; /* we may drop pseudoconstants here */
3501 if (list_member_ptr(tidrangequals, rinfo))
3502 continue; /* simple duplicate */
3503 qpqual = lappend(qpqual, rinfo);
3504 }
3506 }
3507
3508 /* Sort clauses into best execution order */
3510
3511 /* Reduce RestrictInfo lists to bare expressions; ignore pseudoconstants */
3512 tidrangequals = extract_actual_clauses(tidrangequals, false);
3514
3515 /* Replace any outer-relation variables with nestloop params */
3516 if (best_path->path.param_info)
3517 {
3518 tidrangequals = (List *)
3519 replace_nestloop_params(root, (Node *) tidrangequals);
3520 scan_clauses = (List *)
3522 }
3523
3526 scan_relid,
3527 tidrangequals);
3528
3529 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3530
3531 return scan_plan;
3532}
static TidRangeScan * make_tidrangescan(List *qptlist, List *qpqual, Index scanrelid, List *tidrangequals)

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), lappend(), lfirst_node, list_member_ptr(), make_tidrangescan(), NIL, order_qual_clauses(), replace_nestloop_params(), root, and RTE_RELATION.

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

3380{
3382 Index scan_relid = best_path->path.parent->relid;
3383 List *tidquals = best_path->tidquals;
3384
3385 /* it should be a base rel... */
3386 Assert(scan_relid > 0);
3387 Assert(best_path->path.parent->rtekind == RTE_RELATION);
3388
3389 /*
3390 * The qpqual list must contain all restrictions not enforced by the
3391 * tidquals list. Since tidquals has OR semantics, we have to be careful
3392 * about matching it up to scan_clauses. It's convenient to handle the
3393 * single-tidqual case separately from the multiple-tidqual case. In the
3394 * single-tidqual case, we look through the scan_clauses while they are
3395 * still in RestrictInfo form, and drop any that are redundant with the
3396 * tidqual.
3397 *
3398 * In normal cases simple pointer equality checks will be enough to spot
3399 * duplicate RestrictInfos, so we try that first.
3400 *
3401 * Another common case is that a scan_clauses entry is generated from the
3402 * same EquivalenceClass as some tidqual, and is therefore redundant with
3403 * it, though not equal.
3404 *
3405 * Unlike indexpaths, we don't bother with predicate_implied_by(); the
3406 * number of cases where it could win are pretty small.
3407 */
3408 if (list_length(tidquals) == 1)
3409 {
3410 List *qpqual = NIL;
3411 ListCell *l;
3412
3413 foreach(l, scan_clauses)
3414 {
3416
3417 if (rinfo->pseudoconstant)
3418 continue; /* we may drop pseudoconstants here */
3419 if (list_member_ptr(tidquals, rinfo))
3420 continue; /* simple duplicate */
3421 if (is_redundant_derived_clause(rinfo, tidquals))
3422 continue; /* derived from same EquivalenceClass */
3423 qpqual = lappend(qpqual, rinfo);
3424 }
3426 }
3427
3428 /* Sort clauses into best execution order */
3430
3431 /* Reduce RestrictInfo lists to bare expressions; ignore pseudoconstants */
3432 tidquals = extract_actual_clauses(tidquals, false);
3434
3435 /*
3436 * If we have multiple tidquals, it's more convenient to remove duplicate
3437 * scan_clauses after stripping the RestrictInfos. In this situation,
3438 * because the tidquals represent OR sub-clauses, they could not have come
3439 * from EquivalenceClasses so we don't have to worry about matching up
3440 * non-identical clauses. On the other hand, because tidpath.c will have
3441 * extracted those sub-clauses from some OR clause and built its own list,
3442 * we will certainly not have pointer equality to any scan clause. So
3443 * convert the tidquals list to an explicit OR clause and see if we can
3444 * match it via equal() to any scan clause.
3445 */
3446 if (list_length(tidquals) > 1)
3448 list_make1(make_orclause(tidquals)));
3449
3450 /* Replace any outer-relation variables with nestloop params */
3451 if (best_path->path.param_info)
3452 {
3453 tidquals = (List *)
3454 replace_nestloop_params(root, (Node *) tidquals);
3455 scan_clauses = (List *)
3457 }
3458
3459 scan_plan = make_tidscan(tlist,
3461 scan_relid,
3462 tidquals);
3463
3464 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3465
3466 return scan_plan;
3467}
static TidScan * make_tidscan(List *qptlist, List *qpqual, Index scanrelid, List *tidquals)
bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), is_redundant_derived_clause(), lappend(), lfirst_node, list_difference(), list_length(), list_make1, list_member_ptr(), make_orclause(), make_tidscan(), NIL, order_qual_clauses(), replace_nestloop_params(), root, and RTE_RELATION.

Referenced by create_scan_plan().

◆ create_unique_plan()

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

Definition at line 2120 of file createplan.c.

2121{
2122 Unique *plan;
2123 Plan *subplan;
2124
2125 /*
2126 * Unique doesn't project, so tlist requirements pass through; moreover we
2127 * need grouping columns to be labeled.
2128 */
2129 subplan = create_plan_recurse(root, best_path->subpath,
2130 flags | CP_LABEL_TLIST);
2131
2132 /*
2133 * make_unique_from_pathkeys calls find_ec_member_matching_expr, which
2134 * will ignore any child EC members that don't belong to the given relids.
2135 * Thus, if this unique path is based on a child relation, we must pass
2136 * its relids.
2137 */
2139 best_path->path.pathkeys,
2140 best_path->numkeys,
2141 IS_OTHER_REL(best_path->path.parent) ?
2142 best_path->path.parent->relids : NULL);
2143
2145
2146 return plan;
2147}
static Unique * make_unique_from_pathkeys(Plan *lefttree, List *pathkeys, int numCols, Relids relids)

References copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), fb(), IS_OTHER_REL, make_unique_from_pathkeys(), plan, and root.

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

3687{
3689 Index scan_relid = best_path->parent->relid;
3691 List *values_lists;
3692
3693 /* it should be a values base rel... */
3694 Assert(scan_relid > 0);
3696 Assert(rte->rtekind == RTE_VALUES);
3697 values_lists = rte->values_lists;
3698
3699 /* Sort clauses into best execution order */
3701
3702 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3704
3705 /* Replace any outer-relation variables with nestloop params */
3706 if (best_path->param_info)
3707 {
3708 scan_clauses = (List *)
3710 /* The values lists could contain nestloop params, too */
3711 values_lists = (List *)
3712 replace_nestloop_params(root, (Node *) values_lists);
3713 }
3714
3716 values_lists);
3717
3719
3720 return scan_plan;
3721}
static ValuesScan * make_valuesscan(List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
@ RTE_VALUES

References Assert, copy_generic_path_info(), extract_actual_clauses(), fb(), make_valuesscan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_VALUES.

Referenced by create_scan_plan().

◆ create_windowagg_plan()

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

Definition at line 2467 of file createplan.c.

2468{
2469 WindowAgg *plan;
2470 WindowClause *wc = best_path->winclause;
2472 int numOrder = list_length(wc->orderClause);
2473 Plan *subplan;
2474 List *tlist;
2475 int partNumCols;
2479 int ordNumCols;
2483 ListCell *lc;
2484
2485 /*
2486 * Choice of tlist here is motivated by the fact that WindowAgg will be
2487 * storing the input rows of window frames in a tuplestore; it therefore
2488 * behooves us to request a small tlist to avoid wasting space. We do of
2489 * course need grouping columns to be available.
2490 */
2491 subplan = create_plan_recurse(root, best_path->subpath,
2493
2494 tlist = build_path_tlist(root, &best_path->path);
2495
2496 /*
2497 * Convert SortGroupClause lists into arrays of attr indexes and equality
2498 * operators, as wanted by executor.
2499 */
2503
2504 partNumCols = 0;
2505 foreach(lc, wc->partitionClause)
2506 {
2509
2510 Assert(OidIsValid(sgc->eqop));
2511 partColIdx[partNumCols] = tle->resno;
2512 partOperators[partNumCols] = sgc->eqop;
2513 partCollations[partNumCols] = exprCollation((Node *) tle->expr);
2514 partNumCols++;
2515 }
2516
2520
2521 ordNumCols = 0;
2522 foreach(lc, wc->orderClause)
2523 {
2526
2527 Assert(OidIsValid(sgc->eqop));
2528 ordColIdx[ordNumCols] = tle->resno;
2529 ordOperators[ordNumCols] = sgc->eqop;
2530 ordCollations[ordNumCols] = exprCollation((Node *) tle->expr);
2531 ordNumCols++;
2532 }
2533
2534 /* And finally we can make the WindowAgg node */
2535 plan = make_windowagg(tlist,
2536 wc,
2537 partNumCols,
2538 partColIdx,
2541 ordNumCols,
2542 ordColIdx,
2545 best_path->runCondition,
2546 best_path->qual,
2547 best_path->topwindow,
2548 subplan);
2549
2551
2552 return plan;
2553}
static WindowAgg * make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, List *runCondition, List *qual, bool topWindow, Plan *lefttree)
#define palloc_array(type, count)
Definition fe_memutils.h:76
List * partitionClause
List * orderClause

References Assert, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, CP_SMALL_TLIST, create_plan_recurse(), exprCollation(), fb(), get_sortgroupclause_tle(), lfirst, list_length(), make_windowagg(), OidIsValid, WindowClause::orderClause, palloc_array, WindowClause::partitionClause, plan, root, and Plan::targetlist.

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

3903{
3905 Index scan_relid = best_path->parent->relid;
3907 Index levelsup;
3909
3910 Assert(scan_relid > 0);
3912 Assert(rte->rtekind == RTE_CTE);
3913 Assert(rte->self_reference);
3914
3915 /*
3916 * We need to find the worktable param ID, which is in the plan level
3917 * that's processing the recursive UNION, which is one level *below* where
3918 * the CTE comes from.
3919 */
3920 levelsup = rte->ctelevelsup;
3921 if (levelsup == 0) /* shouldn't happen */
3922 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3923 levelsup--;
3924 cteroot = root;
3925 while (levelsup-- > 0)
3926 {
3927 cteroot = cteroot->parent_root;
3928 if (!cteroot) /* shouldn't happen */
3929 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3930 }
3931 if (cteroot->wt_param_id < 0) /* shouldn't happen */
3932 elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
3933
3934 /* Sort clauses into best execution order */
3936
3937 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3939
3940 /* Replace any outer-relation variables with nestloop params */
3941 if (best_path->param_info)
3942 {
3943 scan_clauses = (List *)
3945 }
3946
3948 cteroot->wt_param_id);
3949
3951
3952 return scan_plan;
3953}
static WorkTableScan * make_worktablescan(List *qptlist, List *qpqual, Index scanrelid, int wtParam)

References Assert, copy_generic_path_info(), elog, ERROR, extract_actual_clauses(), fb(), make_worktablescan(), order_qual_clauses(), planner_rt_fetch, replace_nestloop_params(), root, and RTE_CTE.

Referenced by create_scan_plan().

◆ fix_indexorderby_references()

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

Definition at line 5008 of file createplan.c.

5009{
5010 IndexOptInfo *index = index_path->indexinfo;
5012 ListCell *lcc,
5013 *lci;
5014
5016
5017 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5018 {
5019 Node *clause = (Node *) lfirst(lcc);
5020 int indexcol = lfirst_int(lci);
5021
5022 clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5024 }
5025
5026 return fixed_indexorderbys;
5027}
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
#define lfirst_int(lc)
Definition pg_list.h:173
Definition type.h:96

References fb(), fix_indexqual_clause(), forboth, 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 5037 of file createplan.c.

5039{
5040 /*
5041 * Replace any outer-relation variables with nestloop params.
5042 *
5043 * This also makes a copy of the clause, so it's safe to modify it
5044 * in-place below.
5045 */
5046 clause = replace_nestloop_params(root, clause);
5047
5048 if (IsA(clause, OpExpr))
5049 {
5050 OpExpr *op = (OpExpr *) clause;
5051
5052 /* Replace the indexkey expression with an index Var. */
5054 index,
5055 indexcol);
5056 }
5057 else if (IsA(clause, RowCompareExpr))
5058 {
5059 RowCompareExpr *rc = (RowCompareExpr *) clause;
5060 ListCell *lca,
5061 *lcai;
5062
5063 /* Replace the indexkey expressions with index Vars. */
5066 {
5068 index,
5069 lfirst_int(lcai));
5070 }
5071 }
5072 else if (IsA(clause, ScalarArrayOpExpr))
5073 {
5074 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5075
5076 /* Replace the indexkey expression with an index Var. */
5078 index,
5079 indexcol);
5080 }
5081 else if (IsA(clause, NullTest))
5082 {
5083 NullTest *nt = (NullTest *) clause;
5084
5085 /* Replace the indexkey expression with an index Var. */
5086 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5087 index,
5088 indexcol);
5089 }
5090 else
5091 elog(ERROR, "unsupported indexqual type: %d",
5092 (int) nodeTag(clause));
5093
5094 return clause;
5095}
static Node * fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
Datum lca(PG_FUNCTION_ARGS)
Definition ltree_op.c:563
Expr * arg
Definition primnodes.h:1986

References OpExpr::args, ScalarArrayOpExpr::args, Assert, elog, ERROR, fb(), 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 5109 of file createplan.c.

5110{
5111 Var *result;
5112 int pos;
5114
5115 Assert(indexcol >= 0 && indexcol < index->ncolumns);
5116
5117 /*
5118 * Remove any PlaceHolderVar wrapping of the indexkey
5119 */
5120 node = strip_noop_phvs(node);
5121
5122 /*
5123 * Remove any binary-compatible relabeling of the indexkey
5124 */
5125 while (IsA(node, RelabelType))
5126 node = (Node *) ((RelabelType *) node)->arg;
5127
5128 if (index->indexkeys[indexcol] != 0)
5129 {
5130 /* It's a simple index column */
5131 if (IsA(node, Var) &&
5132 ((Var *) node)->varno == index->rel->relid &&
5133 ((Var *) node)->varattno == index->indexkeys[indexcol])
5134 {
5135 result = (Var *) copyObject(node);
5136 result->varno = INDEX_VAR;
5137 result->varattno = indexcol + 1;
5138 return (Node *) result;
5139 }
5140 else
5141 elog(ERROR, "index key does not match expected index column");
5142 }
5143
5144 /* It's an index expression, so find and cross-check the expression */
5145 indexpr_item = list_head(index->indexprs);
5146 for (pos = 0; pos < index->ncolumns; pos++)
5147 {
5148 if (index->indexkeys[pos] == 0)
5149 {
5150 if (indexpr_item == NULL)
5151 elog(ERROR, "too few entries in indexprs list");
5152 if (pos == indexcol)
5153 {
5154 Node *indexkey;
5155
5158 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5159 if (equal(node, indexkey))
5160 {
5161 result = makeVar(INDEX_VAR, indexcol + 1,
5164 0);
5165 return (Node *) result;
5166 }
5167 else
5168 elog(ERROR, "index key does not match expected index column");
5169 }
5170 indexpr_item = lnext(index->indexprs, indexpr_item);
5171 }
5172 }
5173
5174 /* Oops... */
5175 elog(ERROR, "index key does not match expected index column");
5176 return NULL; /* keep compiler quiet */
5177}
uint32 result
Datum arg
Definition elog.c:1322
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
Node * strip_noop_phvs(Node *node)
#define INDEX_VAR
Definition primnodes.h:245

References arg, Assert, copyObject, elog, equal(), ERROR, exprCollation(), exprType(), fb(), INDEX_VAR, IsA, lfirst, list_head(), lnext(), makeVar(), result, and strip_noop_phvs().

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

4969{
4970 IndexOptInfo *index = index_path->indexinfo;
4973 ListCell *lc;
4974
4976
4977 foreach(lc, index_path->indexclauses)
4978 {
4980 int indexcol = iclause->indexcol;
4981 ListCell *lc2;
4982
4983 foreach(lc2, iclause->indexquals)
4984 {
4986 Node *clause = (Node *) rinfo->clause;
4987
4989 clause = fix_indexqual_clause(root, index, indexcol,
4990 clause, iclause->indexcols);
4992 }
4993 }
4994
4997}

References RestrictInfo::clause, fb(), fix_indexqual_clause(), 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 994 of file createplan.c.

995{
996 /* No need to look if we know there are no pseudoconstants */
997 if (!root->hasPseudoConstantQuals)
998 return NIL;
999
1000 /* Sort into desirable execution order while still in RestrictInfo form */
1001 quals = order_qual_clauses(root, quals);
1002
1003 /* Pull out any pseudoconstant quals from the RestrictInfo list */
1004 return extract_actual_clauses(quals, true);
1005}

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

5190{
5191 List *t_list = NIL;
5192 ListCell *l;
5193
5194 foreach(l, clauses)
5195 {
5197 OpExpr *clause = (OpExpr *) restrictinfo->clause;
5198
5199 Assert(is_opclause(clause));
5200 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5201 {
5202 /*
5203 * Duplicate just enough of the structure to allow commuting the
5204 * clause without changing the original list. Could use
5205 * copyObject, but a complete deep copy is overkill.
5206 */
5208
5209 temp->opno = clause->opno;
5210 temp->opfuncid = InvalidOid;
5211 temp->opresulttype = clause->opresulttype;
5212 temp->opretset = clause->opretset;
5213 temp->opcollid = clause->opcollid;
5214 temp->inputcollid = clause->inputcollid;
5215 temp->args = list_copy(clause->args);
5216 temp->location = clause->location;
5217 /* Commute it --- note this modifies the temp node in-place. */
5220 restrictinfo->outer_is_left = false;
5221 }
5222 else
5223 {
5224 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5225 t_list = lappend(t_list, clause);
5226 restrictinfo->outer_is_left = true;
5227 }
5228 }
5229 return t_list;
5230}
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:412
void CommuteOpExpr(OpExpr *clause)
Definition clauses.c:2390

References OpExpr::args, Assert, bms_is_subset(), CommuteOpExpr(), fb(), 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 1960 of file createplan.c.

1961{
1962 Plan *plan;
1963
1964 plan = (Plan *) make_gating_result(tlist, NULL, subplan);
1965
1966 /*
1967 * In principle, we should charge tlist eval cost plus cpu_per_tuple per
1968 * row for the Result node. But the former has probably been factored in
1969 * already and the latter was not accounted for during Path construction,
1970 * so being formally correct might just make the EXPLAIN output look less
1971 * consistent not more so. Hence, just copy the subplan's cost.
1972 */
1973 copy_plan_costsize(plan, subplan);
1974 plan->parallel_safe = parallel_safe;
1975
1976 return plan;
1977}

References copy_plan_costsize(), fb(), make_gating_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 7231 of file createplan.c.

7232{
7233 /* Most plan types can project, so just list the ones that can't */
7234 switch (path->pathtype)
7235 {
7236 case T_Hash:
7237 case T_Material:
7238 case T_Memoize:
7239 case T_Sort:
7240 case T_IncrementalSort:
7241 case T_Unique:
7242 case T_SetOp:
7243 case T_LockRows:
7244 case T_Limit:
7245 case T_ModifyTable:
7246 case T_MergeAppend:
7247 case T_RecursiveUnion:
7248 return false;
7249 case T_CustomScan:
7251 return true;
7252 return false;
7253 case T_Append:
7254
7255 /*
7256 * Append can't project, but if an AppendPath is being used to
7257 * represent a dummy path, what will actually be generated is a
7258 * Result which can project.
7259 */
7260 return IS_DUMMY_APPEND(path);
7261 case T_ProjectSet:
7262
7263 /*
7264 * Although ProjectSet certainly projects, say "no" because we
7265 * don't want the planner to randomly replace its tlist with
7266 * something else; the SRFs have to stay at top level. This might
7267 * get relaxed later.
7268 */
7269 return false;
7270 default:
7271 break;
7272 }
7273 return true;
7274}
#define CUSTOMPATH_SUPPORT_PROJECTION
Definition extensible.h:86
#define IS_DUMMY_APPEND(p)
Definition pathnodes.h:2291
NodeTag pathtype
Definition pathnodes.h:1971

References castNode, CUSTOMPATH_SUPPORT_PROJECTION, fb(), 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 7281 of file createplan.c.

7282{
7283 /* Most plan types can project, so just list the ones that can't */
7284 switch (nodeTag(plan))
7285 {
7286 case T_Hash:
7287 case T_Material:
7288 case T_Memoize:
7289 case T_Sort:
7290 case T_Unique:
7291 case T_SetOp:
7292 case T_LockRows:
7293 case T_Limit:
7294 case T_ModifyTable:
7295 case T_Append:
7296 case T_MergeAppend:
7297 case T_RecursiveUnion:
7298 return false;
7299 case T_CustomScan:
7301 return true;
7302 return false;
7303 case T_ProjectSet:
7304
7305 /*
7306 * Although ProjectSet certainly projects, say "no" because we
7307 * don't want the planner to randomly replace its tlist with
7308 * something else; the SRFs have to stay at top level. This might
7309 * get relaxed later.
7310 */
7311 return false;
7312 default:
7313 break;
7314 }
7315 return true;
7316}

References CUSTOMPATH_SUPPORT_PROJECTION, fb(), 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 5427 of file createplan.c.

5429{
5430 Plan *lefttree = plan->sort.plan.lefttree;
5431 Path sort_path; /* dummy for result of cost_incremental_sort */
5432
5434
5436 plan->nPresortedCols,
5437 plan->sort.plan.disabled_nodes,
5438 lefttree->startup_cost,
5439 lefttree->total_cost,
5440 lefttree->plan_rows,
5441 lefttree->plan_width,
5442 0.0,
5443 work_mem,
5444 limit_tuples);
5445 plan->sort.plan.startup_cost = sort_path.startup_cost;
5446 plan->sort.plan.total_cost = sort_path.total_cost;
5447 plan->sort.plan.plan_rows = lefttree->plan_rows;
5448 plan->sort.plan.plan_width = lefttree->plan_width;
5449 plan->sort.plan.parallel_aware = false;
5450 plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5451}
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:2053
int work_mem
Definition globals.c:133

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

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

◆ label_sort_with_costsize()

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

Definition at line 5399 of file createplan.c.

5400{
5401 Plan *lefttree = plan->plan.lefttree;
5402 Path sort_path; /* dummy for result of cost_sort */
5403
5404 Assert(IsA(plan, Sort));
5405
5407 plan->plan.disabled_nodes,
5408 lefttree->total_cost,
5409 lefttree->plan_rows,
5410 lefttree->plan_width,
5411 0.0,
5412 work_mem,
5413 limit_tuples);
5414 plan->plan.startup_cost = sort_path.startup_cost;
5415 plan->plan.total_cost = sort_path.total_cost;
5416 plan->plan.plan_rows = lefttree->plan_rows;
5417 plan->plan.plan_width = lefttree->plan_width;
5418 plan->plan.parallel_aware = false;
5419 plan->plan.parallel_safe = lefttree->parallel_safe;
5420}
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:2201

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

Referenced by create_append_plan(), create_merge_append_plan(), and create_mergejoin_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,
Cardinality  numGroups,
Size  transitionSpace,
Plan lefttree 
)

Definition at line 6583 of file createplan.c.

6588{
6589 Agg *node = makeNode(Agg);
6590 Plan *plan = &node->plan;
6591
6592 node->aggstrategy = aggstrategy;
6593 node->aggsplit = aggsplit;
6594 node->numCols = numGroupCols;
6595 node->grpColIdx = grpColIdx;
6596 node->grpOperators = grpOperators;
6597 node->grpCollations = grpCollations;
6598 node->numGroups = numGroups;
6599 node->transitionSpace = transitionSpace;
6600 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6601 node->groupingSets = groupingSets;
6602 node->chain = chain;
6603
6604 plan->qual = qual;
6605 plan->targetlist = tlist;
6606 plan->lefttree = lefttree;
6607 plan->righttree = NULL;
6608
6609 return node;
6610}
AggSplit aggsplit
Definition plannodes.h:1217
List * chain
Definition plannodes.h:1244
List * groupingSets
Definition plannodes.h:1241
Bitmapset * aggParams
Definition plannodes.h:1236
Cardinality numGroups
Definition plannodes.h:1230
Plan plan
Definition plannodes.h:1211
int numCols
Definition plannodes.h:1220
uint64 transitionSpace
Definition plannodes.h:1233
AggStrategy aggstrategy
Definition plannodes.h:1214
struct Plan * righttree
Definition plannodes.h:240

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

Referenced by create_agg_plan(), and create_groupingsets_plan().

◆ make_bitmap_and()

static BitmapAnd * make_bitmap_and ( List bitmapplans)
static

Definition at line 5899 of file createplan.c.

5900{
5901 BitmapAnd *node = makeNode(BitmapAnd);
5902 Plan *plan = &node->plan;
5903
5904 plan->targetlist = NIL;
5905 plan->qual = NIL;
5906 plan->lefttree = NULL;
5907 plan->righttree = NULL;
5908 node->bitmapplans = bitmapplans;
5909
5910 return node;
5911}
Plan plan
Definition plannodes.h:512
List * bitmapplans
Definition plannodes.h:513

References BitmapAnd::bitmapplans, fb(), makeNode, NIL, BitmapAnd::plan, plan, and Plan::targetlist.

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

5611{
5613 Plan *plan = &node->scan.plan;
5614
5615 plan->targetlist = qptlist;
5616 plan->qual = qpqual;
5617 plan->lefttree = lefttree;
5618 plan->righttree = NULL;
5619 node->scan.scanrelid = scanrelid;
5620 node->bitmapqualorig = bitmapqualorig;
5621
5622 return node;
5623}
List * bitmapqualorig
Definition plannodes.h:714

References BitmapHeapScan::bitmapqualorig, fb(), makeNode, plan, Plan::righttree, 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 5585 of file createplan.c.

5589{
5591 Plan *plan = &node->scan.plan;
5592
5593 plan->targetlist = NIL; /* not used */
5594 plan->qual = NIL; /* not used */
5595 plan->lefttree = NULL;
5596 plan->righttree = NULL;
5597 node->scan.scanrelid = scanrelid;
5598 node->indexid = indexid;
5599 node->indexqual = indexqual;
5600 node->indexqualorig = indexqualorig;
5601
5602 return node;
5603}
List * indexqualorig
Definition plannodes.h:698

References fb(), 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 5914 of file createplan.c.

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

References BitmapOr::bitmapplans, fb(), makeNode, NIL, BitmapOr::plan, plan, and Plan::targetlist.

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

5748{
5749 CteScan *node = makeNode(CteScan);
5750 Plan *plan = &node->scan.plan;
5751
5752 plan->targetlist = qptlist;
5753 plan->qual = qpqual;
5754 plan->lefttree = NULL;
5755 plan->righttree = NULL;
5756 node->scan.scanrelid = scanrelid;
5757 node->ctePlanId = ctePlanId;
5758 node->cteParam = cteParam;
5759
5760 return node;
5761}
int ctePlanId
Definition plannodes.h:823
int cteParam
Definition plannodes.h:825
Scan scan
Definition plannodes.h:821

References CteScan::cteParam, CteScan::ctePlanId, fb(), 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 5803 of file createplan.c.

5811{
5813 Plan *plan = &node->scan.plan;
5814
5815 /* cost will be filled in by create_foreignscan_plan */
5816 plan->targetlist = qptlist;
5817 plan->qual = qpqual;
5818 plan->lefttree = outer_plan;
5819 plan->righttree = NULL;
5820 node->scan.scanrelid = scanrelid;
5821
5822 /* these may be overridden by the FDW's PlanDirectModify callback. */
5823 node->operation = CMD_SELECT;
5824 node->resultRelation = 0;
5825
5826 /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5827 node->checkAsUser = InvalidOid;
5828 node->fs_server = InvalidOid;
5829 node->fdw_exprs = fdw_exprs;
5830 node->fdw_private = fdw_private;
5831 node->fdw_scan_tlist = fdw_scan_tlist;
5832 node->fdw_recheck_quals = fdw_recheck_quals;
5833 /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5834 node->fs_relids = NULL;
5835 node->fs_base_relids = NULL;
5836 /* fsSystemCol will be filled in by create_foreignscan_plan */
5837 node->fsSystemCol = false;
5838
5839 return node;
5840}
@ CMD_SELECT
Definition nodes.h:275
Oid checkAsUser
Definition plannodes.h:898
CmdType operation
Definition plannodes.h:894
List * fdw_exprs
Definition plannodes.h:902
bool fsSystemCol
Definition plannodes.h:914
Bitmapset * fs_relids
Definition plannodes.h:910
List * fdw_private
Definition plannodes.h:904
Bitmapset * fs_base_relids
Definition plannodes.h:912
Index resultRelation
Definition plannodes.h:896
List * fdw_recheck_quals
Definition plannodes.h:908
List * fdw_scan_tlist
Definition plannodes.h:906

References ForeignScan::checkAsUser, CMD_SELECT, fb(), 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, Plan::righttree, 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 5684 of file createplan.c.

5689{
5691 Plan *plan = &node->scan.plan;
5692
5693 plan->targetlist = qptlist;
5694 plan->qual = qpqual;
5695 plan->lefttree = NULL;
5696 plan->righttree = NULL;
5697 node->scan.scanrelid = scanrelid;
5698 node->functions = functions;
5699 node->funcordinality = funcordinality;
5700
5701 return node;
5702}
List * functions
Definition plannodes.h:788
bool funcordinality
Definition plannodes.h:790

References fb(), 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 6791 of file createplan.c.

6797{
6798 Gather *node = makeNode(Gather);
6799 Plan *plan = &node->plan;
6800
6802 plan->qual = qpqual;
6803 plan->lefttree = subplan;
6804 plan->righttree = NULL;
6805 node->num_workers = nworkers;
6806 node->rescan_param = rescan_param;
6807 node->single_copy = single_copy;
6808 node->invisible = false;
6809 node->initParam = NULL;
6810
6811 return node;
6812}
int num_workers
Definition plannodes.h:1360
bool invisible
Definition plannodes.h:1366
Bitmapset * initParam
Definition plannodes.h:1372
bool single_copy
Definition plannodes.h:1364
Plan plan
Definition plannodes.h:1358
int rescan_param
Definition plannodes.h:1362

References fb(), Gather::initParam, Gather::invisible, makeNode, Gather::num_workers, Gather::plan, plan, Gather::rescan_param, Plan::righttree, Gather::single_copy, and Plan::targetlist.

Referenced by create_gather_plan().

◆ make_gating_result()

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

Definition at line 6931 of file createplan.c.

6934{
6935 Result *node = makeNode(Result);
6936 Plan *plan = &node->plan;
6937
6938 Assert(subplan != NULL);
6939
6940 plan->targetlist = tlist;
6941 plan->qual = NIL;
6942 plan->lefttree = subplan;
6943 plan->righttree = NULL;
6945 node->resconstantqual = resconstantqual;
6946 node->relids = NULL;
6947
6948 return node;
6949}
@ RESULT_TYPE_GATING
Definition plannodes.h:277
Node * resconstantqual
Definition plannodes.h:305

References Assert, fb(), makeNode, NIL, Result::plan, plan, Result::relids, Result::resconstantqual, Result::result_type, RESULT_TYPE_GATING, and Plan::righttree.

Referenced by create_gating_plan(), create_projection_plan(), and inject_projection_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 6653 of file createplan.c.

6660{
6661 Group *node = makeNode(Group);
6662 Plan *plan = &node->plan;
6663
6664 node->numCols = numGroupCols;
6665 node->grpColIdx = grpColIdx;
6666 node->grpOperators = grpOperators;
6667 node->grpCollations = grpCollations;
6668
6669 plan->qual = qual;
6670 plan->targetlist = tlist;
6671 plan->lefttree = lefttree;
6672 plan->righttree = NULL;
6673
6674 return node;
6675}
int numCols
Definition plannodes.h:1185
Plan plan
Definition plannodes.h:1182

References fb(), makeNode, Group::numCols, Group::plan, plan, and Plan::righttree.

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

5990{
5991 Hash *node = makeNode(Hash);
5992 Plan *plan = &node->plan;
5993
5994 plan->targetlist = lefttree->targetlist;
5995 plan->qual = NIL;
5996 plan->lefttree = lefttree;
5997 plan->righttree = NULL;
5998
5999 node->hashkeys = hashkeys;
6000 node->skewTable = skewTable;
6001 node->skewColumn = skewColumn;
6002 node->skewInherit = skewInherit;
6003
6004 return node;
6005}
AttrNumber skewColumn
Definition plannodes.h:1434
List * hashkeys
Definition plannodes.h:1430
Oid skewTable
Definition plannodes.h:1432
bool skewInherit
Definition plannodes.h:1436
Plan plan
Definition plannodes.h:1423

References fb(), Hash::hashkeys, makeNode, NIL, Hash::plan, plan, Plan::righttree, 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 5954 of file createplan.c.

5965{
5966 HashJoin *node = makeNode(HashJoin);
5967 Plan *plan = &node->join.plan;
5968
5969 plan->targetlist = tlist;
5970 plan->qual = otherclauses;
5971 plan->lefttree = lefttree;
5972 plan->righttree = righttree;
5973 node->hashclauses = hashclauses;
5974 node->hashoperators = hashoperators;
5975 node->hashcollations = hashcollations;
5976 node->hashkeys = hashkeys;
5977 node->join.jointype = jointype;
5978 node->join.inner_unique = inner_unique;
5979 node->join.joinqual = joinclauses;
5980
5981 return node;
5982}
List * hashcollations
Definition plannodes.h:1069
List * hashclauses
Definition plannodes.h:1067
List * hashoperators
Definition plannodes.h:1068
Join join
Definition plannodes.h:1066
List * hashkeys
Definition plannodes.h:1075
List * joinqual
Definition plannodes.h:992
JoinType jointype
Definition plannodes.h:989
bool inner_unique
Definition plannodes.h:990

References fb(), HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, Join::inner_unique, HashJoin::join, Join::joinqual, Join::jointype, makeNode, plan, and Plan::righttree.

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

6083{
6084 IncrementalSort *node;
6085 Plan *plan;
6086
6087 node = makeNode(IncrementalSort);
6088
6089 plan = &node->sort.plan;
6090 plan->targetlist = lefttree->targetlist;
6091 plan->qual = NIL;
6092 plan->lefttree = lefttree;
6093 plan->righttree = NULL;
6094 node->nPresortedCols = nPresortedCols;
6095 node->sort.numCols = numCols;
6096 node->sort.sortColIdx = sortColIdx;
6097 node->sort.sortOperators = sortOperators;
6098 node->sort.collations = collations;
6099 node->sort.nullsFirst = nullsFirst;
6100
6101 return node;
6102}
int numCols
Definition plannodes.h:1148
Plan plan
Definition plannodes.h:1145

References fb(), makeNode, NIL, IncrementalSort::nPresortedCols, Sort::numCols, Sort::plan, plan, Plan::righttree, IncrementalSort::sort, and Plan::targetlist.

Referenced by create_append_plan(), create_merge_append_plan(), and 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 6363 of file createplan.c.

6365{
6366 int numsortkeys;
6367 AttrNumber *sortColIdx;
6368 Oid *sortOperators;
6369 Oid *collations;
6370 bool *nullsFirst;
6371
6372 /* Compute sort column info, and adjust lefttree as needed */
6373 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6374 relids,
6375 NULL,
6376 false,
6377 &numsortkeys,
6378 &sortColIdx,
6379 &sortOperators,
6380 &collations,
6381 &nullsFirst);
6382
6383 /* Now build the Sort node */
6384 return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6385 sortColIdx, sortOperators,
6386 collations, nullsFirst);
6387}

References fb(), 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 5556 of file createplan.c.

5565{
5567 Plan *plan = &node->scan.plan;
5568
5569 plan->targetlist = qptlist;
5570 plan->qual = qpqual;
5571 plan->lefttree = NULL;
5572 plan->righttree = NULL;
5573 node->scan.scanrelid = scanrelid;
5574 node->indexid = indexid;
5575 node->indexqual = indexqual;
5576 node->recheckqual = recheckqual;
5577 node->indexorderby = indexorderby;
5578 node->indextlist = indextlist;
5579 node->indexorderdir = indexscandir;
5580
5581 return node;
5582}
List * indexqual
Definition plannodes.h:660
List * recheckqual
Definition plannodes.h:662
List * indextlist
Definition plannodes.h:666
ScanDirection indexorderdir
Definition plannodes.h:668
List * indexorderby
Definition plannodes.h:664

References fb(), 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 5525 of file createplan.c.

5535{
5536 IndexScan *node = makeNode(IndexScan);
5537 Plan *plan = &node->scan.plan;
5538
5539 plan->targetlist = qptlist;
5540 plan->qual = qpqual;
5541 plan->lefttree = NULL;
5542 plan->righttree = NULL;
5543 node->scan.scanrelid = scanrelid;
5544 node->indexid = indexid;
5545 node->indexqual = indexqual;
5546 node->indexqualorig = indexqualorig;
5547 node->indexorderby = indexorderby;
5548 node->indexorderbyorig = indexorderbyorig;
5549 node->indexorderbyops = indexorderbyops;
5550 node->indexorderdir = indexscandir;
5551
5552 return node;
5553}
List * indexorderby
Definition plannodes.h:614
List * indexorderbyops
Definition plannodes.h:618
ScanDirection indexorderdir
Definition plannodes.h:620
List * indexorderbyorig
Definition plannodes.h:616

References fb(), 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 6902 of file createplan.c.

6905{
6906 Limit *node = makeNode(Limit);
6907 Plan *plan = &node->plan;
6908
6909 plan->targetlist = lefttree->targetlist;
6910 plan->qual = NIL;
6911 plan->lefttree = lefttree;
6912 plan->righttree = NULL;
6913
6914 node->limitOffset = limitOffset;
6915 node->limitCount = limitCount;
6916 node->limitOption = limitOption;
6917 node->uniqNumCols = uniqNumCols;
6918 node->uniqColIdx = uniqColIdx;
6919 node->uniqOperators = uniqOperators;
6920 node->uniqCollations = uniqCollations;
6921
6922 return node;
6923}
LimitOption limitOption
Definition plannodes.h:1509
Plan plan
Definition plannodes.h:1500
Node * limitCount
Definition plannodes.h:1506
int uniqNumCols
Definition plannodes.h:1512
Node * limitOffset
Definition plannodes.h:1503

References fb(), Limit::limitCount, Limit::limitOffset, Limit::limitOption, makeNode, NIL, Limit::plan, plan, Plan::righttree, 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 6881 of file createplan.c.

6882{
6883 LockRows *node = makeNode(LockRows);
6884 Plan *plan = &node->plan;
6885
6886 plan->targetlist = lefttree->targetlist;
6887 plan->qual = NIL;
6888 plan->lefttree = lefttree;
6889 plan->righttree = NULL;
6890
6891 node->rowMarks = rowMarks;
6892 node->epqParam = epqParam;
6893
6894 return node;
6895}
int epqParam
Definition plannodes.h:1488
List * rowMarks
Definition plannodes.h:1486
Plan plan
Definition plannodes.h:1484

References LockRows::epqParam, fb(), makeNode, NIL, LockRows::plan, plan, Plan::righttree, LockRows::rowMarks, and Plan::targetlist.

Referenced by create_lockrows_plan().

◆ make_material()

static Material * make_material ( Plan lefttree)
static

Definition at line 6487 of file createplan.c.

6488{
6489 Material *node = makeNode(Material);
6490 Plan *plan = &node->plan;
6491
6492 plan->targetlist = lefttree->targetlist;
6493 plan->qual = NIL;
6494 plan->lefttree = lefttree;
6495 plan->righttree = NULL;
6496
6497 return node;
6498}
Plan plan
Definition plannodes.h:1084

References fb(), makeNode, NIL, Material::plan, plan, Plan::righttree, 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,
Cardinality  est_calls,
Cardinality  est_unique_keys,
double  est_hit_ratio 
)
static

Definition at line 6553 of file createplan.c.

6558{
6559 Memoize *node = makeNode(Memoize);
6560 Plan *plan = &node->plan;
6561
6562 plan->targetlist = lefttree->targetlist;
6563 plan->qual = NIL;
6564 plan->lefttree = lefttree;
6565 plan->righttree = NULL;
6566
6567 node->numKeys = list_length(param_exprs);
6568 node->hashOperators = hashoperators;
6569 node->collations = collations;
6570 node->param_exprs = param_exprs;
6571 node->singlerow = singlerow;
6572 node->binary_mode = binary_mode;
6573 node->est_entries = est_entries;
6574 node->keyparamids = keyparamids;
6575 node->est_calls = est_calls;
6576 node->est_unique_keys = est_unique_keys;
6577 node->est_hit_ratio = est_hit_ratio;
6578
6579 return node;
6580}
Plan plan
Definition plannodes.h:1093
bool singlerow
Definition plannodes.h:1111
Cardinality est_calls
Definition plannodes.h:1129
Bitmapset * keyparamids
Definition plannodes.h:1126
bool binary_mode
Definition plannodes.h:1117
int numKeys
Definition plannodes.h:1096
Cardinality est_unique_keys
Definition plannodes.h:1132
List * param_exprs
Definition plannodes.h:1105
double est_hit_ratio
Definition plannodes.h:1135
uint32 est_entries
Definition plannodes.h:1123

References Memoize::binary_mode, Memoize::est_calls, Memoize::est_entries, Memoize::est_hit_ratio, Memoize::est_unique_keys, fb(), Memoize::keyparamids, list_length(), makeNode, NIL, Memoize::numKeys, Memoize::param_exprs, Memoize::plan, plan, Plan::righttree, 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 6008 of file createplan.c.

6021{
6022 MergeJoin *node = makeNode(MergeJoin);
6023 Plan *plan = &node->join.plan;
6024
6025 plan->targetlist = tlist;
6026 plan->qual = otherclauses;
6027 plan->lefttree = lefttree;
6028 plan->righttree = righttree;
6029 node->skip_mark_restore = skip_mark_restore;
6030 node->mergeclauses = mergeclauses;
6031 node->mergeFamilies = mergefamilies;
6032 node->mergeCollations = mergecollations;
6033 node->mergeReversals = mergereversals;
6034 node->mergeNullsFirst = mergenullsfirst;
6035 node->join.jointype = jointype;
6036 node->join.inner_unique = inner_unique;
6037 node->join.joinqual = joinclauses;
6038
6039 return node;
6040}
List * mergeclauses
Definition plannodes.h:1043
bool skip_mark_restore
Definition plannodes.h:1040

References fb(), Join::inner_unique, MergeJoin::join, Join::joinqual, Join::jointype, makeNode, MergeJoin::mergeclauses, plan, Plan::righttree, 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,
List resultRelations,
List updateColnosLists,
List withCheckOptionLists,
List returningLists,
List rowMarks,
OnConflictExpr onconflict,
List mergeActionLists,
List mergeJoinConditions,
ForPortionOfExpr forPortionOf,
int  epqParam 
)
static

Definition at line 7005 of file createplan.c.

7014{
7016 bool returning_old_or_new = false;
7017 bool returning_old_or_new_valid = false;
7018 bool transition_tables = false;
7019 bool transition_tables_valid = false;
7022 ListCell *lc;
7023 int i;
7024
7026 (operation == CMD_UPDATE ?
7027 list_length(resultRelations) == list_length(updateColnosLists) :
7028 updateColnosLists == NIL));
7029 Assert(withCheckOptionLists == NIL ||
7030 list_length(resultRelations) == list_length(withCheckOptionLists));
7031 Assert(returningLists == NIL ||
7032 list_length(resultRelations) == list_length(returningLists));
7033
7034 node->plan.lefttree = subplan;
7035 node->plan.righttree = NULL;
7036 node->plan.qual = NIL;
7037 /* setrefs.c will fill in the targetlist, if needed */
7038 node->plan.targetlist = NIL;
7039
7040 node->operation = operation;
7041 node->canSetTag = canSetTag;
7042 node->nominalRelation = nominalRelation;
7043 node->rootRelation = rootRelation;
7044 node->resultRelations = resultRelations;
7045 if (!onconflict)
7046 {
7049 node->onConflictSet = NIL;
7050 node->onConflictCols = NIL;
7051 node->onConflictWhere = NULL;
7052 node->arbiterIndexes = NIL;
7053 node->exclRelRTI = 0;
7054 node->exclRelTlist = NIL;
7055 }
7056 else
7057 {
7058 node->onConflictAction = onconflict->action;
7059
7060 /* Lock strength for ON CONFLICT DO SELECT [FOR UPDATE/SHARE] */
7061 node->onConflictLockStrength = onconflict->lockStrength;
7062
7063 /*
7064 * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7065 * executor's convention of having consecutive resno's. The actual
7066 * target column numbers are saved in node->onConflictCols. (This
7067 * could be done earlier, but there seems no need to.)
7068 */
7069 node->onConflictSet = onconflict->onConflictSet;
7070 node->onConflictCols =
7072 node->onConflictWhere = onconflict->onConflictWhere;
7073
7074 /*
7075 * If a set of unique index inference elements was provided (an
7076 * INSERT...ON CONFLICT "inference specification"), then infer
7077 * appropriate unique indexes (or throw an error if none are
7078 * available).
7079 */
7081
7082 node->exclRelRTI = onconflict->exclRelIndex;
7083 node->exclRelTlist = onconflict->exclRelTlist;
7084 }
7085 node->updateColnosLists = updateColnosLists;
7086 node->forPortionOf = (Node *) forPortionOf;
7087 node->withCheckOptionLists = withCheckOptionLists;
7088 node->returningOldAlias = root->parse->returningOldAlias;
7089 node->returningNewAlias = root->parse->returningNewAlias;
7090 node->returningLists = returningLists;
7091 node->rowMarks = rowMarks;
7092 node->mergeActionLists = mergeActionLists;
7093 node->mergeJoinConditions = mergeJoinConditions;
7094 node->epqParam = epqParam;
7095
7096 /*
7097 * For each result relation that is a foreign table, allow the FDW to
7098 * construct private plan data, and accumulate it all into a list.
7099 */
7102 i = 0;
7103 foreach(lc, resultRelations)
7104 {
7105 Index rti = lfirst_int(lc);
7106 FdwRoutine *fdwroutine;
7107 List *fdw_private;
7108 bool direct_modify;
7109
7110 /*
7111 * If possible, we want to get the FdwRoutine from our RelOptInfo for
7112 * the table. But sometimes we don't have a RelOptInfo and must get
7113 * it the hard way. (In INSERT, the target relation is not scanned,
7114 * so it's not a baserel; and there are also corner cases for
7115 * updatable views where the target rel isn't a baserel.)
7116 */
7117 if (rti < root->simple_rel_array_size &&
7118 root->simple_rel_array[rti] != NULL)
7119 {
7120 RelOptInfo *resultRel = root->simple_rel_array[rti];
7121
7122 fdwroutine = resultRel->fdwroutine;
7123 }
7124 else
7125 {
7127
7128 if (rte->rtekind == RTE_RELATION &&
7129 rte->relkind == RELKIND_FOREIGN_TABLE)
7130 {
7131 /* Check if the access to foreign tables is restricted */
7133 {
7134 /* there must not be built-in foreign tables */
7135 Assert(rte->relid >= FirstNormalObjectId);
7136 ereport(ERROR,
7138 errmsg("access to non-system foreign table is restricted")));
7139 }
7140
7141 fdwroutine = GetFdwRoutineByRelId(rte->relid);
7142 }
7143 else
7144 fdwroutine = NULL;
7145 }
7146
7147 /*
7148 * MERGE is not currently supported for foreign tables. We already
7149 * checked that when the table mentioned in the query is foreign; but
7150 * we can still get here if a partitioned table has a foreign table as
7151 * partition. Disallow that now, to avoid an uglier error message
7152 * later.
7153 */
7154 if (operation == CMD_MERGE && fdwroutine != NULL)
7155 {
7157
7158 ereport(ERROR,
7160 errmsg("cannot execute MERGE on relation \"%s\"",
7161 get_rel_name(rte->relid)),
7163 }
7164
7165 /*
7166 * Try to modify the foreign table directly if (1) the FDW provides
7167 * callback functions needed for that and (2) there are no local
7168 * structures that need to be run for each modified row: row-level
7169 * triggers on the foreign table, stored generated columns, WITH CHECK
7170 * OPTIONs from parent views, Vars returning OLD/NEW in the RETURNING
7171 * list, or transition tables on the named relation.
7172 */
7173 direct_modify = false;
7174 if (fdwroutine != NULL &&
7175 fdwroutine->PlanDirectModify != NULL &&
7176 fdwroutine->BeginDirectModify != NULL &&
7177 fdwroutine->IterateDirectModify != NULL &&
7178 fdwroutine->EndDirectModify != NULL &&
7179 withCheckOptionLists == NIL &&
7182 {
7183 /*
7184 * returning_old_or_new and transition_tables are the same for all
7185 * result relations, respectively
7186 */
7188 {
7191 root->parse->returningList);
7193 }
7195 {
7197 {
7199 nominalRelation,
7200 operation);
7202 }
7203 if (!transition_tables)
7204 direct_modify = fdwroutine->PlanDirectModify(root, node,
7205 rti, i);
7206 }
7207 }
7208 if (direct_modify)
7210
7211 if (!direct_modify &&
7212 fdwroutine != NULL &&
7213 fdwroutine->PlanForeignModify != NULL)
7214 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7215 else
7216 fdw_private = NIL;
7218 i++;
7219 }
7222
7223 return node;
7224}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:799
#define unlikely(x)
Definition c.h:438
static DataChecksumsWorkerOperation operation
int errcode(int sqlerrcode)
Definition elog.c:874
#define ereport(elevel,...)
Definition elog.h:152
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition foreign.c:451
@ LCS_NONE
Definition lockoptions.h:23
char * get_rel_name(Oid relid)
Definition lsyscache.c:2148
@ ONCONFLICT_NONE
Definition nodes.h:428
@ CMD_MERGE
Definition nodes.h:279
@ CMD_UPDATE
Definition nodes.h:276
static char * errmsg
int errdetail_relkind_not_supported(char relkind)
Definition pg_class.c:24
bool has_stored_generated_columns(PlannerInfo *root, Index rti)
Definition plancat.c:2613
bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
Definition plancat.c:2509
bool has_transition_tables(PlannerInfo *root, Index rti, CmdType event)
Definition plancat.c:2559
List * infer_arbiter_indexes(PlannerInfo *root)
Definition plancat.c:802
int restrict_nonsystem_relation_kind
Definition postgres.c:111
List * extract_update_targetlist_colnos(List *tlist)
Definition preptlist.c:350
BeginDirectModify_function BeginDirectModify
Definition fdwapi.h:246
PlanForeignModify_function PlanForeignModify
Definition fdwapi.h:234
PlanDirectModify_function PlanDirectModify
Definition fdwapi.h:245
IterateDirectModify_function IterateDirectModify
Definition fdwapi.h:247
EndDirectModify_function EndDirectModify
Definition fdwapi.h:248
List * updateColnosLists
Definition plannodes.h:350
Index nominalRelation
Definition plannodes.h:344
List * arbiterIndexes
Definition plannodes.h:370
List * onConflictCols
Definition plannodes.h:376
List * mergeJoinConditions
Definition plannodes.h:388
char * returningOldAlias
Definition plannodes.h:354
char * returningNewAlias
Definition plannodes.h:356
CmdType operation
Definition plannodes.h:340
Node * forPortionOf
Definition plannodes.h:380
List * resultRelations
Definition plannodes.h:348
Bitmapset * fdwDirectModifyPlans
Definition plannodes.h:362
List * onConflictSet
Definition plannodes.h:374
List * exclRelTlist
Definition plannodes.h:384
List * mergeActionLists
Definition plannodes.h:386
bool canSetTag
Definition plannodes.h:342
List * fdwPrivLists
Definition plannodes.h:360
List * returningLists
Definition plannodes.h:358
List * withCheckOptionLists
Definition plannodes.h:352
LockClauseStrength onConflictLockStrength
Definition plannodes.h:372
Index rootRelation
Definition plannodes.h:346
Node * onConflictWhere
Definition plannodes.h:378
List * rowMarks
Definition plannodes.h:364
OnConflictAction onConflictAction
Definition plannodes.h:368
Index exclRelRTI
Definition plannodes.h:382
OnConflictAction action
Definition primnodes.h:2400
LockClauseStrength lockStrength
Definition primnodes.h:2409
List * onConflictSet
Definition primnodes.h:2412
List * exclRelTlist
Definition primnodes.h:2417
Node * onConflictWhere
Definition primnodes.h:2415
List * qual
Definition plannodes.h:237
#define RESTRICT_RELKIND_FOREIGN_TABLE
Definition tcopprot.h:45
#define FirstNormalObjectId
Definition transam.h:197
bool contain_vars_returning_old_or_new(Node *node)
Definition var.c:511

References OnConflictExpr::action, ModifyTable::arbiterIndexes, Assert, FdwRoutine::BeginDirectModify, bms_add_member(), ModifyTable::canSetTag, CMD_MERGE, CMD_UPDATE, contain_vars_returning_old_or_new(), FdwRoutine::EndDirectModify, ModifyTable::epqParam, ereport, errcode(), errdetail_relkind_not_supported(), errmsg, ERROR, OnConflictExpr::exclRelIndex, ModifyTable::exclRelRTI, ModifyTable::exclRelTlist, OnConflictExpr::exclRelTlist, extract_update_targetlist_colnos(), fb(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, FirstNormalObjectId, ModifyTable::forPortionOf, get_rel_name(), GetFdwRoutineByRelId(), has_row_triggers(), has_stored_generated_columns(), has_transition_tables(), i, infer_arbiter_indexes(), FdwRoutine::IterateDirectModify, lappend(), LCS_NONE, Plan::lefttree, lfirst_int, list_length(), OnConflictExpr::lockStrength, makeNode, ModifyTable::mergeActionLists, ModifyTable::mergeJoinConditions, NIL, ModifyTable::nominalRelation, ONCONFLICT_NONE, ModifyTable::onConflictAction, ModifyTable::onConflictCols, ModifyTable::onConflictLockStrength, ModifyTable::onConflictSet, OnConflictExpr::onConflictSet, ModifyTable::onConflictWhere, OnConflictExpr::onConflictWhere, operation, ModifyTable::operation, ModifyTable::plan, FdwRoutine::PlanDirectModify, FdwRoutine::PlanForeignModify, planner_rt_fetch, Plan::qual, restrict_nonsystem_relation_kind, RESTRICT_RELKIND_FOREIGN_TABLE, ModifyTable::resultRelations, ModifyTable::returningLists, ModifyTable::returningNewAlias, ModifyTable::returningOldAlias, Plan::righttree, root, ModifyTable::rootRelation, ModifyTable::rowMarks, RTE_RELATION, 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 5764 of file createplan.c.

5768{
5770 Plan *plan = &node->scan.plan;
5771
5772 /* cost should be inserted by caller */
5773 plan->targetlist = qptlist;
5774 plan->qual = qpqual;
5775 plan->lefttree = NULL;
5776 plan->righttree = NULL;
5777 node->scan.scanrelid = scanrelid;
5778 node->enrname = enrname;
5779
5780 return node;
5781}

References NamedTuplestoreScan::enrname, fb(), 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 5929 of file createplan.c.

5937{
5938 NestLoop *node = makeNode(NestLoop);
5939 Plan *plan = &node->join.plan;
5940
5941 plan->targetlist = tlist;
5942 plan->qual = otherclauses;
5943 plan->lefttree = lefttree;
5944 plan->righttree = righttree;
5945 node->join.jointype = jointype;
5946 node->join.inner_unique = inner_unique;
5947 node->join.joinqual = joinclauses;
5948 node->nestParams = nestParams;
5949
5950 return node;
5951}
List * nestParams
Definition plannodes.h:1010
Join join
Definition plannodes.h:1008

References fb(), Join::inner_unique, NestLoop::join, Join::joinqual, Join::jointype, makeNode, NestLoop::nestParams, plan, and Plan::righttree.

Referenced by create_nestloop_plan().

◆ make_one_row_result()

static Result * make_one_row_result ( List tlist,
Node resconstantqual,
RelOptInfo rel 
)
static

Definition at line 6962 of file createplan.c.

6965{
6966 Result *node = makeNode(Result);
6967 Plan *plan = &node->plan;
6968
6969 plan->targetlist = tlist;
6970 plan->qual = NIL;
6971 plan->lefttree = NULL;
6972 plan->righttree = NULL;
6975 node->resconstantqual = resconstantqual;
6976 node->relids = rel->relids;
6977
6978 return node;
6979}
#define IS_UPPER_REL(rel)
Definition pathnodes.h:999
@ RESULT_TYPE_UPPER
Definition plannodes.h:280
@ RESULT_TYPE_SCAN
Definition plannodes.h:278
@ RESULT_TYPE_JOIN
Definition plannodes.h:279

References fb(), IS_JOIN_REL, IS_UPPER_REL, makeNode, NIL, Result::plan, plan, RelOptInfo::relids, Result::relids, Result::resconstantqual, Result::result_type, RESULT_TYPE_JOIN, RESULT_TYPE_SCAN, RESULT_TYPE_UPPER, and Plan::targetlist.

Referenced by create_append_plan(), create_group_result_plan(), create_minmaxagg_plan(), and create_resultscan_plan().

◆ make_project_set()

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

Definition at line 6986 of file createplan.c.

6988{
6990 Plan *plan = &node->plan;
6991
6992 plan->targetlist = tlist;
6993 plan->qual = NIL;
6994 plan->lefttree = subplan;
6995 plan->righttree = NULL;
6996
6997 return node;
6998}

References fb(), makeNode, NIL, ProjectSet::plan, plan, Plan::righttree, and Plan::targetlist.

Referenced by create_project_set_plan().

◆ make_recursive_union()

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

Definition at line 5843 of file createplan.c.

5849{
5851 Plan *plan = &node->plan;
5852 int numCols = list_length(distinctList);
5853
5854 plan->targetlist = tlist;
5855 plan->qual = NIL;
5856 plan->lefttree = lefttree;
5857 plan->righttree = righttree;
5858 node->wtParam = wtParam;
5859
5860 /*
5861 * convert SortGroupClause list into arrays of attr indexes and equality
5862 * operators, as wanted by executor
5863 */
5864 node->numCols = numCols;
5865 if (numCols > 0)
5866 {
5867 int keyno = 0;
5872
5873 dupColIdx = palloc_array(AttrNumber, numCols);
5874 dupOperators = palloc_array(Oid, numCols);
5875 dupCollations = palloc_array(Oid, numCols);
5876
5877 foreach(slitem, distinctList)
5878 {
5881 plan->targetlist);
5882
5883 dupColIdx[keyno] = tle->resno;
5884 dupOperators[keyno] = sortcl->eqop;
5885 dupCollations[keyno] = exprCollation((Node *) tle->expr);
5887 keyno++;
5888 }
5889 node->dupColIdx = dupColIdx;
5890 node->dupOperators = dupOperators;
5891 node->dupCollations = dupCollations;
5892 }
5893 node->numGroups = numGroups;
5894
5895 return node;
5896}
Cardinality numGroups
Definition plannodes.h:499

References Assert, exprCollation(), fb(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, RecursiveUnion::numCols, RecursiveUnion::numGroups, OidIsValid, palloc_array, RecursiveUnion::plan, plan, Plan::righttree, and RecursiveUnion::wtParam.

Referenced by create_recursiveunion_plan().

◆ make_samplescan()

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

Definition at line 5506 of file createplan.c.

5510{
5512 Plan *plan = &node->scan.plan;
5513
5514 plan->targetlist = qptlist;
5515 plan->qual = qpqual;
5516 plan->lefttree = NULL;
5517 plan->righttree = NULL;
5518 node->scan.scanrelid = scanrelid;
5519 node->tablesample = tsc;
5520
5521 return node;
5522}
struct TableSampleClause * tablesample
Definition plannodes.h:564

References fb(), 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 5489 of file createplan.c.

5492{
5493 SeqScan *node = makeNode(SeqScan);
5494 Plan *plan = &node->scan.plan;
5495
5496 plan->targetlist = qptlist;
5497 plan->qual = qpqual;
5498 plan->lefttree = NULL;
5499 plan->righttree = NULL;
5500 node->scan.scanrelid = scanrelid;
5501
5502 return node;
5503}
Scan scan
Definition plannodes.h:553

References fb(), makeNode, plan, SeqScan::scan, and Scan::scanrelid.

Referenced by create_seqscan_plan().

◆ make_setop()

static SetOp * make_setop ( SetOpCmd  cmd,
SetOpStrategy  strategy,
List tlist,
Plan lefttree,
Plan righttree,
List groupList,
Cardinality  numGroups 
)
static

Definition at line 6820 of file createplan.c.

6823{
6824 SetOp *node = makeNode(SetOp);
6825 Plan *plan = &node->plan;
6826 int numCols = list_length(groupList);
6827 int keyno = 0;
6831 bool *cmpNullsFirst;
6833
6834 plan->targetlist = tlist;
6835 plan->qual = NIL;
6836 plan->lefttree = lefttree;
6837 plan->righttree = righttree;
6838
6839 /*
6840 * convert SortGroupClause list into arrays of attr indexes and comparison
6841 * operators, as wanted by executor
6842 */
6843 cmpColIdx = palloc_array(AttrNumber, numCols);
6844 cmpOperators = palloc_array(Oid, numCols);
6845 cmpCollations = palloc_array(Oid, numCols);
6846 cmpNullsFirst = palloc_array(bool, numCols);
6847
6848 foreach(slitem, groupList)
6849 {
6852
6853 cmpColIdx[keyno] = tle->resno;
6854 if (strategy == SETOP_HASHED)
6855 cmpOperators[keyno] = sortcl->eqop;
6856 else
6857 cmpOperators[keyno] = sortcl->sortop;
6859 cmpCollations[keyno] = exprCollation((Node *) tle->expr);
6860 cmpNullsFirst[keyno] = sortcl->nulls_first;
6861 keyno++;
6862 }
6863
6864 node->cmd = cmd;
6865 node->strategy = strategy;
6866 node->numCols = numCols;
6867 node->cmpColIdx = cmpColIdx;
6868 node->cmpOperators = cmpOperators;
6869 node->cmpCollations = cmpCollations;
6870 node->cmpNullsFirst = cmpNullsFirst;
6871 node->numGroups = numGroups;
6872
6873 return node;
6874}
@ SETOP_HASHED
Definition nodes.h:417
SetOpStrategy strategy
Definition plannodes.h:1454
SetOpCmd cmd
Definition plannodes.h:1451
int numCols
Definition plannodes.h:1457
Plan plan
Definition plannodes.h:1448
Cardinality numGroups
Definition plannodes.h:1470

References Assert, SetOp::cmd, exprCollation(), fb(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, SetOp::numCols, SetOp::numGroups, OidIsValid, palloc_array, SetOp::plan, plan, Plan::righttree, SETOP_HASHED, and SetOp::strategy.

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

6052{
6053 Sort *node;
6054 Plan *plan;
6055
6056 node = makeNode(Sort);
6057
6058 plan = &node->plan;
6059 plan->targetlist = lefttree->targetlist;
6060 plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
6061 plan->qual = NIL;
6062 plan->lefttree = lefttree;
6063 plan->righttree = NULL;
6064 node->numCols = numCols;
6065 node->sortColIdx = sortColIdx;
6066 node->sortOperators = sortOperators;
6067 node->collations = collations;
6068 node->nullsFirst = nullsFirst;
6069
6070 return node;
6071}
bool enable_sort
Definition costsize.c:151

References Plan::disabled_nodes, enable_sort, fb(), makeNode, NIL, Sort::numCols, Sort::plan, plan, Plan::righttree, 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 6446 of file createplan.c.

6449{
6450 List *sub_tlist = lefttree->targetlist;
6451 ListCell *l;
6452 int numsortkeys;
6453 AttrNumber *sortColIdx;
6454 Oid *sortOperators;
6455 Oid *collations;
6456 bool *nullsFirst;
6457
6458 /* Convert list-ish representation to arrays wanted by executor */
6460 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6461 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6462 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6463 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6464
6465 numsortkeys = 0;
6466 foreach(l, groupcls)
6467 {
6470
6471 if (!tle)
6472 elog(ERROR, "could not retrieve tle for sort-from-groupcols");
6473
6474 sortColIdx[numsortkeys] = tle->resno;
6475 sortOperators[numsortkeys] = grpcl->sortop;
6476 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6477 nullsFirst[numsortkeys] = grpcl->nulls_first;
6478 numsortkeys++;
6479 }
6480
6481 return make_sort(lefttree, numsortkeys,
6482 sortColIdx, sortOperators,
6483 collations, nullsFirst);
6484}
TargetEntry * get_tle_by_resno(List *tlist, AttrNumber resno)

References elog, ERROR, exprCollation(), fb(), get_tle_by_resno(), lfirst, list_length(), make_sort(), palloc(), 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 6328 of file createplan.c.

6329{
6330 int numsortkeys;
6331 AttrNumber *sortColIdx;
6332 Oid *sortOperators;
6333 Oid *collations;
6334 bool *nullsFirst;
6335
6336 /* Compute sort column info, and adjust lefttree as needed */
6337 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6338 relids,
6339 NULL,
6340 false,
6341 &numsortkeys,
6342 &sortColIdx,
6343 &sortOperators,
6344 &collations,
6345 &nullsFirst);
6346
6347 /* Now build the Sort node */
6348 return make_sort(lefttree, numsortkeys,
6349 sortColIdx, sortOperators,
6350 collations, nullsFirst);
6351}

References fb(), 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 6397 of file createplan.c.

6398{
6399 List *sub_tlist = lefttree->targetlist;
6400 ListCell *l;
6401 int numsortkeys;
6402 AttrNumber *sortColIdx;
6403 Oid *sortOperators;
6404 Oid *collations;
6405 bool *nullsFirst;
6406
6407 /* Convert list-ish representation to arrays wanted by executor */
6409 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6410 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6411 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6412 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6413
6414 numsortkeys = 0;
6415 foreach(l, sortcls)
6416 {
6419
6420 sortColIdx[numsortkeys] = tle->resno;
6421 sortOperators[numsortkeys] = sortcl->sortop;
6422 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6423 nullsFirst[numsortkeys] = sortcl->nulls_first;
6424 numsortkeys++;
6425 }
6426
6427 return make_sort(lefttree, numsortkeys,
6428 sortColIdx, sortOperators,
6429 collations, nullsFirst);
6430}

References exprCollation(), fb(), get_sortgroupclause_tle(), lfirst, list_length(), make_sort(), palloc(), and Plan::targetlist.

◆ make_subqueryscan()

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

Definition at line 5664 of file createplan.c.

5668{
5670 Plan *plan = &node->scan.plan;
5671
5672 plan->targetlist = qptlist;
5673 plan->qual = qpqual;
5674 plan->lefttree = NULL;
5675 plan->righttree = NULL;
5676 node->scan.scanrelid = scanrelid;
5677 node->subplan = subplan;
5679
5680 return node;
5681}
@ SUBQUERY_SCAN_UNKNOWN
Definition plannodes.h:768
SubqueryScanStatus scanstatus
Definition plannodes.h:777
Plan * subplan
Definition plannodes.h:776

References fb(), 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 5705 of file createplan.c.

5709{
5711 Plan *plan = &node->scan.plan;
5712
5713 plan->targetlist = qptlist;
5714 plan->qual = qpqual;
5715 plan->lefttree = NULL;
5716 plan->righttree = NULL;
5717 node->scan.scanrelid = scanrelid;
5718 node->tablefunc = tablefunc;
5719
5720 return node;
5721}
TableFunc * tablefunc
Definition plannodes.h:812

References fb(), 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 5645 of file createplan.c.

5649{
5651 Plan *plan = &node->scan.plan;
5652
5653 plan->targetlist = qptlist;
5654 plan->qual = qpqual;
5655 plan->lefttree = NULL;
5656 plan->righttree = NULL;
5657 node->scan.scanrelid = scanrelid;
5658 node->tidrangequals = tidrangequals;
5659
5660 return node;
5661}
List * tidrangequals
Definition plannodes.h:743

References fb(), 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 5626 of file createplan.c.

5630{
5631 TidScan *node = makeNode(TidScan);
5632 Plan *plan = &node->scan.plan;
5633
5634 plan->targetlist = qptlist;
5635 plan->qual = qpqual;
5636 plan->lefttree = NULL;
5637 plan->righttree = NULL;
5638 node->scan.scanrelid = scanrelid;
5639 node->tidquals = tidquals;
5640
5641 return node;
5642}
Scan scan
Definition plannodes.h:727
List * tidquals
Definition plannodes.h:729

References fb(), 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,
Relids  relids 
)
static

Definition at line 6684 of file createplan.c.

6686{
6687 Unique *node = makeNode(Unique);
6688 Plan *plan = &node->plan;
6689 int keyno = 0;
6693 ListCell *lc;
6694
6695 plan->targetlist = lefttree->targetlist;
6696 plan->qual = NIL;
6697 plan->lefttree = lefttree;
6698 plan->righttree = NULL;
6699
6700 /*
6701 * Convert pathkeys list into arrays of attr indexes and equality
6702 * operators, as wanted by executor. This has a lot in common with
6703 * prepare_sort_from_pathkeys ... maybe unify sometime?
6704 */
6705 Assert(numCols >= 0 && numCols <= list_length(pathkeys));
6707 uniqOperators = palloc_array(Oid, numCols);
6708 uniqCollations = palloc_array(Oid, numCols);
6709
6710 foreach(lc, pathkeys)
6711 {
6713 EquivalenceClass *ec = pathkey->pk_eclass;
6715 TargetEntry *tle = NULL;
6717 Oid eqop;
6718 ListCell *j;
6719
6720 /* Ignore pathkeys beyond the specified number of columns */
6721 if (keyno >= numCols)
6722 break;
6723
6724 if (ec->ec_has_volatile)
6725 {
6726 /*
6727 * If the pathkey's EquivalenceClass is volatile, then it must
6728 * have come from an ORDER BY clause, and we have to match it to
6729 * that same targetlist entry.
6730 */
6731 if (ec->ec_sortref == 0) /* can't happen */
6732 elog(ERROR, "volatile EquivalenceClass has no sortref");
6733 tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
6734 Assert(tle);
6735 Assert(list_length(ec->ec_members) == 1);
6736 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6737 }
6738 else
6739 {
6740 /*
6741 * Otherwise, we can use any non-constant expression listed in the
6742 * pathkey's EquivalenceClass. For now, we take the first tlist
6743 * item found in the EC.
6744 */
6745 foreach(j, plan->targetlist)
6746 {
6747 tle = (TargetEntry *) lfirst(j);
6748 em = find_ec_member_matching_expr(ec, tle->expr, relids);
6749 if (em)
6750 {
6751 /* found expr already in tlist */
6752 pk_datatype = em->em_datatype;
6753 break;
6754 }
6755 tle = NULL;
6756 }
6757 }
6758
6759 if (!tle)
6760 elog(ERROR, "could not find pathkey item to sort");
6761
6762 /*
6763 * Look up the correct equality operator from the PathKey's slightly
6764 * abstracted representation.
6765 */
6766 eqop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
6769 COMPARE_EQ);
6770 if (!OidIsValid(eqop)) /* should not happen */
6771 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6773 pathkey->pk_opfamily);
6774
6775 uniqColIdx[keyno] = tle->resno;
6776 uniqOperators[keyno] = eqop;
6777 uniqCollations[keyno] = ec->ec_collation;
6778
6779 keyno++;
6780 }
6781
6782 node->numCols = numCols;
6783 node->uniqColIdx = uniqColIdx;
6784 node->uniqOperators = uniqOperators;
6785 node->uniqCollations = uniqCollations;
6786
6787 return node;
6788}
@ COMPARE_EQ
Definition cmptype.h:36
EquivalenceMember * find_ec_member_matching_expr(EquivalenceClass *ec, Expr *expr, Relids relids)
Definition equivclass.c:916
int j
Definition isn.c:78
Plan plan
Definition plannodes.h:1330
int numCols
Definition plannodes.h:1333
TargetEntry * get_sortgroupref_tle(Index sortref, List *targetList)
Definition tlist.c:354

References Assert, COMPARE_EQ, EquivalenceClass::ec_collation, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_sortref, elog, ERROR, fb(), find_ec_member_matching_expr(), get_opfamily_member_for_cmptype(), get_sortgroupref_tle(), InvalidOid, j, lfirst, linitial, list_length(), makeNode, NIL, Unique::numCols, OidIsValid, palloc_array, Unique::plan, plan, Plan::righttree, 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 5724 of file createplan.c.

5728{
5730 Plan *plan = &node->scan.plan;
5731
5732 plan->targetlist = qptlist;
5733 plan->qual = qpqual;
5734 plan->lefttree = NULL;
5735 plan->righttree = NULL;
5736 node->scan.scanrelid = scanrelid;
5737 node->values_lists = values_lists;
5738
5739 return node;
5740}
List * values_lists
Definition plannodes.h:801

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

Referenced by create_valuesscan_plan().

◆ make_windowagg()

static WindowAgg * make_windowagg ( List tlist,
WindowClause wc,
int  partNumCols,
AttrNumber partColIdx,
Oid partOperators,
Oid partCollations,
int  ordNumCols,
AttrNumber ordColIdx,
Oid ordOperators,
Oid ordCollations,
List runCondition,
List qual,
bool  topWindow,
Plan lefttree 
)
static

Definition at line 6613 of file createplan.c.

6617{
6618 WindowAgg *node = makeNode(WindowAgg);
6619 Plan *plan = &node->plan;
6620
6621 node->winname = wc->name;
6622 node->winref = wc->winref;
6623 node->partNumCols = partNumCols;
6624 node->partColIdx = partColIdx;
6625 node->partOperators = partOperators;
6626 node->partCollations = partCollations;
6627 node->ordNumCols = ordNumCols;
6628 node->ordColIdx = ordColIdx;
6629 node->ordOperators = ordOperators;
6630 node->ordCollations = ordCollations;
6631 node->frameOptions = wc->frameOptions;
6632 node->startOffset = wc->startOffset;
6633 node->endOffset = wc->endOffset;
6634 node->runCondition = runCondition;
6635 /* a duplicate of the above for EXPLAIN */
6636 node->runConditionOrig = runCondition;
6637 node->startInRangeFunc = wc->startInRangeFunc;
6638 node->endInRangeFunc = wc->endInRangeFunc;
6639 node->inRangeColl = wc->inRangeColl;
6640 node->inRangeAsc = wc->inRangeAsc;
6641 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6642 node->topWindow = topWindow;
6643
6644 plan->targetlist = tlist;
6645 plan->lefttree = lefttree;
6646 plan->righttree = NULL;
6647 plan->qual = qual;
6648
6649 return node;
6650}
char * winname
Definition plannodes.h:1256
int partNumCols
Definition plannodes.h:1262
Oid endInRangeFunc
Definition plannodes.h:1306
Node * endOffset
Definition plannodes.h:1292
bool topWindow
Definition plannodes.h:1321
List * runConditionOrig
Definition plannodes.h:1298
Oid inRangeColl
Definition plannodes.h:1309
Node * startOffset
Definition plannodes.h:1289
List * runCondition
Definition plannodes.h:1295
Oid startInRangeFunc
Definition plannodes.h:1303
bool inRangeAsc
Definition plannodes.h:1312
Index winref
Definition plannodes.h:1259
bool inRangeNullsFirst
Definition plannodes.h:1315
int ordNumCols
Definition plannodes.h:1274
int frameOptions
Definition plannodes.h:1286
Node * startOffset
Node * endOffset

References WindowAgg::endInRangeFunc, WindowClause::endOffset, WindowAgg::endOffset, fb(), WindowClause::frameOptions, WindowAgg::frameOptions, WindowAgg::inRangeAsc, WindowAgg::inRangeColl, WindowAgg::inRangeNullsFirst, makeNode, WindowAgg::ordNumCols, WindowAgg::partNumCols, WindowAgg::plan, plan, Plan::qual, Plan::righttree, WindowAgg::runCondition, WindowAgg::runConditionOrig, WindowAgg::startInRangeFunc, WindowClause::startOffset, WindowAgg::startOffset, WindowAgg::topWindow, WindowAgg::winname, WindowClause::winref, 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 5784 of file createplan.c.

5788{
5790 Plan *plan = &node->scan.plan;
5791
5792 plan->targetlist = qptlist;
5793 plan->qual = qpqual;
5794 plan->lefttree = NULL;
5795 plan->righttree = NULL;
5796 node->scan.scanrelid = scanrelid;
5797 node->wtParam = wtParam;
5798
5799 return node;
5800}

References fb(), 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 1132 of file createplan.c.

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

References Assert, fb(), IsA, FdwRoutine::IsForeignPathAsyncCapable, mark_async_capable_plan(), nodeTag, plan, subpath(), and trivial_subqueryscan().

Referenced by create_append_plan(), and mark_async_capable_plan().

◆ materialize_finished_plan()

Plan * materialize_finished_plan ( Plan subplan)

Definition at line 6509 of file createplan.c.

6510{
6511 Plan *matplan;
6512 Path matpath; /* dummy for cost_material */
6514 bool unsafe_initplans;
6515
6516 matplan = (Plan *) make_material(subplan);
6517
6518 /*
6519 * XXX horrid kluge: if there are any initPlans attached to the subplan,
6520 * move them up to the Material node, which is now effectively the top
6521 * plan node in its query level. This prevents failure in
6522 * SS_finalize_plan(), which see for comments.
6523 */
6524 matplan->initPlan = subplan->initPlan;
6525 subplan->initPlan = NIL;
6526
6527 /* Move the initplans' cost delta, as well */
6530 subplan->startup_cost -= initplan_cost;
6531 subplan->total_cost -= initplan_cost;
6532
6533 /* Set cost data */
6536 subplan->disabled_nodes,
6537 subplan->startup_cost,
6538 subplan->total_cost,
6539 subplan->plan_rows,
6540 subplan->plan_width);
6541 matplan->disabled_nodes = subplan->disabled_nodes;
6542 matplan->startup_cost = matpath.startup_cost + initplan_cost;
6543 matplan->total_cost = matpath.total_cost + initplan_cost;
6544 matplan->plan_rows = subplan->plan_rows;
6545 matplan->plan_width = subplan->plan_width;
6546 matplan->parallel_aware = false;
6547 matplan->parallel_safe = subplan->parallel_safe;
6548
6549 return matplan;
6550}
void cost_material(Path *path, bool enabled, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double tuples, int width)
Definition costsize.c:2583
bool enable_material
Definition costsize.c:155
double Cost
Definition nodes.h:261
List * initPlan
Definition plannodes.h:242
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition subselect.c:2493

References cost_material(), Plan::disabled_nodes, enable_material, fb(), Plan::initPlan, make_material(), NIL, Plan::parallel_safe, Plan::plan_rows, Plan::plan_width, SS_compute_initplan_cost(), Plan::startup_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 5266 of file createplan.c.

5267{
5268 typedef struct
5269 {
5270 Node *clause;
5271 Cost cost;
5272 Index security_level;
5273 } QualItem;
5274 int nitems = list_length(clauses);
5275 QualItem *items;
5276 ListCell *lc;
5277 int i;
5278 List *result;
5279
5280 /* No need to work hard for 0 or 1 clause */
5281 if (nitems <= 1)
5282 return clauses;
5283
5284 /*
5285 * Collect the items and costs into an array. This is to avoid repeated
5286 * cost_qual_eval work if the inputs aren't RestrictInfos.
5287 */
5288 items = (QualItem *) palloc(nitems * sizeof(QualItem));
5289 i = 0;
5290 foreach(lc, clauses)
5291 {
5292 Node *clause = (Node *) lfirst(lc);
5294
5295 cost_qual_eval_node(&qcost, clause, root);
5296 items[i].clause = clause;
5297 items[i].cost = qcost.per_tuple;
5298 if (IsA(clause, RestrictInfo))
5299 {
5300 RestrictInfo *rinfo = (RestrictInfo *) clause;
5301
5302 /*
5303 * If a clause is leakproof, it doesn't have to be constrained by
5304 * its nominal security level. If it's also reasonably cheap
5305 * (here defined as 10X cpu_operator_cost), pretend it has
5306 * security_level 0, which will allow it to go in front of
5307 * more-expensive quals of lower security levels. Of course, that
5308 * will also force it to go in front of cheaper quals of its own
5309 * security level, which is not so great, but we can alleviate
5310 * that risk by applying the cost limit cutoff.
5311 */
5312 if (rinfo->leakproof && items[i].cost < 10 * cpu_operator_cost)
5313 items[i].security_level = 0;
5314 else
5315 items[i].security_level = rinfo->security_level;
5316 }
5317 else
5318 items[i].security_level = 0;
5319 i++;
5320 }
5321
5322 /*
5323 * Sort. We don't use qsort() because it's not guaranteed stable for
5324 * equal keys. The expected number of entries is small enough that a
5325 * simple insertion sort should be good enough.
5326 */
5327 for (i = 1; i < nitems; i++)
5328 {
5329 QualItem newitem = items[i];
5330 int j;
5331
5332 /* insert newitem into the already-sorted subarray */
5333 for (j = i; j > 0; j--)
5334 {
5335 QualItem *olditem = &items[j - 1];
5336
5337 if (newitem.security_level > olditem->security_level ||
5338 (newitem.security_level == olditem->security_level &&
5339 newitem.cost >= olditem->cost))
5340 break;
5341 items[j] = *olditem;
5342 }
5343 items[j] = newitem;
5344 }
5345
5346 /* Convert back to a list */
5347 result = NIL;
5348 for (i = 0; i < nitems; i++)
5349 result = lappend(result, items[i].clause);
5350
5351 return result;
5352}
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition costsize.c:4926
#define nitems(x)
Definition indent.h:31
Index security_level
Definition pathnodes.h:2923
static ItemArray items

References cost_qual_eval_node(), cpu_operator_cost, fb(), i, IsA, items, j, lappend(), lfirst, list_length(), NIL, nitems, palloc(), result, 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 6146 of file createplan.c.

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

References Assert, copyObject, EquivalenceClass::ec_collation, EquivalenceClass::ec_has_volatile, EquivalenceClass::ec_members, EquivalenceClass::ec_sortref, elog, ERROR, fb(), find_computable_ec_member(), find_ec_member_matching_expr(), get_opfamily_member_for_cmptype(), 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, 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 2202 of file createplan.c.

2203{
2204 AttrNumber *grouping_map = root->grouping_map;
2206 ListCell *lc;
2207 int i;
2208
2210
2212
2213 i = 0;
2214 foreach(lc, groupClause)
2215 {
2216 SortGroupClause *clause = lfirst(lc);
2217
2219 }
2220
2221 return new_grpColIdx;
2222}
#define palloc0_array(type, count)
Definition fe_memutils.h:77

References Assert, fb(), i, lfirst, list_length(), palloc0_array, 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 4889 of file createplan.c.

4890{
4891 if (node == NULL)
4892 return NULL;
4893 if (IsA(node, Var))
4894 {
4895 Var *var = (Var *) node;
4896
4897 /* Upper-level Vars should be long gone at this point */
4898 Assert(var->varlevelsup == 0);
4899 /* If not to be replaced, we can just return the Var unmodified */
4900 if (IS_SPECIAL_VARNO(var->varno) ||
4901 !bms_is_member(var->varno, root->curOuterRels))
4902 return node;
4903 /* Replace the Var with a nestloop Param */
4904 return (Node *) replace_nestloop_param_var(root, var);
4905 }
4906 if (IsA(node, PlaceHolderVar))
4907 {
4908 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4909
4910 /* Upper-level PlaceHolderVars should be long gone at this point */
4911 Assert(phv->phlevelsup == 0);
4912
4913 /* Check whether we need to replace the PHV */
4914 if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
4915 root->curOuterRels))
4916 {
4917 /*
4918 * We can't replace the whole PHV, but we might still need to
4919 * replace Vars or PHVs within its expression, in case it ends up
4920 * actually getting evaluated here. (It might get evaluated in
4921 * this plan node, or some child node; in the latter case we don't
4922 * really need to process the expression here, but we haven't got
4923 * enough info to tell if that's the case.) Flat-copy the PHV
4924 * node and then recurse on its expression.
4925 *
4926 * Note that after doing this, we might have different
4927 * representations of the contents of the same PHV in different
4928 * parts of the plan tree. This is OK because equal() will just
4929 * match on phid/phlevelsup, so setrefs.c will still recognize an
4930 * upper-level reference to a lower-level copy of the same PHV.
4931 */
4933
4934 memcpy(newphv, phv, sizeof(PlaceHolderVar));
4935 newphv->phexpr = (Expr *)
4937 root);
4938 return (Node *) newphv;
4939 }
4940 /* Replace the PlaceHolderVar with a nestloop Param */
4942 }
4944}
memcpy(sums, checksumBaseOffsets, sizeof(checksumBaseOffsets))
#define expression_tree_mutator(n, m, c)
Definition nodeFuncs.h:155
Param * replace_nestloop_param_placeholdervar(PlannerInfo *root, PlaceHolderVar *phv)
Param * replace_nestloop_param_var(PlannerInfo *root, Var *var)
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv)
Definition placeholder.c:85
#define IS_SPECIAL_VARNO(varno)
Definition primnodes.h:248
Index varlevelsup
Definition primnodes.h:295

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

Referenced by replace_nestloop_params(), and replace_nestloop_params_mutator().

◆ use_physical_tlist()

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

Definition at line 857 of file createplan.c.

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

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, fb(), FirstLowInvalidHeapAttributeNumber, i, IsA, lfirst, RelOptInfo::min_attr, IndexOptInfo::ncolumns, NIL, Path::pathtype, 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().