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, Relids ojrelids, 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, Relids ojrelids, 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, Relids ojrelids, 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 5486 of file createplan.c.

5487{
5488 if (IsA(plan, BitmapAnd))
5490 else if (IsA(plan, BitmapOr))
5491 {
5492 ((BitmapOr *) plan)->isshared = true;
5493 bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5494 }
5495 else if (IsA(plan, BitmapIndexScan))
5496 ((BitmapIndexScan *) plan)->isshared = true;
5497 else
5498 elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5499}
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:162
#define nodeTag(nodeptr)
Definition nodes.h:137
#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 823 of file createplan.c.

824{
825 List *tlist = NIL;
826 Index *sortgrouprefs = path->pathtarget->sortgrouprefs;
827 int resno = 1;
828 ListCell *v;
829
830 foreach(v, path->pathtarget->exprs)
831 {
832 Node *node = (Node *) lfirst(v);
834
835 /*
836 * If it's a parameterized path, there might be lateral references in
837 * the tlist, which need to be replaced with Params. There's no need
838 * to remake the TargetEntry nodes, so apply this to each list item
839 * separately.
840 */
841 if (path->param_info)
842 node = replace_nestloop_params(root, node);
843
844 tle = makeTargetEntry((Expr *) node,
845 resno,
846 NULL,
847 false);
848 if (sortgrouprefs)
849 tle->ressortgroupref = sortgrouprefs[resno - 1];
850
851 tlist = lappend(tlist, tle);
852 resno++;
853 }
854 return tlist;
855}
unsigned int Index
Definition c.h:757
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:133

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

1999{
2000 /*
2001 * If the top plan node can't do projections and its existing target list
2002 * isn't already what we need, we need to add a Result node to help it
2003 * along.
2004 */
2005 if (!is_projection_capable_plan(subplan) &&
2006 !tlist_same_exprs(tlist, subplan->targetlist))
2007 subplan = inject_projection_plan(subplan, tlist,
2008 subplan->parallel_safe &&
2010 else
2011 {
2012 /* Else we can just replace the plan node's tlist */
2013 subplan->targetlist = tlist;
2015 }
2016 return subplan;
2017}
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 5387 of file createplan.c.

5388{
5389 dest->disabled_nodes = src->disabled_nodes;
5390 dest->startup_cost = src->startup_cost;
5391 dest->total_cost = src->total_cost;
5392 dest->plan_rows = src->rows;
5393 dest->plan_width = src->pathtarget->width;
5394 dest->parallel_aware = src->parallel_aware;
5395 dest->parallel_safe = src->parallel_safe;
5396}
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 5403 of file createplan.c.

5404{
5405 dest->disabled_nodes = src->disabled_nodes;
5406 dest->startup_cost = src->startup_cost;
5407 dest->total_cost = src->total_cost;
5408 dest->plan_rows = src->plan_rows;
5409 dest->plan_width = src->plan_width;
5410 /* Assume the inserted node is not parallel-aware. */
5411 dest->parallel_aware = false;
5412 /* Assume the inserted node is parallel-safe, if child plan is. */
5413 dest->parallel_safe = src->parallel_safe;
5414}
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 2162 of file createplan.c.

2163{
2164 Agg *plan;
2165 Plan *subplan;
2166 List *tlist;
2167 List *quals;
2168
2169 /*
2170 * Agg can project, so no need to be terribly picky about child tlist, but
2171 * we do need grouping columns to be available
2172 */
2173 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2174
2175 tlist = build_path_tlist(root, &best_path->path);
2176
2177 quals = order_qual_clauses(root, best_path->qual);
2178
2179 plan = make_agg(tlist, quals,
2180 best_path->aggstrategy,
2181 best_path->aggsplit,
2182 list_length(best_path->groupClause),
2183 extract_grouping_cols(best_path->groupClause,
2184 subplan->targetlist),
2185 extract_grouping_ops(best_path->groupClause),
2187 subplan->targetlist),
2188 NIL,
2189 NIL,
2190 best_path->numGroups,
2191 best_path->transitionSpace,
2192 subplan);
2193
2195
2196 return plan;
2197}
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:396
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition createplan.c:823
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 1214 of file createplan.c.

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

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

3178{
3179 Plan *plan;
3180
3181 if (IsA(bitmapqual, BitmapAndPath))
3182 {
3183 BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
3184 List *subplans = NIL;
3185 List *subquals = NIL;
3187 List *subindexECs = NIL;
3188 ListCell *l;
3189
3190 /*
3191 * There may well be redundant quals among the subplans, since a
3192 * top-level WHERE qual might have gotten used to form several
3193 * different index quals. We don't try exceedingly hard to eliminate
3194 * redundancies, but we do eliminate obvious duplicates by using
3195 * list_concat_unique.
3196 */
3197 foreach(l, apath->bitmapquals)
3198 {
3199 Plan *subplan;
3200 List *subqual;
3203
3204 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3206 &subindexEC);
3207 subplans = lappend(subplans, subplan);
3210 /* Duplicates in indexECs aren't worth getting rid of */
3212 }
3213 plan = (Plan *) make_bitmap_and(subplans);
3214 plan->startup_cost = apath->path.startup_cost;
3215 plan->total_cost = apath->path.total_cost;
3216 plan->plan_rows =
3217 clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
3218 plan->plan_width = 0; /* meaningless */
3219 plan->parallel_aware = false;
3220 plan->parallel_safe = apath->path.parallel_safe;
3221 *qual = subquals;
3222 *indexqual = subindexquals;
3224 }
3225 else if (IsA(bitmapqual, BitmapOrPath))
3226 {
3227 BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
3228 List *subplans = NIL;
3229 List *subquals = NIL;
3231 bool const_true_subqual = false;
3232 bool const_true_subindexqual = false;
3233 ListCell *l;
3234
3235 /*
3236 * Here, we only detect qual-free subplans. A qual-free subplan would
3237 * cause us to generate "... OR true ..." which we may as well reduce
3238 * to just "true". We do not try to eliminate redundant subclauses
3239 * because (a) it's not as likely as in the AND case, and (b) we might
3240 * well be working with hundreds or even thousands of OR conditions,
3241 * perhaps from a long IN list. The performance of list_append_unique
3242 * would be unacceptable.
3243 */
3244 foreach(l, opath->bitmapquals)
3245 {
3246 Plan *subplan;
3247 List *subqual;
3250
3251 subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
3253 &subindexEC);
3254 subplans = lappend(subplans, subplan);
3255 if (subqual == NIL)
3256 const_true_subqual = true;
3257 else if (!const_true_subqual)
3260 if (subindexqual == NIL)
3262 else if (!const_true_subindexqual)
3265 }
3266
3267 /*
3268 * In the presence of ScalarArrayOpExpr quals, we might have built
3269 * BitmapOrPaths with just one subpath; don't add an OR step.
3270 */
3271 if (list_length(subplans) == 1)
3272 {
3273 plan = (Plan *) linitial(subplans);
3274 }
3275 else
3276 {
3277 plan = (Plan *) make_bitmap_or(subplans);
3278 plan->startup_cost = opath->path.startup_cost;
3279 plan->total_cost = opath->path.total_cost;
3280 plan->plan_rows =
3281 clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
3282 plan->plan_width = 0; /* meaningless */
3283 plan->parallel_aware = false;
3284 plan->parallel_safe = opath->path.parallel_safe;
3285 }
3286
3287 /*
3288 * If there were constant-TRUE subquals, the OR reduces to constant
3289 * TRUE. Also, avoid generating one-element ORs, which could happen
3290 * due to redundancy elimination or ScalarArrayOpExpr quals.
3291 */
3293 *qual = NIL;
3294 else if (list_length(subquals) <= 1)
3295 *qual = subquals;
3296 else
3299 *indexqual = NIL;
3300 else if (list_length(subindexquals) <= 1)
3301 *indexqual = subindexquals;
3302 else
3303 *indexqual = list_make1(make_orclause(subindexquals));
3304 *indexECs = NIL;
3305 }
3306 else if (IsA(bitmapqual, IndexPath))
3307 {
3308 IndexPath *ipath = (IndexPath *) bitmapqual;
3309 IndexScan *iscan;
3310 List *subquals;
3313 ListCell *l;
3314
3315 /* Use the regular indexscan plan build machinery... */
3316 iscan = castNode(IndexScan,
3318 NIL, NIL, false));
3319 /* then convert to a bitmap indexscan */
3321 iscan->indexid,
3322 iscan->indexqual,
3323 iscan->indexqualorig);
3324 /* and set its cost/width fields appropriately */
3325 plan->startup_cost = 0.0;
3326 plan->total_cost = ipath->indextotalcost;
3327 plan->plan_rows =
3328 clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
3329 plan->plan_width = 0; /* meaningless */
3330 plan->parallel_aware = false;
3331 plan->parallel_safe = ipath->path.parallel_safe;
3332 /* Extract original index clauses, actual index quals, relevant ECs */
3333 subquals = NIL;
3335 subindexECs = NIL;
3336 foreach(l, ipath->indexclauses)
3337 {
3339 RestrictInfo *rinfo = iclause->rinfo;
3340
3341 Assert(!rinfo->pseudoconstant);
3342 subquals = lappend(subquals, rinfo->clause);
3344 get_actual_clauses(iclause->indexquals));
3345 if (rinfo->parent_ec)
3346 subindexECs = lappend(subindexECs, rinfo->parent_ec);
3347 }
3348 /* We can add any index predicate conditions, too */
3349 foreach(l, ipath->indexinfo->indpred)
3350 {
3351 Expr *pred = (Expr *) lfirst(l);
3352
3353 /*
3354 * We know that the index predicate must have been implied by the
3355 * query condition as a whole, but it may or may not be implied by
3356 * the conditions that got pushed into the bitmapqual. Avoid
3357 * generating redundant conditions.
3358 */
3359 if (!predicate_implied_by(list_make1(pred), subquals, false))
3360 {
3361 subquals = lappend(subquals, pred);
3363 }
3364 }
3365 *qual = subquals;
3366 *indexqual = subindexquals;
3368 }
3369 else
3370 {
3371 elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
3372 plan = NULL; /* keep compiler quiet */
3373 }
3374
3375 return plan;
3376}
double clamp_row_est(double nrows)
Definition costsize.c:215
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:180
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 3735 of file createplan.c.

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

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

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

3607{
3609 Index scan_relid = best_path->parent->relid;
3611 List *functions;
3612
3613 /* it should be a function base rel... */
3614 Assert(scan_relid > 0);
3616 Assert(rte->rtekind == RTE_FUNCTION);
3617 functions = rte->functions;
3618
3619 /* Sort clauses into best execution order */
3621
3622 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3624
3625 /* Replace any outer-relation variables with nestloop params */
3626 if (best_path->param_info)
3627 {
3628 scan_clauses = (List *)
3630 /* The function expressions could contain nestloop params, too */
3632 }
3633
3635 functions, rte->funcordinality);
3636
3638
3639 return scan_plan;
3640}
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 1809 of file createplan.c.

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

1772{
1774 Plan *subplan;
1775 List *tlist;
1776
1777 /*
1778 * Push projection down to the child node. That way, the projection work
1779 * is parallelized, and there can be no system columns in the result (they
1780 * can't travel through a tuple queue because it uses MinimalTuple
1781 * representation).
1782 */
1783 subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1784
1785 tlist = build_path_tlist(root, &best_path->path);
1786
1787 gather_plan = make_gather(tlist,
1788 NIL,
1789 best_path->num_workers,
1791 best_path->single_copy,
1792 subplan);
1793
1795
1796 /* use parallel mode for parallel plans. */
1797 root->glob->parallelModeNeeded = true;
1798
1799 return gather_plan;
1800}
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 1020 of file createplan.c.

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

2088{
2089 Group *plan;
2090 Plan *subplan;
2091 List *tlist;
2092 List *quals;
2093
2094 /*
2095 * Group can project, so no need to be terribly picky about child tlist,
2096 * but we do need grouping columns to be available
2097 */
2098 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2099
2100 tlist = build_path_tlist(root, &best_path->path);
2101
2102 quals = order_qual_clauses(root, best_path->qual);
2103
2104 plan = make_group(tlist,
2105 quals,
2106 list_length(best_path->groupClause),
2107 extract_grouping_cols(best_path->groupClause,
2108 subplan->targetlist),
2109 extract_grouping_ops(best_path->groupClause),
2111 subplan->targetlist),
2112 subplan);
2113
2115
2116 return plan;
2117}
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 1638 of file createplan.c.

1639{
1640 Result *plan;
1641 List *tlist;
1642 List *quals;
1643
1644 tlist = build_path_tlist(root, &best_path->path);
1645
1646 /* best_path->quals is just bare clauses */
1647 quals = order_qual_clauses(root, best_path->quals);
1648
1649 plan = make_one_row_result(tlist, (Node *) quals, best_path->path.parent);
1650
1652
1653 return plan;
1654}

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

2247{
2248 Agg *plan;
2249 Plan *subplan;
2250 List *rollups = best_path->rollups;
2252 int maxref;
2253 List *chain;
2254 ListCell *lc;
2255
2256 /* Shouldn't get here without grouping sets */
2257 Assert(root->parse->groupingSets);
2258 Assert(rollups != NIL);
2259
2260 /*
2261 * Agg can project, so no need to be terribly picky about child tlist, but
2262 * we do need grouping columns to be available
2263 */
2264 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2265
2266 /*
2267 * Compute the mapping from tleSortGroupRef to column index in the child's
2268 * tlist. First, identify max SortGroupRef in groupClause, for array
2269 * sizing.
2270 */
2271 maxref = 0;
2272 foreach(lc, root->processed_groupClause)
2273 {
2275
2276 if (gc->tleSortGroupRef > maxref)
2278 }
2279
2280 grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
2281
2282 /* Now look up the column numbers in the child's tlist */
2283 foreach(lc, root->processed_groupClause)
2284 {
2287
2288 grouping_map[gc->tleSortGroupRef] = tle->resno;
2289 }
2290
2291 /*
2292 * During setrefs.c, we'll need the grouping_map to fix up the cols lists
2293 * in GroupingFunc nodes. Save it for setrefs.c to use.
2294 */
2295 Assert(root->grouping_map == NULL);
2296 root->grouping_map = grouping_map;
2297
2298 /*
2299 * Generate the side nodes that describe the other sort and group
2300 * operations besides the top one. Note that we don't worry about putting
2301 * accurate cost estimates in the side nodes; only the topmost Agg node's
2302 * costs will be shown by EXPLAIN.
2303 */
2304 chain = NIL;
2305 if (list_length(rollups) > 1)
2306 {
2307 bool is_first_sort = ((RollupData *) linitial(rollups))->is_hashed;
2308
2309 for_each_from(lc, rollups, 1)
2310 {
2313 Plan *sort_plan = NULL;
2314 Plan *agg_plan;
2316
2317 new_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2318
2319 if (!rollup->is_hashed && !is_first_sort)
2320 {
2321 sort_plan = (Plan *)
2322 make_sort_from_groupcols(rollup->groupClause,
2324 subplan);
2325 }
2326
2327 if (!rollup->is_hashed)
2328 is_first_sort = false;
2329
2330 if (rollup->is_hashed)
2331 strat = AGG_HASHED;
2332 else if (linitial(rollup->gsets) == NIL)
2333 strat = AGG_PLAIN;
2334 else
2335 strat = AGG_SORTED;
2336
2337 agg_plan = (Plan *) make_agg(NIL,
2338 NIL,
2339 strat,
2341 list_length((List *) linitial(rollup->gsets)),
2343 extract_grouping_ops(rollup->groupClause),
2344 extract_grouping_collations(rollup->groupClause, subplan->targetlist),
2345 rollup->gsets,
2346 NIL,
2347 rollup->numGroups,
2348 best_path->transitionSpace,
2349 sort_plan);
2350
2351 /*
2352 * Remove stuff we don't need to avoid bloating debug output.
2353 */
2354 if (sort_plan)
2355 {
2356 sort_plan->targetlist = NIL;
2357 sort_plan->lefttree = NULL;
2358 }
2359
2360 chain = lappend(chain, agg_plan);
2361 }
2362 }
2363
2364 /*
2365 * Now make the real Agg node
2366 */
2367 {
2368 RollupData *rollup = linitial(rollups);
2370 int numGroupCols;
2371
2372 top_grpColIdx = remap_groupColIdx(root, rollup->groupClause);
2373
2375
2377 best_path->qual,
2378 best_path->aggstrategy,
2382 extract_grouping_ops(rollup->groupClause),
2383 extract_grouping_collations(rollup->groupClause, subplan->targetlist),
2384 rollup->gsets,
2385 chain,
2386 rollup->numGroups,
2387 best_path->transitionSpace,
2388 subplan);
2389
2390 /* Copy cost data from Path to Plan */
2391 copy_generic_path_info(&plan->plan, &best_path->path);
2392 }
2393
2394 return (Plan *) plan;
2395}
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:1420
AggStrategy
Definition nodes.h:361
@ AGG_SORTED
Definition nodes.h:363
@ AGG_HASHED
Definition nodes.h:364
@ AGG_PLAIN
Definition nodes.h:362
@ AGGSPLIT_SIMPLE
Definition nodes.h:385
#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 4713 of file createplan.c.

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

References OpExpr::args, Assert, bms_difference(), bms_union(), 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 2060 of file createplan.c.

2062{
2064 Plan *subplan;
2065
2066 /* See comments in create_sort_plan() above */
2067 subplan = create_plan_recurse(root, best_path->spath.subpath,
2068 flags | CP_SMALL_TLIST);
2070 best_path->spath.path.pathkeys,
2071 IS_OTHER_REL(best_path->spath.subpath->parent) ?
2072 best_path->spath.path.parent->relids : NULL,
2073 best_path->nPresortedCols);
2074
2075 copy_generic_path_info(&plan->sort.plan, (Path *) best_path);
2076
2077 return plan;
2078}
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 2850 of file createplan.c.

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

1080{
1081 Plan *plan;
1083
1084 switch (best_path->path.pathtype)
1085 {
1086 case T_MergeJoin:
1088 (MergePath *) best_path);
1089 break;
1090 case T_HashJoin:
1092 (HashPath *) best_path);
1093 break;
1094 case T_NestLoop:
1096 (NestPath *) best_path);
1097 break;
1098 default:
1099 elog(ERROR, "unrecognized node type: %d",
1100 (int) best_path->path.pathtype);
1101 plan = NULL; /* keep compiler quiet */
1102 break;
1103 }
1104
1105 /*
1106 * If there are any pseudoconstant clauses attached to this node, insert a
1107 * gating Result node that evaluates the pseudoconstants as one-time
1108 * quals.
1109 */
1110 gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
1111 if (gating_clauses)
1114
1115#ifdef NOT_USED
1116
1117 /*
1118 * * Expensive function pullups may have pulled local predicates * into
1119 * this path node. Put them in the qpqual of the plan node. * JMH,
1120 * 6/15/92
1121 */
1126#endif
1127
1128 return plan;
1129}
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)
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 2700 of file createplan.c.

2701{
2702 Limit *plan;
2703 Plan *subplan;
2704 int numUniqkeys = 0;
2708
2709 /* Limit doesn't project, so tlist requirements pass through */
2710 subplan = create_plan_recurse(root, best_path->subpath, flags);
2711
2712 /* Extract information necessary for comparing rows for WITH TIES. */
2713 if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
2714 {
2715 Query *parse = root->parse;
2716 ListCell *l;
2717
2718 numUniqkeys = list_length(parse->sortClause);
2720 uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2721 uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2722
2723 numUniqkeys = 0;
2724 foreach(l, parse->sortClause)
2725 {
2728
2729 uniqColIdx[numUniqkeys] = tle->resno;
2732 numUniqkeys++;
2733 }
2734 }
2735
2736 plan = make_limit(subplan,
2737 best_path->limitOffset,
2738 best_path->limitCount,
2739 best_path->limitOption,
2741
2743
2744 return plan;
2745}
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:1390
Oid exprCollation(const Node *expr)
Definition nodeFuncs.c:826
@ LIMIT_OPTION_WITH_TIES
Definition nodes.h:441

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

2638{
2639 LockRows *plan;
2640 Plan *subplan;
2641
2642 /* LockRows doesn't project, so tlist requirements pass through */
2643 subplan = create_plan_recurse(root, best_path->subpath, flags);
2644
2645 plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2646
2648
2649 return plan;
2650}
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 1689 of file createplan.c.

1690{
1691 Material *plan;
1692 Plan *subplan;
1693
1694 /*
1695 * We don't want any excess columns in the materialized tuples, so request
1696 * a smaller tlist. Otherwise, since Material doesn't project, tlist
1697 * requirements pass through.
1698 */
1699 subplan = create_plan_recurse(root, best_path->subpath,
1700 flags | CP_SMALL_TLIST);
1701
1702 plan = make_material(subplan);
1703
1705
1706 return plan;
1707}
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 1717 of file createplan.c.

1718{
1719 Memoize *plan;
1720 Bitmapset *keyparamids;
1721 Plan *subplan;
1722 Oid *operators;
1723 Oid *collations;
1724 List *param_exprs = NIL;
1725 ListCell *lc;
1726 ListCell *lc2;
1727 int nkeys;
1728 int i;
1729
1730 subplan = create_plan_recurse(root, best_path->subpath,
1731 flags | CP_SMALL_TLIST);
1732
1733 param_exprs = (List *) replace_nestloop_params(root, (Node *)
1734 best_path->param_exprs);
1735
1736 nkeys = list_length(param_exprs);
1737 Assert(nkeys > 0);
1738 operators = palloc(nkeys * sizeof(Oid));
1739 collations = palloc(nkeys * sizeof(Oid));
1740
1741 i = 0;
1742 forboth(lc, param_exprs, lc2, best_path->hash_operators)
1743 {
1744 Expr *param_expr = (Expr *) lfirst(lc);
1745 Oid opno = lfirst_oid(lc2);
1746
1747 operators[i] = opno;
1748 collations[i] = exprCollation((Node *) param_expr);
1749 i++;
1750 }
1751
1752 keyparamids = pull_paramids((Expr *) param_exprs);
1753
1754 plan = make_memoize(subplan, operators, collations, param_exprs,
1755 best_path->singlerow, best_path->binary_mode,
1756 best_path->est_entries, keyparamids, best_path->est_calls,
1757 best_path->est_unique_keys, best_path->est_hit_ratio);
1758
1760
1761 return plan;
1762}
Bitmapset * pull_paramids(Expr *expr)
Definition clauses.c:6259
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 1461 of file createplan.c.

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

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

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

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

2660{
2662 Path *subpath = best_path->subpath;
2663 Plan *subplan;
2664
2665 /* Subplan must produce exactly the specified tlist */
2667
2668 /* Transfer resname/resjunk labeling, too, to keep executor happy */
2669 apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2670
2672 subplan,
2673 best_path->operation,
2674 best_path->canSetTag,
2675 best_path->nominalRelation,
2676 best_path->rootRelation,
2677 best_path->resultRelations,
2678 best_path->updateColnosLists,
2679 best_path->withCheckOptionLists,
2680 best_path->returningLists,
2681 best_path->rowMarks,
2682 best_path->onconflict,
2683 best_path->mergeActionLists,
2684 best_path->mergeJoinConditions,
2685 best_path->forPortionOf,
2686 best_path->epqParam);
2687
2688 copy_generic_path_info(&plan->plan, &best_path->path);
2689
2690 return plan;
2691}
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 3830 of file createplan.c.

3832{
3834 Index scan_relid = best_path->parent->relid;
3836
3837 Assert(scan_relid > 0);
3839 Assert(rte->rtekind == RTE_NAMEDTUPLESTORE);
3840
3841 /* Sort clauses into best execution order */
3843
3844 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3846
3847 /* Replace any outer-relation variables with nestloop params */
3848 if (best_path->param_info)
3849 {
3850 scan_clauses = (List *)
3852 }
3853
3855 rte->enrname);
3856
3858
3859 return scan_plan;
3860}
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 4193 of file createplan.c.

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

References Assert, bms_difference(), 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 345 of file createplan.c.

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

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

397{
398 Plan *plan;
399
400 /* Guard against stack overflow due to overly complex plans */
402
403 switch (best_path->pathtype)
404 {
405 case T_SeqScan:
406 case T_SampleScan:
407 case T_IndexScan:
408 case T_IndexOnlyScan:
409 case T_BitmapHeapScan:
410 case T_TidScan:
411 case T_TidRangeScan:
412 case T_SubqueryScan:
413 case T_FunctionScan:
414 case T_TableFuncScan:
415 case T_ValuesScan:
416 case T_CteScan:
417 case T_WorkTableScan:
419 case T_ForeignScan:
420 case T_CustomScan:
422 break;
423 case T_HashJoin:
424 case T_MergeJoin:
425 case T_NestLoop:
427 (JoinPath *) best_path);
428 break;
429 case T_Append:
432 flags);
433 break;
434 case T_MergeAppend:
437 flags);
438 break;
439 case T_Result:
441 {
444 flags);
445 }
446 else if (IsA(best_path, MinMaxAggPath))
447 {
450 }
451 else if (IsA(best_path, GroupResultPath))
452 {
455 }
456 else
457 {
458 /* Simple RTE_RESULT base relation */
461 }
462 break;
463 case T_ProjectSet:
466 break;
467 case T_Material:
470 flags);
471 break;
472 case T_Memoize:
475 flags);
476 break;
477 case T_Unique:
480 flags);
481 break;
482 case T_Gather:
485 break;
486 case T_Sort:
489 flags);
490 break;
494 flags);
495 break;
496 case T_Group:
498 (GroupPath *) best_path);
499 break;
500 case T_Agg:
504 else
505 {
508 (AggPath *) best_path);
509 }
510 break;
511 case T_WindowAgg:
514 break;
515 case T_SetOp:
518 flags);
519 break;
520 case T_RecursiveUnion:
523 break;
524 case T_LockRows:
527 flags);
528 break;
529 case T_ModifyTable:
532 break;
533 case T_Limit:
536 flags);
537 break;
538 case T_GatherMerge:
541 break;
542 default:
543 elog(ERROR, "unrecognized node type: %d",
544 (int) best_path->pathtype);
545 plan = NULL; /* keep compiler quiet */
546 break;
547 }
548
549 return plan;
550}
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:557
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:96

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

1664{
1666 Plan *subplan;
1667 List *tlist;
1668
1669 /* Since we intend to project, we don't need to constrain child tlist */
1670 subplan = create_plan_recurse(root, best_path->subpath, 0);
1671
1672 tlist = build_path_tlist(root, &best_path->path);
1673
1674 plan = make_project_set(tlist, subplan);
1675
1677
1678 return plan;
1679}
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 1865 of file createplan.c.

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

2605{
2607 Plan *leftplan;
2608 Plan *rightplan;
2609 List *tlist;
2610
2611 /* Need both children to produce same tlist, so force it */
2614
2615 tlist = build_path_tlist(root, &best_path->path);
2616
2617 plan = make_recursive_union(tlist,
2618 leftplan,
2619 rightplan,
2620 best_path->wtParam,
2621 best_path->distinctList,
2622 best_path->numGroups);
2623
2625
2626 return plan;
2627}
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 3869 of file createplan.c.

3871{
3873 Index scan_relid = best_path->parent->relid;
3875
3876 Assert(scan_relid > 0);
3878 Assert(rte->rtekind == RTE_RESULT);
3879
3880 /* Sort clauses into best execution order */
3882
3883 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3885
3886 /* Replace any outer-relation variables with nestloop params */
3887 if (best_path->param_info)
3888 {
3889 scan_clauses = (List *)
3891 }
3892
3894 best_path->parent);
3895
3897
3898 return scan_plan;
3899}
#define PG_USED_FOR_ASSERTS_ONLY
Definition c.h:308
@ 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 2799 of file createplan.c.

2801{
2803 Index scan_relid = best_path->parent->relid;
2806
2807 /* it should be a base rel with a tablesample clause... */
2808 Assert(scan_relid > 0);
2810 Assert(rte->rtekind == RTE_RELATION);
2811 tsc = rte->tablesample;
2812 Assert(tsc != NULL);
2813
2814 /* Sort clauses into best execution order */
2816
2817 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2819
2820 /* Replace any outer-relation variables with nestloop params */
2821 if (best_path->param_info)
2822 {
2823 scan_clauses = (List *)
2827 }
2828
2829 scan_plan = make_samplescan(tlist,
2831 scan_relid,
2832 tsc);
2833
2835
2836 return scan_plan;
2837}
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 557 of file createplan.c.

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

2763{
2765 Index scan_relid = best_path->parent->relid;
2766
2767 /* it should be a base rel... */
2768 Assert(scan_relid > 0);
2769 Assert(best_path->parent->rtekind == RTE_RELATION);
2770
2771 /* Sort clauses into best execution order */
2773
2774 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2776
2777 /* Replace any outer-relation variables with nestloop params */
2778 if (best_path->param_info)
2779 {
2780 scan_clauses = (List *)
2782 }
2783
2784 scan_plan = make_seqscan(tlist,
2786 scan_relid);
2787
2789
2790 return scan_plan;
2791}
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 2568 of file createplan.c.

2569{
2570 SetOp *plan;
2571 List *tlist = build_path_tlist(root, &best_path->path);
2572 Plan *leftplan;
2573 Plan *rightplan;
2574
2575 /*
2576 * SetOp doesn't project, so tlist requirements pass through; moreover we
2577 * need grouping columns to be labeled.
2578 */
2580 flags | CP_LABEL_TLIST);
2582 flags | CP_LABEL_TLIST);
2583
2584 plan = make_setop(best_path->cmd,
2585 best_path->strategy,
2586 tlist,
2587 leftplan,
2588 rightplan,
2589 best_path->groupList,
2590 best_path->numGroups);
2591
2593
2594 return plan;
2595}
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 2026 of file createplan.c.

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

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

3548{
3550 RelOptInfo *rel = best_path->path.parent;
3551 Index scan_relid = rel->relid;
3552 Plan *subplan;
3553
3554 /* it should be a subquery base rel... */
3555 Assert(scan_relid > 0);
3556 Assert(rel->rtekind == RTE_SUBQUERY);
3557
3558 /*
3559 * Recursively create Plan from Path for subquery. Since we are entering
3560 * a different planner context (subroot), recurse to create_plan not
3561 * create_plan_recurse.
3562 */
3563 subplan = create_plan(rel->subroot, best_path->subpath);
3564
3565 /* Sort clauses into best execution order */
3567
3568 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3570
3571 /*
3572 * Replace any outer-relation variables with nestloop params.
3573 *
3574 * We must provide nestloop params for both lateral references of the
3575 * subquery and outer vars in the scan_clauses. It's better to assign the
3576 * former first, because that code path requires specific param IDs, while
3577 * replace_nestloop_params can adapt to the IDs assigned by
3578 * process_subquery_nestloop_params. This avoids possibly duplicating
3579 * nestloop params when the same Var is needed for both reasons.
3580 */
3581 if (best_path->path.param_info)
3582 {
3584 rel->subplan_params);
3585 scan_clauses = (List *)
3587 }
3588
3591 scan_relid,
3592 subplan);
3593
3594 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3595
3596 return scan_plan;
3597}
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 3648 of file createplan.c.

3650{
3652 Index scan_relid = best_path->parent->relid;
3654 TableFunc *tablefunc;
3655
3656 /* it should be a function base rel... */
3657 Assert(scan_relid > 0);
3659 Assert(rte->rtekind == RTE_TABLEFUNC);
3660 tablefunc = rte->tablefunc;
3661
3662 /* Sort clauses into best execution order */
3664
3665 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3667
3668 /* Replace any outer-relation variables with nestloop params */
3669 if (best_path->param_info)
3670 {
3671 scan_clauses = (List *)
3673 /* The function expressions could contain nestloop params, too */
3674 tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
3675 }
3676
3678 tablefunc);
3679
3681
3682 return scan_plan;
3683}
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 3481 of file createplan.c.

3483{
3485 Index scan_relid = best_path->path.parent->relid;
3486 List *tidrangequals = best_path->tidrangequals;
3487
3488 /* it should be a base rel... */
3489 Assert(scan_relid > 0);
3490 Assert(best_path->path.parent->rtekind == RTE_RELATION);
3491
3492 /*
3493 * The qpqual list must contain all restrictions not enforced by the
3494 * tidrangequals list. tidrangequals has AND semantics, so we can simply
3495 * remove any qual that appears in it.
3496 */
3497 {
3498 List *qpqual = NIL;
3499 ListCell *l;
3500
3501 foreach(l, scan_clauses)
3502 {
3504
3505 if (rinfo->pseudoconstant)
3506 continue; /* we may drop pseudoconstants here */
3507 if (list_member_ptr(tidrangequals, rinfo))
3508 continue; /* simple duplicate */
3509 qpqual = lappend(qpqual, rinfo);
3510 }
3512 }
3513
3514 /* Sort clauses into best execution order */
3516
3517 /* Reduce RestrictInfo lists to bare expressions; ignore pseudoconstants */
3518 tidrangequals = extract_actual_clauses(tidrangequals, false);
3520
3521 /* Replace any outer-relation variables with nestloop params */
3522 if (best_path->path.param_info)
3523 {
3524 tidrangequals = (List *)
3525 replace_nestloop_params(root, (Node *) tidrangequals);
3526 scan_clauses = (List *)
3528 }
3529
3532 scan_relid,
3533 tidrangequals);
3534
3535 copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3536
3537 return scan_plan;
3538}
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 3384 of file createplan.c.

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

2127{
2128 Unique *plan;
2129 Plan *subplan;
2130
2131 /*
2132 * Unique doesn't project, so tlist requirements pass through; moreover we
2133 * need grouping columns to be labeled.
2134 */
2135 subplan = create_plan_recurse(root, best_path->subpath,
2136 flags | CP_LABEL_TLIST);
2137
2138 /*
2139 * make_unique_from_pathkeys calls find_ec_member_matching_expr, which
2140 * will ignore any child EC members that don't belong to the given relids.
2141 * Thus, if this unique path is based on a child relation, we must pass
2142 * its relids.
2143 */
2145 best_path->path.pathkeys,
2146 best_path->numkeys,
2147 IS_OTHER_REL(best_path->path.parent) ?
2148 best_path->path.parent->relids : NULL);
2149
2151
2152 return plan;
2153}
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 3691 of file createplan.c.

3693{
3695 Index scan_relid = best_path->parent->relid;
3697 List *values_lists;
3698
3699 /* it should be a values base rel... */
3700 Assert(scan_relid > 0);
3702 Assert(rte->rtekind == RTE_VALUES);
3703 values_lists = rte->values_lists;
3704
3705 /* Sort clauses into best execution order */
3707
3708 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3710
3711 /* Replace any outer-relation variables with nestloop params */
3712 if (best_path->param_info)
3713 {
3714 scan_clauses = (List *)
3716 /* The values lists could contain nestloop params, too */
3717 values_lists = (List *)
3718 replace_nestloop_params(root, (Node *) values_lists);
3719 }
3720
3722 values_lists);
3723
3725
3726 return scan_plan;
3727}
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 2473 of file createplan.c.

2474{
2475 WindowAgg *plan;
2476 WindowClause *wc = best_path->winclause;
2478 int numOrder = list_length(wc->orderClause);
2479 Plan *subplan;
2480 List *tlist;
2481 int partNumCols;
2485 int ordNumCols;
2489 ListCell *lc;
2490
2491 /*
2492 * Choice of tlist here is motivated by the fact that WindowAgg will be
2493 * storing the input rows of window frames in a tuplestore; it therefore
2494 * behooves us to request a small tlist to avoid wasting space. We do of
2495 * course need grouping columns to be available.
2496 */
2497 subplan = create_plan_recurse(root, best_path->subpath,
2499
2500 tlist = build_path_tlist(root, &best_path->path);
2501
2502 /*
2503 * Convert SortGroupClause lists into arrays of attr indexes and equality
2504 * operators, as wanted by executor.
2505 */
2509
2510 partNumCols = 0;
2511 foreach(lc, wc->partitionClause)
2512 {
2515
2516 Assert(OidIsValid(sgc->eqop));
2517 partColIdx[partNumCols] = tle->resno;
2518 partOperators[partNumCols] = sgc->eqop;
2519 partCollations[partNumCols] = exprCollation((Node *) tle->expr);
2520 partNumCols++;
2521 }
2522
2526
2527 ordNumCols = 0;
2528 foreach(lc, wc->orderClause)
2529 {
2532
2533 Assert(OidIsValid(sgc->eqop));
2534 ordColIdx[ordNumCols] = tle->resno;
2535 ordOperators[ordNumCols] = sgc->eqop;
2536 ordCollations[ordNumCols] = exprCollation((Node *) tle->expr);
2537 ordNumCols++;
2538 }
2539
2540 /* And finally we can make the WindowAgg node */
2541 plan = make_windowagg(tlist,
2542 wc,
2543 partNumCols,
2544 partColIdx,
2547 ordNumCols,
2548 ordColIdx,
2551 best_path->runCondition,
2552 best_path->qual,
2553 best_path->topwindow,
2554 subplan);
2555
2557
2558 return plan;
2559}
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:91
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 3907 of file createplan.c.

3909{
3911 Index scan_relid = best_path->parent->relid;
3913 Index levelsup;
3915
3916 Assert(scan_relid > 0);
3918 Assert(rte->rtekind == RTE_CTE);
3919 Assert(rte->self_reference);
3920
3921 /*
3922 * We need to find the worktable param ID, which is in the plan level
3923 * that's processing the recursive UNION, which is one level *below* where
3924 * the CTE comes from.
3925 */
3926 levelsup = rte->ctelevelsup;
3927 if (levelsup == 0) /* shouldn't happen */
3928 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3929 levelsup--;
3930 cteroot = root;
3931 while (levelsup-- > 0)
3932 {
3933 cteroot = cteroot->parent_root;
3934 if (!cteroot) /* shouldn't happen */
3935 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3936 }
3937 if (cteroot->wt_param_id < 0) /* shouldn't happen */
3938 elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
3939
3940 /* Sort clauses into best execution order */
3942
3943 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3945
3946 /* Replace any outer-relation variables with nestloop params */
3947 if (best_path->param_info)
3948 {
3949 scan_clauses = (List *)
3951 }
3952
3954 cteroot->wt_param_id);
3955
3957
3958 return scan_plan;
3959}
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 5035 of file createplan.c.

5036{
5037 IndexOptInfo *index = index_path->indexinfo;
5039 ListCell *lcc,
5040 *lci;
5041
5043
5044 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5045 {
5046 Node *clause = (Node *) lfirst(lcc);
5047 int indexcol = lfirst_int(lci);
5048
5049 clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5051 }
5052
5053 return fixed_indexorderbys;
5054}
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:97

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

5066{
5067 /*
5068 * Replace any outer-relation variables with nestloop params.
5069 *
5070 * This also makes a copy of the clause, so it's safe to modify it
5071 * in-place below.
5072 */
5073 clause = replace_nestloop_params(root, clause);
5074
5075 if (IsA(clause, OpExpr))
5076 {
5077 OpExpr *op = (OpExpr *) clause;
5078
5079 /* Replace the indexkey expression with an index Var. */
5081 index,
5082 indexcol);
5083 }
5084 else if (IsA(clause, RowCompareExpr))
5085 {
5086 RowCompareExpr *rc = (RowCompareExpr *) clause;
5087 ListCell *lca,
5088 *lcai;
5089
5090 /* Replace the indexkey expressions with index Vars. */
5093 {
5095 index,
5096 lfirst_int(lcai));
5097 }
5098 }
5099 else if (IsA(clause, ScalarArrayOpExpr))
5100 {
5101 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5102
5103 /* Replace the indexkey expression with an index Var. */
5105 index,
5106 indexcol);
5107 }
5108 else if (IsA(clause, NullTest))
5109 {
5110 NullTest *nt = (NullTest *) clause;
5111
5112 /* Replace the indexkey expression with an index Var. */
5113 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5114 index,
5115 indexcol);
5116 }
5117 else
5118 elog(ERROR, "unsupported indexqual type: %d",
5119 (int) nodeTag(clause));
5120
5121 return clause;
5122}
static Node * fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
Datum lca(PG_FUNCTION_ARGS)
Definition ltree_op.c:600
Expr * arg
Definition primnodes.h:1981

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

5137{
5138 Var *result;
5139 int pos;
5141
5142 Assert(indexcol >= 0 && indexcol < index->ncolumns);
5143
5144 /*
5145 * Remove any PlaceHolderVar wrapping of the indexkey
5146 */
5147 node = strip_noop_phvs(node);
5148
5149 /*
5150 * Remove any binary-compatible relabeling of the indexkey
5151 */
5152 while (IsA(node, RelabelType))
5153 node = (Node *) ((RelabelType *) node)->arg;
5154
5155 if (index->indexkeys[indexcol] != 0)
5156 {
5157 /* It's a simple index column */
5158 if (IsA(node, Var) &&
5159 ((Var *) node)->varno == index->rel->relid &&
5160 ((Var *) node)->varattno == index->indexkeys[indexcol])
5161 {
5162 result = (Var *) copyObject(node);
5163 result->varno = INDEX_VAR;
5164 result->varattno = indexcol + 1;
5165 return (Node *) result;
5166 }
5167 else
5168 elog(ERROR, "index key does not match expected index column");
5169 }
5170
5171 /* It's an index expression, so find and cross-check the expression */
5172 indexpr_item = list_head(index->indexprs);
5173 for (pos = 0; pos < index->ncolumns; pos++)
5174 {
5175 if (index->indexkeys[pos] == 0)
5176 {
5177 if (indexpr_item == NULL)
5178 elog(ERROR, "too few entries in indexprs list");
5179 if (pos == indexcol)
5180 {
5181 Node *indexkey;
5182
5185 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5186 if (equal(node, indexkey))
5187 {
5188 result = makeVar(INDEX_VAR, indexcol + 1,
5191 0);
5192 return (Node *) result;
5193 }
5194 else
5195 elog(ERROR, "index key does not match expected index column");
5196 }
5197 indexpr_item = lnext(index->indexprs, indexpr_item);
5198 }
5199 }
5200
5201 /* Oops... */
5202 elog(ERROR, "index key does not match expected index column");
5203 return NULL; /* keep compiler quiet */
5204}
uint32 result
Datum arg
Definition elog.c:1323
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 4994 of file createplan.c.

4996{
4997 IndexOptInfo *index = index_path->indexinfo;
5000 ListCell *lc;
5001
5003
5004 foreach(lc, index_path->indexclauses)
5005 {
5007 int indexcol = iclause->indexcol;
5008 ListCell *lc2;
5009
5010 foreach(lc2, iclause->indexquals)
5011 {
5013 Node *clause = (Node *) rinfo->clause;
5014
5016 clause = fix_indexqual_clause(root, index, indexcol,
5017 clause, iclause->indexcols);
5019 }
5020 }
5021
5024}

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

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

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

5217{
5218 List *t_list = NIL;
5219 ListCell *l;
5220
5221 foreach(l, clauses)
5222 {
5224 OpExpr *clause = (OpExpr *) restrictinfo->clause;
5225
5226 Assert(is_opclause(clause));
5227 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5228 {
5229 /*
5230 * Duplicate just enough of the structure to allow commuting the
5231 * clause without changing the original list. Could use
5232 * copyObject, but a complete deep copy is overkill.
5233 */
5235
5236 temp->opno = clause->opno;
5237 temp->opfuncid = InvalidOid;
5238 temp->opresulttype = clause->opresulttype;
5239 temp->opretset = clause->opretset;
5240 temp->opcollid = clause->opcollid;
5241 temp->inputcollid = clause->inputcollid;
5242 temp->args = list_copy(clause->args);
5243 temp->location = clause->location;
5244 /* Commute it --- note this modifies the temp node in-place. */
5247 restrictinfo->outer_is_left = false;
5248 }
5249 else
5250 {
5251 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5252 t_list = lappend(t_list, clause);
5253 restrictinfo->outer_is_left = true;
5254 }
5255 }
5256 return t_list;
5257}
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition bitmapset.c:547
void CommuteOpExpr(OpExpr *clause)
Definition clauses.c:2408

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

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

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

7265{
7266 /* Most plan types can project, so just list the ones that can't */
7267 switch (path->pathtype)
7268 {
7269 case T_Hash:
7270 case T_Material:
7271 case T_Memoize:
7272 case T_Sort:
7273 case T_IncrementalSort:
7274 case T_Unique:
7275 case T_SetOp:
7276 case T_LockRows:
7277 case T_Limit:
7278 case T_ModifyTable:
7279 case T_MergeAppend:
7280 case T_RecursiveUnion:
7281 return false;
7282 case T_CustomScan:
7284 return true;
7285 return false;
7286 case T_Append:
7287
7288 /*
7289 * Append can't project, but if an AppendPath is being used to
7290 * represent a dummy path, what will actually be generated is a
7291 * Result which can project.
7292 */
7293 return IS_DUMMY_APPEND(path);
7294 case T_ProjectSet:
7295
7296 /*
7297 * Although ProjectSet certainly projects, say "no" because we
7298 * don't want the planner to randomly replace its tlist with
7299 * something else; the SRFs have to stay at top level. This might
7300 * get relaxed later.
7301 */
7302 return false;
7303 default:
7304 break;
7305 }
7306 return true;
7307}
#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 7314 of file createplan.c.

7315{
7316 /* Most plan types can project, so just list the ones that can't */
7317 switch (nodeTag(plan))
7318 {
7319 case T_Hash:
7320 case T_Material:
7321 case T_Memoize:
7322 case T_Sort:
7323 case T_Unique:
7324 case T_SetOp:
7325 case T_LockRows:
7326 case T_Limit:
7327 case T_ModifyTable:
7328 case T_Append:
7329 case T_MergeAppend:
7330 case T_RecursiveUnion:
7331 return false;
7332 case T_CustomScan:
7334 return true;
7335 return false;
7336 case T_ProjectSet:
7337
7338 /*
7339 * Although ProjectSet certainly projects, say "no" because we
7340 * don't want the planner to randomly replace its tlist with
7341 * something else; the SRFs have to stay at top level. This might
7342 * get relaxed later.
7343 */
7344 return false;
7345 default:
7346 break;
7347 }
7348 return true;
7349}

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

5456{
5457 Plan *lefttree = plan->sort.plan.lefttree;
5458 Path sort_path; /* dummy for result of cost_incremental_sort */
5459
5461
5463 plan->nPresortedCols,
5464 plan->sort.plan.disabled_nodes,
5465 lefttree->startup_cost,
5466 lefttree->total_cost,
5467 lefttree->plan_rows,
5468 lefttree->plan_width,
5469 0.0,
5470 work_mem,
5471 limit_tuples);
5472 plan->sort.plan.startup_cost = sort_path.startup_cost;
5473 plan->sort.plan.total_cost = sort_path.total_cost;
5474 plan->sort.plan.plan_rows = lefttree->plan_rows;
5475 plan->sort.plan.plan_width = lefttree->plan_width;
5476 plan->sort.plan.parallel_aware = false;
5477 plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5478}
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:2054
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 5426 of file createplan.c.

5427{
5428 Plan *lefttree = plan->plan.lefttree;
5429 Path sort_path; /* dummy for result of cost_sort */
5430
5431 Assert(IsA(plan, Sort));
5432
5434 plan->plan.disabled_nodes,
5435 lefttree->total_cost,
5436 lefttree->plan_rows,
5437 lefttree->plan_width,
5438 0.0,
5439 work_mem,
5440 limit_tuples);
5441 plan->plan.startup_cost = sort_path.startup_cost;
5442 plan->plan.total_cost = sort_path.total_cost;
5443 plan->plan.plan_rows = lefttree->plan_rows;
5444 plan->plan.plan_width = lefttree->plan_width;
5445 plan->plan.parallel_aware = false;
5446 plan->plan.parallel_safe = lefttree->parallel_safe;
5447}
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:2202

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

6621{
6622 Agg *node = makeNode(Agg);
6623 Plan *plan = &node->plan;
6624
6625 node->aggstrategy = aggstrategy;
6626 node->aggsplit = aggsplit;
6627 node->numCols = numGroupCols;
6628 node->grpColIdx = grpColIdx;
6629 node->grpOperators = grpOperators;
6630 node->grpCollations = grpCollations;
6631 node->numGroups = numGroups;
6632 node->transitionSpace = transitionSpace;
6633 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6634 node->groupingSets = groupingSets;
6635 node->chain = chain;
6636
6637 plan->qual = qual;
6638 plan->targetlist = tlist;
6639 plan->lefttree = lefttree;
6640 plan->righttree = NULL;
6641
6642 return node;
6643}
AggSplit aggsplit
Definition plannodes.h:1219
List * chain
Definition plannodes.h:1246
List * groupingSets
Definition plannodes.h:1243
Bitmapset * aggParams
Definition plannodes.h:1238
Cardinality numGroups
Definition plannodes.h:1232
Plan plan
Definition plannodes.h:1213
int numCols
Definition plannodes.h:1222
uint64 transitionSpace
Definition plannodes.h:1235
AggStrategy aggstrategy
Definition plannodes.h:1216
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 5926 of file createplan.c.

5927{
5928 BitmapAnd *node = makeNode(BitmapAnd);
5929 Plan *plan = &node->plan;
5930
5931 plan->targetlist = NIL;
5932 plan->qual = NIL;
5933 plan->lefttree = NULL;
5934 plan->righttree = NULL;
5935 node->bitmapplans = bitmapplans;
5936
5937 return node;
5938}
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 5633 of file createplan.c.

5638{
5640 Plan *plan = &node->scan.plan;
5641
5642 plan->targetlist = qptlist;
5643 plan->qual = qpqual;
5644 plan->lefttree = lefttree;
5645 plan->righttree = NULL;
5646 node->scan.scanrelid = scanrelid;
5647 node->bitmapqualorig = bitmapqualorig;
5648
5649 return node;
5650}
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 5612 of file createplan.c.

5616{
5618 Plan *plan = &node->scan.plan;
5619
5620 plan->targetlist = NIL; /* not used */
5621 plan->qual = NIL; /* not used */
5622 plan->lefttree = NULL;
5623 plan->righttree = NULL;
5624 node->scan.scanrelid = scanrelid;
5625 node->indexid = indexid;
5626 node->indexqual = indexqual;
5627 node->indexqualorig = indexqualorig;
5628
5629 return node;
5630}
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 5941 of file createplan.c.

5942{
5943 BitmapOr *node = makeNode(BitmapOr);
5944 Plan *plan = &node->plan;
5945
5946 plan->targetlist = NIL;
5947 plan->qual = NIL;
5948 plan->lefttree = NULL;
5949 plan->righttree = NULL;
5950 node->bitmapplans = bitmapplans;
5951
5952 return node;
5953}
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 5770 of file createplan.c.

5775{
5776 CteScan *node = makeNode(CteScan);
5777 Plan *plan = &node->scan.plan;
5778
5779 plan->targetlist = qptlist;
5780 plan->qual = qpqual;
5781 plan->lefttree = NULL;
5782 plan->righttree = NULL;
5783 node->scan.scanrelid = scanrelid;
5784 node->ctePlanId = ctePlanId;
5785 node->cteParam = cteParam;
5786
5787 return node;
5788}
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 5830 of file createplan.c.

5838{
5840 Plan *plan = &node->scan.plan;
5841
5842 /* cost will be filled in by create_foreignscan_plan */
5843 plan->targetlist = qptlist;
5844 plan->qual = qpqual;
5845 plan->lefttree = outer_plan;
5846 plan->righttree = NULL;
5847 node->scan.scanrelid = scanrelid;
5848
5849 /* these may be overridden by the FDW's PlanDirectModify callback. */
5850 node->operation = CMD_SELECT;
5851 node->resultRelation = 0;
5852
5853 /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5854 node->checkAsUser = InvalidOid;
5855 node->fs_server = InvalidOid;
5856 node->fdw_exprs = fdw_exprs;
5857 node->fdw_private = fdw_private;
5858 node->fdw_scan_tlist = fdw_scan_tlist;
5859 node->fdw_recheck_quals = fdw_recheck_quals;
5860 /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5861 node->fs_relids = NULL;
5862 node->fs_base_relids = NULL;
5863 /* fsSystemCol will be filled in by create_foreignscan_plan */
5864 node->fsSystemCol = false;
5865
5866 return node;
5867}
@ CMD_SELECT
Definition nodes.h:273
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 5711 of file createplan.c.

5716{
5718 Plan *plan = &node->scan.plan;
5719
5720 plan->targetlist = qptlist;
5721 plan->qual = qpqual;
5722 plan->lefttree = NULL;
5723 plan->righttree = NULL;
5724 node->scan.scanrelid = scanrelid;
5725 node->functions = functions;
5726 node->funcordinality = funcordinality;
5727
5728 return node;
5729}
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 6824 of file createplan.c.

6830{
6831 Gather *node = makeNode(Gather);
6832 Plan *plan = &node->plan;
6833
6835 plan->qual = qpqual;
6836 plan->lefttree = subplan;
6837 plan->righttree = NULL;
6838 node->num_workers = nworkers;
6839 node->rescan_param = rescan_param;
6840 node->single_copy = single_copy;
6841 node->invisible = false;
6842 node->initParam = NULL;
6843
6844 return node;
6845}
int num_workers
Definition plannodes.h:1362
bool invisible
Definition plannodes.h:1368
Bitmapset * initParam
Definition plannodes.h:1374
bool single_copy
Definition plannodes.h:1366
Plan plan
Definition plannodes.h:1360
int rescan_param
Definition plannodes.h:1364

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

6967{
6968 Result *node = makeNode(Result);
6969 Plan *plan = &node->plan;
6970
6971 Assert(subplan != NULL);
6972
6973 plan->targetlist = tlist;
6974 plan->qual = NIL;
6975 plan->lefttree = subplan;
6976 plan->righttree = NULL;
6978 node->resconstantqual = resconstantqual;
6979 node->relids = NULL;
6980
6981 return node;
6982}
@ 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 6686 of file createplan.c.

6693{
6694 Group *node = makeNode(Group);
6695 Plan *plan = &node->plan;
6696
6697 node->numCols = numGroupCols;
6698 node->grpColIdx = grpColIdx;
6699 node->grpOperators = grpOperators;
6700 node->grpCollations = grpCollations;
6701
6702 plan->qual = qual;
6703 plan->targetlist = tlist;
6704 plan->lefttree = lefttree;
6705 plan->righttree = NULL;
6706
6707 return node;
6708}
int numCols
Definition plannodes.h:1187
Plan plan
Definition plannodes.h:1184

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

6021{
6022 Hash *node = makeNode(Hash);
6023 Plan *plan = &node->plan;
6024
6025 plan->targetlist = lefttree->targetlist;
6026 plan->qual = NIL;
6027 plan->lefttree = lefttree;
6028 plan->righttree = NULL;
6029
6030 node->hashkeys = hashkeys;
6031 node->skewTable = skewTable;
6032 node->skewColumn = skewColumn;
6033 node->skewInherit = skewInherit;
6034
6035 return node;
6036}
AttrNumber skewColumn
Definition plannodes.h:1436
List * hashkeys
Definition plannodes.h:1432
Oid skewTable
Definition plannodes.h:1434
bool skewInherit
Definition plannodes.h:1438
Plan plan
Definition plannodes.h:1425

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,
Relids  ojrelids,
bool  inner_unique 
)
static

Definition at line 5983 of file createplan.c.

5995{
5996 HashJoin *node = makeNode(HashJoin);
5997 Plan *plan = &node->join.plan;
5998
5999 plan->targetlist = tlist;
6000 plan->qual = otherclauses;
6001 plan->lefttree = lefttree;
6002 plan->righttree = righttree;
6003 node->hashclauses = hashclauses;
6004 node->hashoperators = hashoperators;
6005 node->hashcollations = hashcollations;
6006 node->hashkeys = hashkeys;
6007 node->join.jointype = jointype;
6008 node->join.inner_unique = inner_unique;
6009 node->join.joinqual = joinclauses;
6010 node->join.ojrelids = ojrelids;
6011
6012 return node;
6013}
List * hashcollations
Definition plannodes.h:1071
List * hashclauses
Definition plannodes.h:1069
List * hashoperators
Definition plannodes.h:1070
Join join
Definition plannodes.h:1068
List * hashkeys
Definition plannodes.h:1077
List * joinqual
Definition plannodes.h:993
JoinType jointype
Definition plannodes.h:990
Bitmapset * ojrelids
Definition plannodes.h:994
bool inner_unique
Definition plannodes.h:991

References fb(), HashJoin::hashclauses, HashJoin::hashcollations, HashJoin::hashkeys, HashJoin::hashoperators, Join::inner_unique, HashJoin::join, Join::joinqual, Join::jointype, makeNode, Join::ojrelids, 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 6113 of file createplan.c.

6116{
6117 IncrementalSort *node;
6118 Plan *plan;
6119
6120 node = makeNode(IncrementalSort);
6121
6122 plan = &node->sort.plan;
6123 plan->targetlist = lefttree->targetlist;
6124 plan->qual = NIL;
6125 plan->lefttree = lefttree;
6126 plan->righttree = NULL;
6127 node->nPresortedCols = nPresortedCols;
6128 node->sort.numCols = numCols;
6129 node->sort.sortColIdx = sortColIdx;
6130 node->sort.sortOperators = sortOperators;
6131 node->sort.collations = collations;
6132 node->sort.nullsFirst = nullsFirst;
6133
6134 return node;
6135}
int numCols
Definition plannodes.h:1150
Plan plan
Definition plannodes.h:1147

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

6398{
6399 int numsortkeys;
6400 AttrNumber *sortColIdx;
6401 Oid *sortOperators;
6402 Oid *collations;
6403 bool *nullsFirst;
6404
6405 /* Compute sort column info, and adjust lefttree as needed */
6406 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6407 relids,
6408 NULL,
6409 false,
6410 &numsortkeys,
6411 &sortColIdx,
6412 &sortOperators,
6413 &collations,
6414 &nullsFirst);
6415
6416 /* Now build the Sort node */
6417 return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6418 sortColIdx, sortOperators,
6419 collations, nullsFirst);
6420}

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

5592{
5594 Plan *plan = &node->scan.plan;
5595
5596 plan->targetlist = qptlist;
5597 plan->qual = qpqual;
5598 plan->lefttree = NULL;
5599 plan->righttree = NULL;
5600 node->scan.scanrelid = scanrelid;
5601 node->indexid = indexid;
5602 node->indexqual = indexqual;
5603 node->recheckqual = recheckqual;
5604 node->indexorderby = indexorderby;
5605 node->indextlist = indextlist;
5606 node->indexorderdir = indexscandir;
5607
5608 return node;
5609}
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 5552 of file createplan.c.

5562{
5563 IndexScan *node = makeNode(IndexScan);
5564 Plan *plan = &node->scan.plan;
5565
5566 plan->targetlist = qptlist;
5567 plan->qual = qpqual;
5568 plan->lefttree = NULL;
5569 plan->righttree = NULL;
5570 node->scan.scanrelid = scanrelid;
5571 node->indexid = indexid;
5572 node->indexqual = indexqual;
5573 node->indexqualorig = indexqualorig;
5574 node->indexorderby = indexorderby;
5575 node->indexorderbyorig = indexorderbyorig;
5576 node->indexorderbyops = indexorderbyops;
5577 node->indexorderdir = indexscandir;
5578
5579 return node;
5580}
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 6935 of file createplan.c.

6938{
6939 Limit *node = makeNode(Limit);
6940 Plan *plan = &node->plan;
6941
6942 plan->targetlist = lefttree->targetlist;
6943 plan->qual = NIL;
6944 plan->lefttree = lefttree;
6945 plan->righttree = NULL;
6946
6947 node->limitOffset = limitOffset;
6948 node->limitCount = limitCount;
6949 node->limitOption = limitOption;
6950 node->uniqNumCols = uniqNumCols;
6951 node->uniqColIdx = uniqColIdx;
6952 node->uniqOperators = uniqOperators;
6953 node->uniqCollations = uniqCollations;
6954
6955 return node;
6956}
LimitOption limitOption
Definition plannodes.h:1511
Plan plan
Definition plannodes.h:1502
Node * limitCount
Definition plannodes.h:1508
int uniqNumCols
Definition plannodes.h:1514
Node * limitOffset
Definition plannodes.h:1505

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

6915{
6916 LockRows *node = makeNode(LockRows);
6917 Plan *plan = &node->plan;
6918
6919 plan->targetlist = lefttree->targetlist;
6920 plan->qual = NIL;
6921 plan->lefttree = lefttree;
6922 plan->righttree = NULL;
6923
6924 node->rowMarks = rowMarks;
6925 node->epqParam = epqParam;
6926
6927 return node;
6928}
int epqParam
Definition plannodes.h:1490
List * rowMarks
Definition plannodes.h:1488
Plan plan
Definition plannodes.h:1486

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

6521{
6522 Material *node = makeNode(Material);
6523 Plan *plan = &node->plan;
6524
6525 plan->targetlist = lefttree->targetlist;
6526 plan->qual = NIL;
6527 plan->lefttree = lefttree;
6528 plan->righttree = NULL;
6529
6530 return node;
6531}
Plan plan
Definition plannodes.h:1086

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

6591{
6592 Memoize *node = makeNode(Memoize);
6593 Plan *plan = &node->plan;
6594
6595 plan->targetlist = lefttree->targetlist;
6596 plan->qual = NIL;
6597 plan->lefttree = lefttree;
6598 plan->righttree = NULL;
6599
6600 node->numKeys = list_length(param_exprs);
6601 node->hashOperators = hashoperators;
6602 node->collations = collations;
6603 node->param_exprs = param_exprs;
6604 node->singlerow = singlerow;
6605 node->binary_mode = binary_mode;
6606 node->est_entries = est_entries;
6607 node->keyparamids = keyparamids;
6608 node->est_calls = est_calls;
6609 node->est_unique_keys = est_unique_keys;
6610 node->est_hit_ratio = est_hit_ratio;
6611
6612 return node;
6613}
Plan plan
Definition plannodes.h:1095
bool singlerow
Definition plannodes.h:1113
Cardinality est_calls
Definition plannodes.h:1131
Bitmapset * keyparamids
Definition plannodes.h:1128
bool binary_mode
Definition plannodes.h:1119
int numKeys
Definition plannodes.h:1098
Cardinality est_unique_keys
Definition plannodes.h:1134
List * param_exprs
Definition plannodes.h:1107
double est_hit_ratio
Definition plannodes.h:1137
uint32 est_entries
Definition plannodes.h:1125

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,
Relids  ojrelids,
bool  inner_unique,
bool  skip_mark_restore 
)
static

Definition at line 6039 of file createplan.c.

6053{
6054 MergeJoin *node = makeNode(MergeJoin);
6055 Plan *plan = &node->join.plan;
6056
6057 plan->targetlist = tlist;
6058 plan->qual = otherclauses;
6059 plan->lefttree = lefttree;
6060 plan->righttree = righttree;
6061 node->skip_mark_restore = skip_mark_restore;
6062 node->mergeclauses = mergeclauses;
6063 node->mergeFamilies = mergefamilies;
6064 node->mergeCollations = mergecollations;
6065 node->mergeReversals = mergereversals;
6066 node->mergeNullsFirst = mergenullsfirst;
6067 node->join.jointype = jointype;
6068 node->join.inner_unique = inner_unique;
6069 node->join.joinqual = joinclauses;
6070 node->join.ojrelids = ojrelids;
6071
6072 return node;
6073}
List * mergeclauses
Definition plannodes.h:1045
bool skip_mark_restore
Definition plannodes.h:1042

References fb(), Join::inner_unique, MergeJoin::join, Join::joinqual, Join::jointype, makeNode, MergeJoin::mergeclauses, Join::ojrelids, 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 7038 of file createplan.c.

7047{
7049 bool returning_old_or_new = false;
7050 bool returning_old_or_new_valid = false;
7051 bool transition_tables = false;
7052 bool transition_tables_valid = false;
7055 ListCell *lc;
7056 int i;
7057
7059 (operation == CMD_UPDATE ?
7060 list_length(resultRelations) == list_length(updateColnosLists) :
7061 updateColnosLists == NIL));
7062 Assert(withCheckOptionLists == NIL ||
7063 list_length(resultRelations) == list_length(withCheckOptionLists));
7064 Assert(returningLists == NIL ||
7065 list_length(resultRelations) == list_length(returningLists));
7066
7067 node->plan.lefttree = subplan;
7068 node->plan.righttree = NULL;
7069 node->plan.qual = NIL;
7070 /* setrefs.c will fill in the targetlist, if needed */
7071 node->plan.targetlist = NIL;
7072
7073 node->operation = operation;
7074 node->canSetTag = canSetTag;
7075 node->nominalRelation = nominalRelation;
7076 node->rootRelation = rootRelation;
7077 node->resultRelations = resultRelations;
7078 if (!onconflict)
7079 {
7082 node->onConflictSet = NIL;
7083 node->onConflictCols = NIL;
7084 node->onConflictWhere = NULL;
7085 node->arbiterIndexes = NIL;
7086 node->exclRelRTI = 0;
7087 node->exclRelTlist = NIL;
7088 }
7089 else
7090 {
7091 node->onConflictAction = onconflict->action;
7092
7093 /* Lock strength for ON CONFLICT DO SELECT [FOR UPDATE/SHARE] */
7094 node->onConflictLockStrength = onconflict->lockStrength;
7095
7096 /*
7097 * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7098 * executor's convention of having consecutive resno's. The actual
7099 * target column numbers are saved in node->onConflictCols. (This
7100 * could be done earlier, but there seems no need to.)
7101 */
7102 node->onConflictSet = onconflict->onConflictSet;
7103 node->onConflictCols =
7105 node->onConflictWhere = onconflict->onConflictWhere;
7106
7107 /*
7108 * If a set of unique index inference elements was provided (an
7109 * INSERT...ON CONFLICT "inference specification"), then infer
7110 * appropriate unique indexes (or throw an error if none are
7111 * available).
7112 */
7114
7115 node->exclRelRTI = onconflict->exclRelIndex;
7116 node->exclRelTlist = onconflict->exclRelTlist;
7117 }
7118 node->updateColnosLists = updateColnosLists;
7119 node->forPortionOf = (Node *) forPortionOf;
7120 node->withCheckOptionLists = withCheckOptionLists;
7121 node->returningOldAlias = root->parse->returningOldAlias;
7122 node->returningNewAlias = root->parse->returningNewAlias;
7123 node->returningLists = returningLists;
7124 node->rowMarks = rowMarks;
7125 node->mergeActionLists = mergeActionLists;
7126 node->mergeJoinConditions = mergeJoinConditions;
7127 node->epqParam = epqParam;
7128
7129 /*
7130 * For each result relation that is a foreign table, allow the FDW to
7131 * construct private plan data, and accumulate it all into a list.
7132 */
7135 i = 0;
7136 foreach(lc, resultRelations)
7137 {
7138 Index rti = lfirst_int(lc);
7139 FdwRoutine *fdwroutine;
7140 List *fdw_private;
7141 bool direct_modify;
7142
7143 /*
7144 * If possible, we want to get the FdwRoutine from our RelOptInfo for
7145 * the table. But sometimes we don't have a RelOptInfo and must get
7146 * it the hard way. (In INSERT, the target relation is not scanned,
7147 * so it's not a baserel; and there are also corner cases for
7148 * updatable views where the target rel isn't a baserel.)
7149 */
7150 if (rti < root->simple_rel_array_size &&
7151 root->simple_rel_array[rti] != NULL)
7152 {
7153 RelOptInfo *resultRel = root->simple_rel_array[rti];
7154
7155 fdwroutine = resultRel->fdwroutine;
7156 }
7157 else
7158 {
7160
7161 if (rte->rtekind == RTE_RELATION &&
7162 rte->relkind == RELKIND_FOREIGN_TABLE)
7163 {
7164 /* Check if the access to foreign tables is restricted */
7166 {
7167 /* there must not be built-in foreign tables */
7168 Assert(rte->relid >= FirstNormalObjectId);
7169 ereport(ERROR,
7171 errmsg("access to non-system foreign table is restricted")));
7172 }
7173
7174 fdwroutine = GetFdwRoutineByRelId(rte->relid);
7175 }
7176 else
7177 fdwroutine = NULL;
7178 }
7179
7180 /*
7181 * MERGE is not currently supported for foreign tables. We already
7182 * checked that when the table mentioned in the query is foreign; but
7183 * we can still get here if a partitioned table has a foreign table as
7184 * partition. Disallow that now, to avoid an uglier error message
7185 * later.
7186 */
7187 if (operation == CMD_MERGE && fdwroutine != NULL)
7188 {
7190
7191 ereport(ERROR,
7193 errmsg("cannot execute MERGE on relation \"%s\"",
7194 get_rel_name(rte->relid)),
7196 }
7197
7198 /*
7199 * Try to modify the foreign table directly if (1) the FDW provides
7200 * callback functions needed for that and (2) there are no local
7201 * structures that need to be run for each modified row: row-level
7202 * triggers on the foreign table, stored generated columns, WITH CHECK
7203 * OPTIONs from parent views, Vars returning OLD/NEW in the RETURNING
7204 * list, or transition tables on the named relation.
7205 */
7206 direct_modify = false;
7207 if (fdwroutine != NULL &&
7208 fdwroutine->PlanDirectModify != NULL &&
7209 fdwroutine->BeginDirectModify != NULL &&
7210 fdwroutine->IterateDirectModify != NULL &&
7211 fdwroutine->EndDirectModify != NULL &&
7212 withCheckOptionLists == NIL &&
7215 {
7216 /*
7217 * returning_old_or_new and transition_tables are the same for all
7218 * result relations, respectively
7219 */
7221 {
7224 root->parse->returningList);
7226 }
7228 {
7230 {
7232 nominalRelation,
7233 operation);
7235 }
7236 if (!transition_tables)
7237 direct_modify = fdwroutine->PlanDirectModify(root, node,
7238 rti, i);
7239 }
7240 }
7241 if (direct_modify)
7243
7244 if (!direct_modify &&
7245 fdwroutine != NULL &&
7246 fdwroutine->PlanForeignModify != NULL)
7247 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7248 else
7249 fdw_private = NIL;
7251 i++;
7252 }
7255
7256 return node;
7257}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition bitmapset.c:934
#define unlikely(x)
Definition c.h:497
static DataChecksumsWorkerOperation operation
int errcode(int sqlerrcode)
Definition elog.c:875
#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:2242
@ ONCONFLICT_NONE
Definition nodes.h:426
@ CMD_MERGE
Definition nodes.h:277
@ CMD_UPDATE
Definition nodes.h:274
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:2395
LockClauseStrength lockStrength
Definition primnodes.h:2404
List * onConflictSet
Definition primnodes.h:2407
List * exclRelTlist
Definition primnodes.h:2412
Node * onConflictWhere
Definition primnodes.h:2410
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 5791 of file createplan.c.

5795{
5797 Plan *plan = &node->scan.plan;
5798
5799 /* cost should be inserted by caller */
5800 plan->targetlist = qptlist;
5801 plan->qual = qpqual;
5802 plan->lefttree = NULL;
5803 plan->righttree = NULL;
5804 node->scan.scanrelid = scanrelid;
5805 node->enrname = enrname;
5806
5807 return node;
5808}

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,
Relids  ojrelids,
bool  inner_unique 
)
static

Definition at line 5956 of file createplan.c.

5965{
5966 NestLoop *node = makeNode(NestLoop);
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->join.jointype = jointype;
5974 node->join.inner_unique = inner_unique;
5975 node->join.joinqual = joinclauses;
5976 node->join.ojrelids = ojrelids;
5977 node->nestParams = nestParams;
5978
5979 return node;
5980}
List * nestParams
Definition plannodes.h:1012
Join join
Definition plannodes.h:1010

References fb(), Join::inner_unique, NestLoop::join, Join::joinqual, Join::jointype, makeNode, NestLoop::nestParams, Join::ojrelids, 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 6995 of file createplan.c.

6998{
6999 Result *node = makeNode(Result);
7000 Plan *plan = &node->plan;
7001
7002 plan->targetlist = tlist;
7003 plan->qual = NIL;
7004 plan->lefttree = NULL;
7005 plan->righttree = NULL;
7008 node->resconstantqual = resconstantqual;
7009 node->relids = rel->relids;
7010
7011 return node;
7012}
#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 7019 of file createplan.c.

7021{
7023 Plan *plan = &node->plan;
7024
7025 plan->targetlist = tlist;
7026 plan->qual = NIL;
7027 plan->lefttree = subplan;
7028 plan->righttree = NULL;
7029
7030 return node;
7031}

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

5876{
5878 Plan *plan = &node->plan;
5879 int numCols = list_length(distinctList);
5880
5881 plan->targetlist = tlist;
5882 plan->qual = NIL;
5883 plan->lefttree = lefttree;
5884 plan->righttree = righttree;
5885 node->wtParam = wtParam;
5886
5887 /*
5888 * convert SortGroupClause list into arrays of attr indexes and equality
5889 * operators, as wanted by executor
5890 */
5891 node->numCols = numCols;
5892 if (numCols > 0)
5893 {
5894 int keyno = 0;
5899
5900 dupColIdx = palloc_array(AttrNumber, numCols);
5901 dupOperators = palloc_array(Oid, numCols);
5902 dupCollations = palloc_array(Oid, numCols);
5903
5904 foreach(slitem, distinctList)
5905 {
5908 plan->targetlist);
5909
5910 dupColIdx[keyno] = tle->resno;
5911 dupOperators[keyno] = sortcl->eqop;
5912 dupCollations[keyno] = exprCollation((Node *) tle->expr);
5914 keyno++;
5915 }
5916 node->dupColIdx = dupColIdx;
5917 node->dupOperators = dupOperators;
5918 node->dupCollations = dupCollations;
5919 }
5920 node->numGroups = numGroups;
5921
5922 return node;
5923}
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 5533 of file createplan.c.

5537{
5539 Plan *plan = &node->scan.plan;
5540
5541 plan->targetlist = qptlist;
5542 plan->qual = qpqual;
5543 plan->lefttree = NULL;
5544 plan->righttree = NULL;
5545 node->scan.scanrelid = scanrelid;
5546 node->tablesample = tsc;
5547
5548 return node;
5549}
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 5516 of file createplan.c.

5519{
5520 SeqScan *node = makeNode(SeqScan);
5521 Plan *plan = &node->scan.plan;
5522
5523 plan->targetlist = qptlist;
5524 plan->qual = qpqual;
5525 plan->lefttree = NULL;
5526 plan->righttree = NULL;
5527 node->scan.scanrelid = scanrelid;
5528
5529 return node;
5530}
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 6853 of file createplan.c.

6856{
6857 SetOp *node = makeNode(SetOp);
6858 Plan *plan = &node->plan;
6859 int numCols = list_length(groupList);
6860 int keyno = 0;
6864 bool *cmpNullsFirst;
6866
6867 plan->targetlist = tlist;
6868 plan->qual = NIL;
6869 plan->lefttree = lefttree;
6870 plan->righttree = righttree;
6871
6872 /*
6873 * convert SortGroupClause list into arrays of attr indexes and comparison
6874 * operators, as wanted by executor
6875 */
6876 cmpColIdx = palloc_array(AttrNumber, numCols);
6877 cmpOperators = palloc_array(Oid, numCols);
6878 cmpCollations = palloc_array(Oid, numCols);
6879 cmpNullsFirst = palloc_array(bool, numCols);
6880
6881 foreach(slitem, groupList)
6882 {
6885
6886 cmpColIdx[keyno] = tle->resno;
6887 if (strategy == SETOP_HASHED)
6888 cmpOperators[keyno] = sortcl->eqop;
6889 else
6890 cmpOperators[keyno] = sortcl->sortop;
6892 cmpCollations[keyno] = exprCollation((Node *) tle->expr);
6893 cmpNullsFirst[keyno] = sortcl->nulls_first;
6894 keyno++;
6895 }
6896
6897 node->cmd = cmd;
6898 node->strategy = strategy;
6899 node->numCols = numCols;
6900 node->cmpColIdx = cmpColIdx;
6901 node->cmpOperators = cmpOperators;
6902 node->cmpCollations = cmpCollations;
6903 node->cmpNullsFirst = cmpNullsFirst;
6904 node->numGroups = numGroups;
6905
6906 return node;
6907}
@ SETOP_HASHED
Definition nodes.h:415
SetOpStrategy strategy
Definition plannodes.h:1456
SetOpCmd cmd
Definition plannodes.h:1453
int numCols
Definition plannodes.h:1459
Plan plan
Definition plannodes.h:1450
Cardinality numGroups
Definition plannodes.h:1472

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

6085{
6086 Sort *node;
6087 Plan *plan;
6088
6089 node = makeNode(Sort);
6090
6091 plan = &node->plan;
6092 plan->targetlist = lefttree->targetlist;
6093 plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
6094 plan->qual = NIL;
6095 plan->lefttree = lefttree;
6096 plan->righttree = NULL;
6097 node->numCols = numCols;
6098 node->sortColIdx = sortColIdx;
6099 node->sortOperators = sortOperators;
6100 node->collations = collations;
6101 node->nullsFirst = nullsFirst;
6102
6103 return node;
6104}
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 6479 of file createplan.c.

6482{
6483 List *sub_tlist = lefttree->targetlist;
6484 ListCell *l;
6485 int numsortkeys;
6486 AttrNumber *sortColIdx;
6487 Oid *sortOperators;
6488 Oid *collations;
6489 bool *nullsFirst;
6490
6491 /* Convert list-ish representation to arrays wanted by executor */
6493 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6494 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6495 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6496 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6497
6498 numsortkeys = 0;
6499 foreach(l, groupcls)
6500 {
6503
6504 if (!tle)
6505 elog(ERROR, "could not retrieve tle for sort-from-groupcols");
6506
6507 sortColIdx[numsortkeys] = tle->resno;
6508 sortOperators[numsortkeys] = grpcl->sortop;
6509 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6510 nullsFirst[numsortkeys] = grpcl->nulls_first;
6511 numsortkeys++;
6512 }
6513
6514 return make_sort(lefttree, numsortkeys,
6515 sortColIdx, sortOperators,
6516 collations, nullsFirst);
6517}
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 6361 of file createplan.c.

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

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

6431{
6432 List *sub_tlist = lefttree->targetlist;
6433 ListCell *l;
6434 int numsortkeys;
6435 AttrNumber *sortColIdx;
6436 Oid *sortOperators;
6437 Oid *collations;
6438 bool *nullsFirst;
6439
6440 /* Convert list-ish representation to arrays wanted by executor */
6442 sortColIdx = (AttrNumber *) palloc(numsortkeys * sizeof(AttrNumber));
6443 sortOperators = (Oid *) palloc(numsortkeys * sizeof(Oid));
6444 collations = (Oid *) palloc(numsortkeys * sizeof(Oid));
6445 nullsFirst = (bool *) palloc(numsortkeys * sizeof(bool));
6446
6447 numsortkeys = 0;
6448 foreach(l, sortcls)
6449 {
6452
6453 sortColIdx[numsortkeys] = tle->resno;
6454 sortOperators[numsortkeys] = sortcl->sortop;
6455 collations[numsortkeys] = exprCollation((Node *) tle->expr);
6456 nullsFirst[numsortkeys] = sortcl->nulls_first;
6457 numsortkeys++;
6458 }
6459
6460 return make_sort(lefttree, numsortkeys,
6461 sortColIdx, sortOperators,
6462 collations, nullsFirst);
6463}

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

5695{
5697 Plan *plan = &node->scan.plan;
5698
5699 plan->targetlist = qptlist;
5700 plan->qual = qpqual;
5701 plan->lefttree = NULL;
5702 plan->righttree = NULL;
5703 node->scan.scanrelid = scanrelid;
5704 node->subplan = subplan;
5706
5707 return node;
5708}
@ 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 5732 of file createplan.c.

5736{
5738 Plan *plan = &node->scan.plan;
5739
5740 plan->targetlist = qptlist;
5741 plan->qual = qpqual;
5742 plan->lefttree = NULL;
5743 plan->righttree = NULL;
5744 node->scan.scanrelid = scanrelid;
5745 node->tablefunc = tablefunc;
5746
5747 return node;
5748}
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 5672 of file createplan.c.

5676{
5678 Plan *plan = &node->scan.plan;
5679
5680 plan->targetlist = qptlist;
5681 plan->qual = qpqual;
5682 plan->lefttree = NULL;
5683 plan->righttree = NULL;
5684 node->scan.scanrelid = scanrelid;
5685 node->tidrangequals = tidrangequals;
5686
5687 return node;
5688}
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 5653 of file createplan.c.

5657{
5658 TidScan *node = makeNode(TidScan);
5659 Plan *plan = &node->scan.plan;
5660
5661 plan->targetlist = qptlist;
5662 plan->qual = qpqual;
5663 plan->lefttree = NULL;
5664 plan->righttree = NULL;
5665 node->scan.scanrelid = scanrelid;
5666 node->tidquals = tidquals;
5667
5668 return node;
5669}
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 6717 of file createplan.c.

6719{
6720 Unique *node = makeNode(Unique);
6721 Plan *plan = &node->plan;
6722 int keyno = 0;
6726 ListCell *lc;
6727
6728 plan->targetlist = lefttree->targetlist;
6729 plan->qual = NIL;
6730 plan->lefttree = lefttree;
6731 plan->righttree = NULL;
6732
6733 /*
6734 * Convert pathkeys list into arrays of attr indexes and equality
6735 * operators, as wanted by executor. This has a lot in common with
6736 * prepare_sort_from_pathkeys ... maybe unify sometime?
6737 */
6738 Assert(numCols >= 0 && numCols <= list_length(pathkeys));
6740 uniqOperators = palloc_array(Oid, numCols);
6741 uniqCollations = palloc_array(Oid, numCols);
6742
6743 foreach(lc, pathkeys)
6744 {
6746 EquivalenceClass *ec = pathkey->pk_eclass;
6748 TargetEntry *tle = NULL;
6750 Oid eqop;
6751 ListCell *j;
6752
6753 /* Ignore pathkeys beyond the specified number of columns */
6754 if (keyno >= numCols)
6755 break;
6756
6757 if (ec->ec_has_volatile)
6758 {
6759 /*
6760 * If the pathkey's EquivalenceClass is volatile, then it must
6761 * have come from an ORDER BY clause, and we have to match it to
6762 * that same targetlist entry.
6763 */
6764 if (ec->ec_sortref == 0) /* can't happen */
6765 elog(ERROR, "volatile EquivalenceClass has no sortref");
6766 tle = get_sortgroupref_tle(ec->ec_sortref, plan->targetlist);
6767 Assert(tle);
6768 Assert(list_length(ec->ec_members) == 1);
6769 pk_datatype = ((EquivalenceMember *) linitial(ec->ec_members))->em_datatype;
6770 }
6771 else
6772 {
6773 /*
6774 * Otherwise, we can use any non-constant expression listed in the
6775 * pathkey's EquivalenceClass. For now, we take the first tlist
6776 * item found in the EC.
6777 */
6778 foreach(j, plan->targetlist)
6779 {
6780 tle = (TargetEntry *) lfirst(j);
6781 em = find_ec_member_matching_expr(ec, tle->expr, relids);
6782 if (em)
6783 {
6784 /* found expr already in tlist */
6785 pk_datatype = em->em_datatype;
6786 break;
6787 }
6788 tle = NULL;
6789 }
6790 }
6791
6792 if (!tle)
6793 elog(ERROR, "could not find pathkey item to sort");
6794
6795 /*
6796 * Look up the correct equality operator from the PathKey's slightly
6797 * abstracted representation.
6798 */
6799 eqop = get_opfamily_member_for_cmptype(pathkey->pk_opfamily,
6802 COMPARE_EQ);
6803 if (!OidIsValid(eqop)) /* should not happen */
6804 elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
6806 pathkey->pk_opfamily);
6807
6808 uniqColIdx[keyno] = tle->resno;
6809 uniqOperators[keyno] = eqop;
6810 uniqCollations[keyno] = ec->ec_collation;
6811
6812 keyno++;
6813 }
6814
6815 node->numCols = numCols;
6816 node->uniqColIdx = uniqColIdx;
6817 node->uniqOperators = uniqOperators;
6818 node->uniqCollations = uniqCollations;
6819
6820 return node;
6821}
@ 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:1332
int numCols
Definition plannodes.h:1335
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 5751 of file createplan.c.

5755{
5757 Plan *plan = &node->scan.plan;
5758
5759 plan->targetlist = qptlist;
5760 plan->qual = qpqual;
5761 plan->lefttree = NULL;
5762 plan->righttree = NULL;
5763 node->scan.scanrelid = scanrelid;
5764 node->values_lists = values_lists;
5765
5766 return node;
5767}
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 6646 of file createplan.c.

6650{
6651 WindowAgg *node = makeNode(WindowAgg);
6652 Plan *plan = &node->plan;
6653
6654 node->winname = wc->name;
6655 node->winref = wc->winref;
6656 node->partNumCols = partNumCols;
6657 node->partColIdx = partColIdx;
6658 node->partOperators = partOperators;
6659 node->partCollations = partCollations;
6660 node->ordNumCols = ordNumCols;
6661 node->ordColIdx = ordColIdx;
6662 node->ordOperators = ordOperators;
6663 node->ordCollations = ordCollations;
6664 node->frameOptions = wc->frameOptions;
6665 node->startOffset = wc->startOffset;
6666 node->endOffset = wc->endOffset;
6667 node->runCondition = runCondition;
6668 /* a duplicate of the above for EXPLAIN */
6669 node->runConditionOrig = runCondition;
6670 node->startInRangeFunc = wc->startInRangeFunc;
6671 node->endInRangeFunc = wc->endInRangeFunc;
6672 node->inRangeColl = wc->inRangeColl;
6673 node->inRangeAsc = wc->inRangeAsc;
6674 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6675 node->topWindow = topWindow;
6676
6677 plan->targetlist = tlist;
6678 plan->lefttree = lefttree;
6679 plan->righttree = NULL;
6680 plan->qual = qual;
6681
6682 return node;
6683}
char * winname
Definition plannodes.h:1258
int partNumCols
Definition plannodes.h:1264
Oid endInRangeFunc
Definition plannodes.h:1308
Node * endOffset
Definition plannodes.h:1294
bool topWindow
Definition plannodes.h:1323
List * runConditionOrig
Definition plannodes.h:1300
Oid inRangeColl
Definition plannodes.h:1311
Node * startOffset
Definition plannodes.h:1291
List * runCondition
Definition plannodes.h:1297
Oid startInRangeFunc
Definition plannodes.h:1305
bool inRangeAsc
Definition plannodes.h:1314
Index winref
Definition plannodes.h:1261
bool inRangeNullsFirst
Definition plannodes.h:1317
int ordNumCols
Definition plannodes.h:1276
int frameOptions
Definition plannodes.h:1288
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 5811 of file createplan.c.

5815{
5817 Plan *plan = &node->scan.plan;
5818
5819 plan->targetlist = qptlist;
5820 plan->qual = qpqual;
5821 plan->lefttree = NULL;
5822 plan->righttree = NULL;
5823 node->scan.scanrelid = scanrelid;
5824 node->wtParam = wtParam;
5825
5826 return node;
5827}

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

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

6543{
6544 Plan *matplan;
6545 Path matpath; /* dummy for cost_material */
6547 bool unsafe_initplans;
6548
6549 matplan = (Plan *) make_material(subplan);
6550
6551 /*
6552 * XXX horrid kluge: if there are any initPlans attached to the subplan,
6553 * move them up to the Material node, which is now effectively the top
6554 * plan node in its query level. This prevents failure in
6555 * SS_finalize_plan(), which see for comments.
6556 */
6557 matplan->initPlan = subplan->initPlan;
6558 subplan->initPlan = NIL;
6559
6560 /* Move the initplans' cost delta, as well */
6563 subplan->startup_cost -= initplan_cost;
6564 subplan->total_cost -= initplan_cost;
6565
6566 /* Set cost data */
6569 subplan->disabled_nodes,
6570 subplan->startup_cost,
6571 subplan->total_cost,
6572 subplan->plan_rows,
6573 subplan->plan_width);
6574 matplan->disabled_nodes = subplan->disabled_nodes;
6575 matplan->startup_cost = matpath.startup_cost + initplan_cost;
6576 matplan->total_cost = matpath.total_cost + initplan_cost;
6577 matplan->plan_rows = subplan->plan_rows;
6578 matplan->plan_width = subplan->plan_width;
6579 matplan->parallel_aware = false;
6580 matplan->parallel_safe = subplan->parallel_safe;
6581
6582 return matplan;
6583}
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:2584
bool enable_material
Definition costsize.c:156
double Cost
Definition nodes.h:259
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:2495

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

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

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

2209{
2210 AttrNumber *grouping_map = root->grouping_map;
2212 ListCell *lc;
2213 int i;
2214
2216
2218
2219 i = 0;
2220 foreach(lc, groupClause)
2221 {
2222 SortGroupClause *clause = lfirst(lc);
2223
2225 }
2226
2227 return new_grpColIdx;
2228}
#define palloc0_array(type, count)
Definition fe_memutils.h:92

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

4917{
4918 if (node == NULL)
4919 return NULL;
4920 if (IsA(node, Var))
4921 {
4922 Var *var = (Var *) node;
4923
4924 /* Upper-level Vars should be long gone at this point */
4925 Assert(var->varlevelsup == 0);
4926 /* If not to be replaced, we can just return the Var unmodified */
4927 if (IS_SPECIAL_VARNO(var->varno) ||
4928 !bms_is_member(var->varno, root->curOuterRels))
4929 return node;
4930 /* Replace the Var with a nestloop Param */
4931 return (Node *) replace_nestloop_param_var(root, var);
4932 }
4933 if (IsA(node, PlaceHolderVar))
4934 {
4935 PlaceHolderVar *phv = (PlaceHolderVar *) node;
4936
4937 /* Upper-level PlaceHolderVars should be long gone at this point */
4938 Assert(phv->phlevelsup == 0);
4939
4940 /* Check whether we need to replace the PHV */
4941 if (!bms_is_subset(find_placeholder_info(root, phv)->ph_eval_at,
4942 root->curOuterRels))
4943 {
4944 /*
4945 * We can't replace the whole PHV, but we might still need to
4946 * replace Vars or PHVs within its expression, in case it ends up
4947 * actually getting evaluated here. (It might get evaluated in
4948 * this plan node, or some child node; in the latter case we don't
4949 * really need to process the expression here, but we haven't got
4950 * enough info to tell if that's the case.) Flat-copy the PHV
4951 * node and then recurse on its expression.
4952 *
4953 * Note that after doing this, we might have different
4954 * representations of the contents of the same PHV in different
4955 * parts of the plan tree. This is OK because equal() will just
4956 * match on phid/phlevelsup, so setrefs.c will still recognize an
4957 * upper-level reference to a lower-level copy of the same PHV.
4958 */
4960
4961 memcpy(newphv, phv, sizeof(PlaceHolderVar));
4962 newphv->phexpr = (Expr *)
4964 root);
4965 return (Node *) newphv;
4966 }
4967 /* Replace the PlaceHolderVar with a nestloop Param */
4969 }
4971}
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 863 of file createplan.c.

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