Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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

Go to the source code of this file.

Macros

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

Functions

static Plancreate_plan_recurse (PlannerInfo *root, Path *best_path, int flags)
 
static Plancreate_scan_plan (PlannerInfo *root, Path *best_path, int flags)
 
static Listbuild_path_tlist (PlannerInfo *root, Path *path)
 
static bool use_physical_tlist (PlannerInfo *root, Path *path, int flags)
 
static Listget_gating_quals (PlannerInfo *root, List *quals)
 
static Plancreate_gating_plan (PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
 
static Plancreate_join_plan (PlannerInfo *root, JoinPath *best_path)
 
static bool mark_async_capable_plan (Plan *plan, Path *path)
 
static Plancreate_append_plan (PlannerInfo *root, AppendPath *best_path, int flags)
 
static Plancreate_merge_append_plan (PlannerInfo *root, MergeAppendPath *best_path, int flags)
 
static Resultcreate_group_result_plan (PlannerInfo *root, GroupResultPath *best_path)
 
static ProjectSetcreate_project_set_plan (PlannerInfo *root, ProjectSetPath *best_path)
 
static Materialcreate_material_plan (PlannerInfo *root, MaterialPath *best_path, int flags)
 
static Memoizecreate_memoize_plan (PlannerInfo *root, MemoizePath *best_path, int flags)
 
static 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, long numGroups)
 
static BitmapAndmake_bitmap_and (List *bitmapplans)
 
static BitmapOrmake_bitmap_or (List *bitmapplans)
 
static NestLoopmake_nestloop (List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static HashJoinmake_hashjoin (List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, List *hashoperators, List *hashcollations, List *hashkeys, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static Hashmake_hash (Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
 
static MergeJoinmake_mergejoin (List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, bool *mergereversals, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, bool skip_mark_restore)
 
static Sortmake_sort (Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static IncrementalSortmake_incrementalsort (Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static Planprepare_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, int *p_numsortkeys, AttrNumber **p_sortColIdx, Oid **p_sortOperators, Oid **p_collations, bool **p_nullsFirst)
 
static Sortmake_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids)
 
static IncrementalSortmake_incrementalsort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
 
static Sortmake_sort_from_groupcols (List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
 
static Materialmake_material (Plan *lefttree)
 
static Memoizemake_memoize (Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids, 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, long 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, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
 
static GatherMergecreate_gather_merge_plan (PlannerInfo *root, GatherMergePath *best_path)
 
Plancreate_plan (PlannerInfo *root, Path *best_path)
 
Planchange_plan_targetlist (Plan *subplan, List *tlist, bool tlist_parallel_safe)
 
static AttrNumberremap_groupColIdx (PlannerInfo *root, List *groupClause)
 
ForeignScanmake_foreignscan (List *qptlist, List *qpqual, Index scanrelid, List *fdw_exprs, List *fdw_private, List *fdw_scan_tlist, List *fdw_recheck_quals, Plan *outer_plan)
 
Sortmake_sort_from_sortclauses (List *sortcls, Plan *lefttree)
 
Planmaterialize_finished_plan (Plan *subplan)
 
Aggmake_agg (List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, List *groupingSets, List *chain, double dNumGroups, Size transitionSpace, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 

Macro Definition Documentation

◆ CP_EXACT_TLIST

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

Definition at line 70 of file createplan.c.

◆ CP_IGNORE_TLIST

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

Definition at line 73 of file createplan.c.

◆ CP_LABEL_TLIST

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

Definition at line 72 of file createplan.c.

◆ CP_SMALL_TLIST

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

Definition at line 71 of file createplan.c.

Function Documentation

◆ bitmap_subplan_mark_shared()

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 5461 of file createplan.c.

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

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

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

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

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

◆ change_plan_targetlist()

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

Definition at line 1992 of file createplan.c.

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

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

Referenced by create_nestloop_plan(), and postgresGetForeignPlan().

◆ copy_generic_path_info()

static void copy_generic_path_info ( Plan dest,
Path src 
)
static

Definition at line 5362 of file createplan.c.

5363{
5364 dest->disabled_nodes = src->disabled_nodes;
5365 dest->startup_cost = src->startup_cost;
5366 dest->total_cost = src->total_cost;
5367 dest->plan_rows = src->rows;
5368 dest->plan_width = src->pathtarget->width;
5369 dest->parallel_aware = src->parallel_aware;
5370 dest->parallel_safe = src->parallel_safe;
5371}
Cardinality rows
Definition: pathnodes.h:1818
Cost startup_cost
Definition: pathnodes.h:1820
int disabled_nodes
Definition: pathnodes.h:1819
Cost total_cost
Definition: pathnodes.h:1821
bool parallel_aware
Definition: pathnodes.h:1811
bool parallel_safe
Definition: pathnodes.h:1813

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

Referenced by create_agg_plan(), create_append_plan(), create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_hashjoin_plan(), create_incrementalsort_plan(), create_indexscan_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_namedtuplestorescan_plan(), create_nestloop_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_resultscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_setop_plan(), create_sort_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidrangescan_plan(), create_tidscan_plan(), create_unique_plan(), create_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 5378 of file createplan.c.

5379{
5380 dest->disabled_nodes = src->disabled_nodes;
5381 dest->startup_cost = src->startup_cost;
5382 dest->total_cost = src->total_cost;
5383 dest->plan_rows = src->plan_rows;
5384 dest->plan_width = src->plan_width;
5385 /* Assume the inserted node is not parallel-aware. */
5386 dest->parallel_aware = false;
5387 /* Assume the inserted node is parallel-safe, if child plan is. */
5388 dest->parallel_safe = src->parallel_safe;
5389}
Cost total_cost
Definition: plannodes.h:190
Cost startup_cost
Definition: plannodes.h:188
int plan_width
Definition: plannodes.h:198
Cardinality plan_rows
Definition: plannodes.h:196
int disabled_nodes
Definition: plannodes.h:186

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

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

◆ create_agg_plan()

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

Definition at line 2156 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_append_plan()

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

Definition at line 1210 of file createplan.c.

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

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(), AppendPath::first_partial_path, inject_projection_plan(), label_incrementalsort_with_costsize(), label_sort_with_costsize(), lappend(), lfirst, AppendPath::limit_tuples, 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, Path::parallel_safe, AppendPath::path, Path::pathkeys, pathkeys_count_contained_in(), plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, replace_nestloop_params(), root, subpath(), and AppendPath::subpaths.

Referenced by create_plan_recurse().

◆ create_bitmap_scan_plan()

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

Definition at line 3048 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_bitmap_subplan()

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

Definition at line 3178 of file createplan.c.

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

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

Referenced by create_bitmap_scan_plan(), 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 3737 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_customscan_plan()

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

Definition at line 4124 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_foreignscan_plan()

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

Definition at line 3969 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_functionscan_plan()

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

Definition at line 3607 of file createplan.c.

3609{
3610 FunctionScan *scan_plan;
3611 Index scan_relid = best_path->parent->relid;
3612 RangeTblEntry *rte;
3613 List *functions;
3614
3615 /* it should be a function base rel... */
3616 Assert(scan_relid > 0);
3617 rte = planner_rt_fetch(scan_relid, root);
3618 Assert(rte->rtekind == RTE_FUNCTION);
3619 functions = rte->functions;
3620
3621 /* Sort clauses into best execution order */
3622 scan_clauses = order_qual_clauses(root, scan_clauses);
3623
3624 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3625 scan_clauses = extract_actual_clauses(scan_clauses, false);
3626
3627 /* Replace any outer-relation variables with nestloop params */
3628 if (best_path->param_info)
3629 {
3630 scan_clauses = (List *)
3631 replace_nestloop_params(root, (Node *) scan_clauses);
3632 /* The function expressions could contain nestloop params, too */
3634 }
3635
3636 scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3638
3639 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3640
3641 return scan_plan;
3642}
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5686
@ RTE_FUNCTION
Definition: parsenodes.h:1045
static const struct fns functions
Definition: regcomp.c:358
bool funcordinality
Definition: parsenodes.h:1209
List * functions
Definition: parsenodes.h:1207

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

Referenced by create_scan_plan().

◆ create_gather_merge_plan()

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

Definition at line 1803 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_gather_plan()

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

Definition at line 1765 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_gating_plan()

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

Definition at line 1016 of file createplan.c.

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

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

Referenced by create_join_plan(), and create_scan_plan().

◆ create_group_plan()

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

Definition at line 2081 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_group_result_plan()

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

Definition at line 1632 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_groupingsets_plan()

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

Definition at line 2240 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_hashjoin_plan()

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

Definition at line 4701 of file createplan.c.

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

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

Referenced by create_join_plan().

◆ create_incrementalsort_plan()

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

Definition at line 2054 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_indexscan_plan()

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

Definition at line 2852 of file createplan.c.

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

References Assert(), BackwardScanDirection, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), elog, ERROR, exprType(), extract_actual_clauses(), fix_indexorderby_references(), fix_indexqual_references(), forboth, ForwardScanDirection, get_opfamily_member_for_cmptype(), i, IndexPath::indexclauses, IndexPath::indexinfo, IndexOptInfo::indexoid, IndexPath::indexorderbys, IndexPath::indexscandir, IndexOptInfo::indextlist, is_redundant_with_indexclauses(), lappend(), lappend_oid(), lfirst, lfirst_node, list_length(), list_make1, make_indexonlyscan(), make_indexscan(), NIL, OidIsValid, order_qual_clauses(), IndexPath::path, Path::pathkeys, PathKey::pk_cmptype, PathKey::pk_opfamily, 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 1075 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_limit_plan()

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

Definition at line 2702 of file createplan.c.

2703{
2704 Limit *plan;
2705 Plan *subplan;
2706 int numUniqkeys = 0;
2707 AttrNumber *uniqColIdx = NULL;
2708 Oid *uniqOperators = NULL;
2709 Oid *uniqCollations = NULL;
2710
2711 /* Limit doesn't project, so tlist requirements pass through */
2712 subplan = create_plan_recurse(root, best_path->subpath, flags);
2713
2714 /* Extract information necessary for comparing rows for WITH TIES. */
2715 if (best_path->limitOption == LIMIT_OPTION_WITH_TIES)
2716 {
2717 Query *parse = root->parse;
2718 ListCell *l;
2719
2720 numUniqkeys = list_length(parse->sortClause);
2721 uniqColIdx = (AttrNumber *) palloc(numUniqkeys * sizeof(AttrNumber));
2722 uniqOperators = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2723 uniqCollations = (Oid *) palloc(numUniqkeys * sizeof(Oid));
2724
2725 numUniqkeys = 0;
2726 foreach(l, parse->sortClause)
2727 {
2728 SortGroupClause *sortcl = (SortGroupClause *) lfirst(l);
2729 TargetEntry *tle = get_sortgroupclause_tle(sortcl, parse->targetList);
2730
2731 uniqColIdx[numUniqkeys] = tle->resno;
2732 uniqOperators[numUniqkeys] = sortcl->eqop;
2733 uniqCollations[numUniqkeys] = exprCollation((Node *) tle->expr);
2734 numUniqkeys++;
2735 }
2736 }
2737
2738 plan = make_limit(subplan,
2739 best_path->limitOffset,
2740 best_path->limitCount,
2741 best_path->limitOption,
2742 numUniqkeys, uniqColIdx, uniqOperators, uniqCollations);
2743
2744 copy_generic_path_info(&plan->plan, (Path *) best_path);
2745
2746 return plan;
2747}
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
Definition: createplan.c:6907
void * palloc(Size size)
Definition: mcxt.c:1365
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:821
@ LIMIT_OPTION_WITH_TIES
Definition: nodes.h:442
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
Path * subpath
Definition: pathnodes.h:2541
LimitOption limitOption
Definition: pathnodes.h:2544
Node * limitOffset
Definition: pathnodes.h:2542
Node * limitCount
Definition: pathnodes.h:2543
Expr * expr
Definition: primnodes.h:2225

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

Referenced by create_plan_recurse().

◆ create_lockrows_plan()

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

Definition at line 2638 of file createplan.c.

2640{
2641 LockRows *plan;
2642 Plan *subplan;
2643
2644 /* LockRows doesn't project, so tlist requirements pass through */
2645 subplan = create_plan_recurse(root, best_path->subpath, flags);
2646
2647 plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2648
2649 copy_generic_path_info(&plan->plan, (Path *) best_path);
2650
2651 return plan;
2652}
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:6886
Path * subpath
Definition: pathnodes.h:2501
List * rowMarks
Definition: pathnodes.h:2502

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

Referenced by create_plan_recurse().

◆ create_material_plan()

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

Definition at line 1683 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_memoize_plan()

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

Definition at line 1711 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_merge_append_plan()

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

Definition at line 1456 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_mergejoin_plan()

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

Definition at line 4347 of file createplan.c.

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

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

Referenced by create_join_plan().

◆ create_minmaxagg_plan()

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

Definition at line 2398 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_modifytable_plan()

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

Definition at line 2661 of file createplan.c.

2662{
2664 Path *subpath = best_path->subpath;
2665 Plan *subplan;
2666
2667 /* Subplan must produce exactly the specified tlist */
2669
2670 /* Transfer resname/resjunk labeling, too, to keep executor happy */
2671 apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2672
2674 subplan,
2675 best_path->operation,
2676 best_path->canSetTag,
2677 best_path->nominalRelation,
2678 best_path->rootRelation,
2679 best_path->partColsUpdated,
2680 best_path->resultRelations,
2681 best_path->updateColnosLists,
2682 best_path->withCheckOptionLists,
2683 best_path->returningLists,
2684 best_path->rowMarks,
2685 best_path->onconflict,
2686 best_path->mergeActionLists,
2687 best_path->mergeJoinConditions,
2688 best_path->epqParam);
2689
2690 copy_generic_path_info(&plan->plan, &best_path->path);
2691
2692 return plan;
2693}
static ModifyTable * make_modifytable(PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
Definition: createplan.c:7010
bool partColsUpdated
Definition: pathnodes.h:2521
List * returningLists
Definition: pathnodes.h:2525
List * resultRelations
Definition: pathnodes.h:2522
List * withCheckOptionLists
Definition: pathnodes.h:2524
List * mergeJoinConditions
Definition: pathnodes.h:2531
List * updateColnosLists
Definition: pathnodes.h:2523
OnConflictExpr * onconflict
Definition: pathnodes.h:2527
CmdType operation
Definition: pathnodes.h:2517
Index rootRelation
Definition: pathnodes.h:2520
Index nominalRelation
Definition: pathnodes.h:2519
List * mergeActionLists
Definition: pathnodes.h:2529
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:318

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

Referenced by create_plan_recurse().

◆ create_namedtuplestorescan_plan()

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

Definition at line 3832 of file createplan.c.

3834{
3835 NamedTuplestoreScan *scan_plan;
3836 Index scan_relid = best_path->parent->relid;
3837 RangeTblEntry *rte;
3838
3839 Assert(scan_relid > 0);
3840 rte = planner_rt_fetch(scan_relid, root);
3842
3843 /* Sort clauses into best execution order */
3844 scan_clauses = order_qual_clauses(root, scan_clauses);
3845
3846 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3847 scan_clauses = extract_actual_clauses(scan_clauses, false);
3848
3849 /* Replace any outer-relation variables with nestloop params */
3850 if (best_path->param_info)
3851 {
3852 scan_clauses = (List *)
3853 replace_nestloop_params(root, (Node *) scan_clauses);
3854 }
3855
3856 scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
3857 rte->enrname);
3858
3859 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3860
3861 return scan_plan;
3862}
static NamedTuplestoreScan * make_namedtuplestorescan(List *qptlist, List *qpqual, Index scanrelid, char *enrname)
Definition: createplan.c:5766
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1049
char * enrname
Definition: parsenodes.h:1261

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

Referenced by create_scan_plan().

◆ create_nestloop_plan()

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

Definition at line 4195 of file createplan.c.

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

References Assert(), bms_free(), bms_union(), build_path_tlist(), castNode, change_plan_targetlist(), copy_generic_path_info(), copyObject, create_plan_recurse(), extract_actual_clauses(), extract_actual_join_clauses(), identify_current_nestloop_params(), JoinPath::inner_unique, JoinPath::innerjoinpath, IS_OUTER_JOIN, is_parallel_safe(), IsA, NestLoop::join, JoinPath::joinrestrictinfo, JoinPath::jointype, NestPath::jpath, lappend(), lfirst, list_copy(), list_length(), make_nestloop(), makeTargetEntry(), NIL, order_qual_clauses(), JoinPath::outerjoinpath, Plan::parallel_safe, NestLoopParam::paramval, 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 341 of file createplan.c.

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

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

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

◆ create_plan_recurse()

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

Definition at line 392 of file createplan.c.

393{
394 Plan *plan;
395
396 /* Guard against stack overflow due to overly complex plans */
398
399 switch (best_path->pathtype)
400 {
401 case T_SeqScan:
402 case T_SampleScan:
403 case T_IndexScan:
404 case T_IndexOnlyScan:
405 case T_BitmapHeapScan:
406 case T_TidScan:
407 case T_TidRangeScan:
408 case T_SubqueryScan:
409 case T_FunctionScan:
410 case T_TableFuncScan:
411 case T_ValuesScan:
412 case T_CteScan:
413 case T_WorkTableScan:
414 case T_NamedTuplestoreScan:
415 case T_ForeignScan:
416 case T_CustomScan:
417 plan = create_scan_plan(root, best_path, flags);
418 break;
419 case T_HashJoin:
420 case T_MergeJoin:
421 case T_NestLoop:
423 (JoinPath *) best_path);
424 break;
425 case T_Append:
427 (AppendPath *) best_path,
428 flags);
429 break;
430 case T_MergeAppend:
432 (MergeAppendPath *) best_path,
433 flags);
434 break;
435 case T_Result:
436 if (IsA(best_path, ProjectionPath))
437 {
439 (ProjectionPath *) best_path,
440 flags);
441 }
442 else if (IsA(best_path, MinMaxAggPath))
443 {
445 (MinMaxAggPath *) best_path);
446 }
447 else if (IsA(best_path, GroupResultPath))
448 {
450 (GroupResultPath *) best_path);
451 }
452 else
453 {
454 /* Simple RTE_RESULT base relation */
455 Assert(IsA(best_path, Path));
456 plan = create_scan_plan(root, best_path, flags);
457 }
458 break;
459 case T_ProjectSet:
461 (ProjectSetPath *) best_path);
462 break;
463 case T_Material:
465 (MaterialPath *) best_path,
466 flags);
467 break;
468 case T_Memoize:
470 (MemoizePath *) best_path,
471 flags);
472 break;
473 case T_Unique:
475 (UniquePath *) best_path,
476 flags);
477 break;
478 case T_Gather:
480 (GatherPath *) best_path);
481 break;
482 case T_Sort:
484 (SortPath *) best_path,
485 flags);
486 break;
487 case T_IncrementalSort:
489 (IncrementalSortPath *) best_path,
490 flags);
491 break;
492 case T_Group:
494 (GroupPath *) best_path);
495 break;
496 case T_Agg:
497 if (IsA(best_path, GroupingSetsPath))
499 (GroupingSetsPath *) best_path);
500 else
501 {
502 Assert(IsA(best_path, AggPath));
504 (AggPath *) best_path);
505 }
506 break;
507 case T_WindowAgg:
509 (WindowAggPath *) best_path);
510 break;
511 case T_SetOp:
513 (SetOpPath *) best_path,
514 flags);
515 break;
516 case T_RecursiveUnion:
518 (RecursiveUnionPath *) best_path);
519 break;
520 case T_LockRows:
522 (LockRowsPath *) best_path,
523 flags);
524 break;
525 case T_ModifyTable:
527 (ModifyTablePath *) best_path);
528 break;
529 case T_Limit:
531 (LimitPath *) best_path,
532 flags);
533 break;
534 case T_GatherMerge:
536 (GatherMergePath *) best_path);
537 break;
538 default:
539 elog(ERROR, "unrecognized node type: %d",
540 (int) best_path->pathtype);
541 plan = NULL; /* keep compiler quiet */
542 break;
543 }
544
545 return plan;
546}
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
Definition: createplan.c:1075
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, int flags)
Definition: createplan.c:1456
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
Definition: createplan.c:1803
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
Definition: createplan.c:1210
static Unique * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
Definition: createplan.c:2120
static Result * create_group_result_plan(PlannerInfo *root, GroupResultPath *best_path)
Definition: createplan.c:1632
static Limit * create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
Definition: createplan.c:2702
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
Definition: createplan.c:2156
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
Definition: createplan.c:2562
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
Definition: createplan.c:2020
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
Definition: createplan.c:1765
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
Definition: createplan.c:1657
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
Definition: createplan.c:2081
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
Definition: createplan.c:2661
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
Definition: createplan.c:2398
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
Definition: createplan.c:2638
static Material * create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
Definition: createplan.c:1683
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:553
static IncrementalSort * create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path, int flags)
Definition: createplan.c:2054
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
Definition: createplan.c:1859
static Memoize * create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
Definition: createplan.c:1711
static WindowAgg * create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
Definition: createplan.c:2467
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
Definition: createplan.c:2240
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
Definition: createplan.c:2602
void check_stack_depth(void)
Definition: stack_depth.c:95
NodeTag pathtype
Definition: pathnodes.h:1784

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, IsA, Path::pathtype, plan, and root.

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

◆ create_project_set_plan()

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

Definition at line 1657 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_projection_plan()

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

Definition at line 1859 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_recursiveunion_plan()

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

Definition at line 2602 of file createplan.c.

2603{
2605 Plan *leftplan;
2606 Plan *rightplan;
2607 List *tlist;
2608 long numGroups;
2609
2610 /* Need both children to produce same tlist, so force it */
2611 leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
2612 rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
2613
2614 tlist = build_path_tlist(root, &best_path->path);
2615
2616 /* Convert numGroups to long int --- but 'ware overflow! */
2617 numGroups = clamp_cardinality_to_long(best_path->numGroups);
2618
2619 plan = make_recursive_union(tlist,
2620 leftplan,
2621 rightplan,
2622 best_path->wtParam,
2623 best_path->distinctList,
2624 numGroups);
2625
2626 copy_generic_path_info(&plan->plan, (Path *) best_path);
2627
2628 return plan;
2629}
long clamp_cardinality_to_long(Cardinality x)
Definition: costsize.c:265
static RecursiveUnion * make_recursive_union(List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, long numGroups)
Definition: createplan.c:5845
Cardinality numGroups
Definition: pathnodes.h:2492

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

Referenced by create_plan_recurse().

◆ create_resultscan_plan()

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

Definition at line 3871 of file createplan.c.

3873{
3874 Result *scan_plan;
3875 Index scan_relid = best_path->parent->relid;
3877
3878 Assert(scan_relid > 0);
3879 rte = planner_rt_fetch(scan_relid, root);
3880 Assert(rte->rtekind == RTE_RESULT);
3881
3882 /* Sort clauses into best execution order */
3883 scan_clauses = order_qual_clauses(root, scan_clauses);
3884
3885 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3886 scan_clauses = extract_actual_clauses(scan_clauses, false);
3887
3888 /* Replace any outer-relation variables with nestloop params */
3889 if (best_path->param_info)
3890 {
3891 scan_clauses = (List *)
3892 replace_nestloop_params(root, (Node *) scan_clauses);
3893 }
3894
3895 scan_plan = make_one_row_result(tlist, (Node *) scan_clauses,
3896 best_path->parent);
3897
3898 copy_generic_path_info(&scan_plan->plan, best_path);
3899
3900 return scan_plan;
3901}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:223
@ RTE_RESULT
Definition: parsenodes.h:1050

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

Referenced by create_scan_plan().

◆ create_samplescan_plan()

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

Definition at line 2801 of file createplan.c.

2803{
2804 SampleScan *scan_plan;
2805 Index scan_relid = best_path->parent->relid;
2806 RangeTblEntry *rte;
2807 TableSampleClause *tsc;
2808
2809 /* it should be a base rel with a tablesample clause... */
2810 Assert(scan_relid > 0);
2811 rte = planner_rt_fetch(scan_relid, root);
2812 Assert(rte->rtekind == RTE_RELATION);
2813 tsc = rte->tablesample;
2814 Assert(tsc != NULL);
2815
2816 /* Sort clauses into best execution order */
2817 scan_clauses = order_qual_clauses(root, scan_clauses);
2818
2819 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2820 scan_clauses = extract_actual_clauses(scan_clauses, false);
2821
2822 /* Replace any outer-relation variables with nestloop params */
2823 if (best_path->param_info)
2824 {
2825 scan_clauses = (List *)
2826 replace_nestloop_params(root, (Node *) scan_clauses);
2827 tsc = (TableSampleClause *)
2829 }
2830
2831 scan_plan = make_samplescan(tlist,
2832 scan_clauses,
2833 scan_relid,
2834 tsc);
2835
2836 copy_generic_path_info(&scan_plan->scan.plan, best_path);
2837
2838 return scan_plan;
2839}
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:5508
struct TableSampleClause * tablesample
Definition: parsenodes.h:1128
Scan scan
Definition: plannodes.h:534

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

Referenced by create_scan_plan().

◆ create_scan_plan()

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

Definition at line 553 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_seqscan_plan()

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

Definition at line 2763 of file createplan.c.

2765{
2766 SeqScan *scan_plan;
2767 Index scan_relid = best_path->parent->relid;
2768
2769 /* it should be a base rel... */
2770 Assert(scan_relid > 0);
2771 Assert(best_path->parent->rtekind == RTE_RELATION);
2772
2773 /* Sort clauses into best execution order */
2774 scan_clauses = order_qual_clauses(root, scan_clauses);
2775
2776 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2777 scan_clauses = extract_actual_clauses(scan_clauses, false);
2778
2779 /* Replace any outer-relation variables with nestloop params */
2780 if (best_path->param_info)
2781 {
2782 scan_clauses = (List *)
2783 replace_nestloop_params(root, (Node *) scan_clauses);
2784 }
2785
2786 scan_plan = make_seqscan(tlist,
2787 scan_clauses,
2788 scan_relid);
2789
2790 copy_generic_path_info(&scan_plan->scan.plan, best_path);
2791
2792 return scan_plan;
2793}
static SeqScan * make_seqscan(List *qptlist, List *qpqual, Index scanrelid)
Definition: createplan.c:5491
Scan scan
Definition: plannodes.h:525

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

Referenced by create_scan_plan().

◆ create_setop_plan()

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

Definition at line 2562 of file createplan.c.

2563{
2564 SetOp *plan;
2565 List *tlist = build_path_tlist(root, &best_path->path);
2566 Plan *leftplan;
2567 Plan *rightplan;
2568 long numGroups;
2569
2570 /*
2571 * SetOp doesn't project, so tlist requirements pass through; moreover we
2572 * need grouping columns to be labeled.
2573 */
2574 leftplan = create_plan_recurse(root, best_path->leftpath,
2575 flags | CP_LABEL_TLIST);
2576 rightplan = create_plan_recurse(root, best_path->rightpath,
2577 flags | CP_LABEL_TLIST);
2578
2579 /* Convert numGroups to long int --- but 'ware overflow! */
2580 numGroups = clamp_cardinality_to_long(best_path->numGroups);
2581
2582 plan = make_setop(best_path->cmd,
2583 best_path->strategy,
2584 tlist,
2585 leftplan,
2586 rightplan,
2587 best_path->groupList,
2588 numGroups);
2589
2590 copy_generic_path_info(&plan->plan, (Path *) best_path);
2591
2592 return plan;
2593}
static SetOp * make_setop(SetOpCmd cmd, SetOpStrategy strategy, List *tlist, Plan *lefttree, Plan *righttree, List *groupList, long numGroups)
Definition: createplan.c:6825
Path * rightpath
Definition: pathnodes.h:2475
Cardinality numGroups
Definition: pathnodes.h:2479
Path * leftpath
Definition: pathnodes.h:2474
SetOpCmd cmd
Definition: pathnodes.h:2476
Path path
Definition: pathnodes.h:2473
SetOpStrategy strategy
Definition: pathnodes.h:2477
List * groupList
Definition: pathnodes.h:2478

References build_path_tlist(), clamp_cardinality_to_long(), SetOpPath::cmd, copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), SetOpPath::groupList, SetOpPath::leftpath, make_setop(), SetOpPath::numGroups, SetOpPath::path, plan, SetOpPath::rightpath, root, and SetOpPath::strategy.

Referenced by create_plan_recurse().

◆ create_sort_plan()

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

Definition at line 2020 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_subqueryscan_plan()

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

Definition at line 3548 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_tablefuncscan_plan()

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

Definition at line 3650 of file createplan.c.

3652{
3653 TableFuncScan *scan_plan;
3654 Index scan_relid = best_path->parent->relid;
3655 RangeTblEntry *rte;
3656 TableFunc *tablefunc;
3657
3658 /* it should be a function base rel... */
3659 Assert(scan_relid > 0);
3660 rte = planner_rt_fetch(scan_relid, root);
3661 Assert(rte->rtekind == RTE_TABLEFUNC);
3662 tablefunc = rte->tablefunc;
3663
3664 /* Sort clauses into best execution order */
3665 scan_clauses = order_qual_clauses(root, scan_clauses);
3666
3667 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3668 scan_clauses = extract_actual_clauses(scan_clauses, false);
3669
3670 /* Replace any outer-relation variables with nestloop params */
3671 if (best_path->param_info)
3672 {
3673 scan_clauses = (List *)
3674 replace_nestloop_params(root, (Node *) scan_clauses);
3675 /* The function expressions could contain nestloop params, too */
3676 tablefunc = (TableFunc *) replace_nestloop_params(root, (Node *) tablefunc);
3677 }
3678
3679 scan_plan = make_tablefuncscan(tlist, scan_clauses, scan_relid,
3680 tablefunc);
3681
3682 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3683
3684 return scan_plan;
3685}
static TableFuncScan * make_tablefuncscan(List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
Definition: createplan.c:5707
@ RTE_TABLEFUNC
Definition: parsenodes.h:1046
TableFunc * tablefunc
Definition: parsenodes.h:1214

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

Referenced by create_scan_plan().

◆ create_tidrangescan_plan()

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

Definition at line 3483 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_tidscan_plan()

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

Definition at line 3386 of file createplan.c.

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

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

Referenced by create_scan_plan().

◆ create_unique_plan()

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

Definition at line 2120 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_valuesscan_plan()

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

Definition at line 3693 of file createplan.c.

3695{
3696 ValuesScan *scan_plan;
3697 Index scan_relid = best_path->parent->relid;
3698 RangeTblEntry *rte;
3699 List *values_lists;
3700
3701 /* it should be a values base rel... */
3702 Assert(scan_relid > 0);
3703 rte = planner_rt_fetch(scan_relid, root);
3704 Assert(rte->rtekind == RTE_VALUES);
3705 values_lists = rte->values_lists;
3706
3707 /* Sort clauses into best execution order */
3708 scan_clauses = order_qual_clauses(root, scan_clauses);
3709
3710 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3711 scan_clauses = extract_actual_clauses(scan_clauses, false);
3712
3713 /* Replace any outer-relation variables with nestloop params */
3714 if (best_path->param_info)
3715 {
3716 scan_clauses = (List *)
3717 replace_nestloop_params(root, (Node *) scan_clauses);
3718 /* The values lists could contain nestloop params, too */
3719 values_lists = (List *)
3720 replace_nestloop_params(root, (Node *) values_lists);
3721 }
3722
3723 scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
3724 values_lists);
3725
3726 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3727
3728 return scan_plan;
3729}
static ValuesScan * make_valuesscan(List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
Definition: createplan.c:5726
@ RTE_VALUES
Definition: parsenodes.h:1047
List * values_lists
Definition: parsenodes.h:1220
Scan scan
Definition: plannodes.h:771

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

Referenced by create_scan_plan().

◆ create_windowagg_plan()

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

Definition at line 2467 of file createplan.c.

2468{
2469 WindowAgg *plan;
2470 WindowClause *wc = best_path->winclause;
2471 int numPart = list_length(wc->partitionClause);
2472 int numOrder = list_length(wc->orderClause);
2473 Plan *subplan;
2474 List *tlist;
2475 int partNumCols;
2476 AttrNumber *partColIdx;
2477 Oid *partOperators;
2478 Oid *partCollations;
2479 int ordNumCols;
2480 AttrNumber *ordColIdx;
2481 Oid *ordOperators;
2482 Oid *ordCollations;
2483 ListCell *lc;
2484
2485 /*
2486 * Choice of tlist here is motivated by the fact that WindowAgg will be
2487 * storing the input rows of window frames in a tuplestore; it therefore
2488 * behooves us to request a small tlist to avoid wasting space. We do of
2489 * course need grouping columns to be available.
2490 */
2491 subplan = create_plan_recurse(root, best_path->subpath,
2493
2494 tlist = build_path_tlist(root, &best_path->path);
2495
2496 /*
2497 * Convert SortGroupClause lists into arrays of attr indexes and equality
2498 * operators, as wanted by executor.
2499 */
2500 partColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numPart);
2501 partOperators = (Oid *) palloc(sizeof(Oid) * numPart);
2502 partCollations = (Oid *) palloc(sizeof(Oid) * numPart);
2503
2504 partNumCols = 0;
2505 foreach(lc, wc->partitionClause)
2506 {
2507 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2508 TargetEntry *tle = get_sortgroupclause_tle(sgc, subplan->targetlist);
2509
2510 Assert(OidIsValid(sgc->eqop));
2511 partColIdx[partNumCols] = tle->resno;
2512 partOperators[partNumCols] = sgc->eqop;
2513 partCollations[partNumCols] = exprCollation((Node *) tle->expr);
2514 partNumCols++;
2515 }
2516
2517 ordColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numOrder);
2518 ordOperators = (Oid *) palloc(sizeof(Oid) * numOrder);
2519 ordCollations = (Oid *) palloc(sizeof(Oid) * numOrder);
2520
2521 ordNumCols = 0;
2522 foreach(lc, wc->orderClause)
2523 {
2524 SortGroupClause *sgc = (SortGroupClause *) lfirst(lc);
2525 TargetEntry *tle = get_sortgroupclause_tle(sgc, subplan->targetlist);
2526
2527 Assert(OidIsValid(sgc->eqop));
2528 ordColIdx[ordNumCols] = tle->resno;
2529 ordOperators[ordNumCols] = sgc->eqop;
2530 ordCollations[ordNumCols] = exprCollation((Node *) tle->expr);
2531 ordNumCols++;
2532 }
2533
2534 /* And finally we can make the WindowAgg node */
2535 plan = make_windowagg(tlist,
2536 wc,
2537 partNumCols,
2538 partColIdx,
2539 partOperators,
2540 partCollations,
2541 ordNumCols,
2542 ordColIdx,
2543 ordOperators,
2544 ordCollations,
2545 best_path->runCondition,
2546 best_path->qual,
2547 best_path->topwindow,
2548 subplan);
2549
2550 copy_generic_path_info(&plan->plan, (Path *) best_path);
2551
2552 return plan;
2553}
static WindowAgg * make_windowagg(List *tlist, WindowClause *wc, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, Oid *partCollations, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, Oid *ordCollations, List *runCondition, List *qual, bool topWindow, Plan *lefttree)
Definition: createplan.c:6618
List * runCondition
Definition: pathnodes.h:2463
Path * subpath
Definition: pathnodes.h:2460
WindowClause * winclause
Definition: pathnodes.h:2461
List * partitionClause
Definition: parsenodes.h:1573
List * orderClause
Definition: parsenodes.h:1575

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

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

3911{
3912 WorkTableScan *scan_plan;
3913 Index scan_relid = best_path->parent->relid;
3914 RangeTblEntry *rte;
3915 Index levelsup;
3916 PlannerInfo *cteroot;
3917
3918 Assert(scan_relid > 0);
3919 rte = planner_rt_fetch(scan_relid, root);
3920 Assert(rte->rtekind == RTE_CTE);
3921 Assert(rte->self_reference);
3922
3923 /*
3924 * We need to find the worktable param ID, which is in the plan level
3925 * that's processing the recursive UNION, which is one level *below* where
3926 * the CTE comes from.
3927 */
3928 levelsup = rte->ctelevelsup;
3929 if (levelsup == 0) /* shouldn't happen */
3930 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3931 levelsup--;
3932 cteroot = root;
3933 while (levelsup-- > 0)
3934 {
3935 cteroot = cteroot->parent_root;
3936 if (!cteroot) /* shouldn't happen */
3937 elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3938 }
3939 if (cteroot->wt_param_id < 0) /* shouldn't happen */
3940 elog(ERROR, "could not find param ID for CTE \"%s\"", rte->ctename);
3941
3942 /* Sort clauses into best execution order */
3943 scan_clauses = order_qual_clauses(root, scan_clauses);
3944
3945 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3946 scan_clauses = extract_actual_clauses(scan_clauses, false);
3947
3948 /* Replace any outer-relation variables with nestloop params */
3949 if (best_path->param_info)
3950 {
3951 scan_clauses = (List *)
3952 replace_nestloop_params(root, (Node *) scan_clauses);
3953 }
3954
3955 scan_plan = make_worktablescan(tlist, scan_clauses, scan_relid,
3956 cteroot->wt_param_id);
3957
3958 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3959
3960 return scan_plan;
3961}
static WorkTableScan * make_worktablescan(List *qptlist, List *qpqual, Index scanrelid, int wtParam)
Definition: createplan.c:5786
int wt_param_id
Definition: pathnodes.h:554

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

Referenced by create_scan_plan().

◆ fix_indexorderby_references()

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

Definition at line 5016 of file createplan.c.

5017{
5018 IndexOptInfo *index = index_path->indexinfo;
5019 List *fixed_indexorderbys;
5020 ListCell *lcc,
5021 *lci;
5022
5023 fixed_indexorderbys = NIL;
5024
5025 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5026 {
5027 Node *clause = (Node *) lfirst(lcc);
5028 int indexcol = lfirst_int(lci);
5029
5030 clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5031 fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5032 }
5033
5034 return fixed_indexorderbys;
5035}
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
Definition: createplan.c:5045
#define lfirst_int(lc)
Definition: pg_list.h:173
List * indexorderbycols
Definition: pathnodes.h:1872
Definition: type.h:96

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

Referenced by create_indexscan_plan().

◆ fix_indexqual_clause()

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

Definition at line 5045 of file createplan.c.

5047{
5048 /*
5049 * Replace any outer-relation variables with nestloop params.
5050 *
5051 * This also makes a copy of the clause, so it's safe to modify it
5052 * in-place below.
5053 */
5054 clause = replace_nestloop_params(root, clause);
5055
5056 if (IsA(clause, OpExpr))
5057 {
5058 OpExpr *op = (OpExpr *) clause;
5059
5060 /* Replace the indexkey expression with an index Var. */
5062 index,
5063 indexcol);
5064 }
5065 else if (IsA(clause, RowCompareExpr))
5066 {
5067 RowCompareExpr *rc = (RowCompareExpr *) clause;
5068 ListCell *lca,
5069 *lcai;
5070
5071 /* Replace the indexkey expressions with index Vars. */
5072 Assert(list_length(rc->largs) == list_length(indexcolnos));
5073 forboth(lca, rc->largs, lcai, indexcolnos)
5074 {
5076 index,
5077 lfirst_int(lcai));
5078 }
5079 }
5080 else if (IsA(clause, ScalarArrayOpExpr))
5081 {
5082 ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) clause;
5083
5084 /* Replace the indexkey expression with an index Var. */
5086 index,
5087 indexcol);
5088 }
5089 else if (IsA(clause, NullTest))
5090 {
5091 NullTest *nt = (NullTest *) clause;
5092
5093 /* Replace the indexkey expression with an index Var. */
5094 nt->arg = (Expr *) fix_indexqual_operand((Node *) nt->arg,
5095 index,
5096 indexcol);
5097 }
5098 else
5099 elog(ERROR, "unsupported indexqual type: %d",
5100 (int) nodeTag(clause));
5101
5102 return clause;
5103}
static Node * fix_indexqual_operand(Node *node, IndexOptInfo *index, int indexcol)
Definition: createplan.c:5116
Datum lca(PG_FUNCTION_ARGS)
Definition: ltree_op.c:571
Expr * arg
Definition: primnodes.h:1969

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

Referenced by fix_indexorderby_references(), and fix_indexqual_references().

◆ fix_indexqual_operand()

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

Definition at line 5116 of file createplan.c.

5117{
5118 Var *result;
5119 int pos;
5120 ListCell *indexpr_item;
5121
5122 /*
5123 * Remove any binary-compatible relabeling of the indexkey
5124 */
5125 if (IsA(node, RelabelType))
5126 node = (Node *) ((RelabelType *) node)->arg;
5127
5128 Assert(indexcol >= 0 && indexcol < index->ncolumns);
5129
5130 if (index->indexkeys[indexcol] != 0)
5131 {
5132 /* It's a simple index column */
5133 if (IsA(node, Var) &&
5134 ((Var *) node)->varno == index->rel->relid &&
5135 ((Var *) node)->varattno == index->indexkeys[indexcol])
5136 {
5137 result = (Var *) copyObject(node);
5138 result->varno = INDEX_VAR;
5139 result->varattno = indexcol + 1;
5140 return (Node *) result;
5141 }
5142 else
5143 elog(ERROR, "index key does not match expected index column");
5144 }
5145
5146 /* It's an index expression, so find and cross-check the expression */
5147 indexpr_item = list_head(index->indexprs);
5148 for (pos = 0; pos < index->ncolumns; pos++)
5149 {
5150 if (index->indexkeys[pos] == 0)
5151 {
5152 if (indexpr_item == NULL)
5153 elog(ERROR, "too few entries in indexprs list");
5154 if (pos == indexcol)
5155 {
5156 Node *indexkey;
5157
5158 indexkey = (Node *) lfirst(indexpr_item);
5159 if (indexkey && IsA(indexkey, RelabelType))
5160 indexkey = (Node *) ((RelabelType *) indexkey)->arg;
5161 if (equal(node, indexkey))
5162 {
5163 result = makeVar(INDEX_VAR, indexcol + 1,
5164 exprType(lfirst(indexpr_item)), -1,
5165 exprCollation(lfirst(indexpr_item)),
5166 0);
5167 return (Node *) result;
5168 }
5169 else
5170 elog(ERROR, "index key does not match expected index column");
5171 }
5172 indexpr_item = lnext(index->indexprs, indexpr_item);
5173 }
5174 }
5175
5176 /* Oops... */
5177 elog(ERROR, "index key does not match expected index column");
5178 return NULL; /* keep compiler quiet */
5179}
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:223
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
void * arg
#define INDEX_VAR
Definition: primnodes.h:244

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

Referenced by fix_indexqual_clause().

◆ fix_indexqual_references()

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

Definition at line 4975 of file createplan.c.

4977{
4978 IndexOptInfo *index = index_path->indexinfo;
4979 List *stripped_indexquals;
4980 List *fixed_indexquals;
4981 ListCell *lc;
4982
4983 stripped_indexquals = fixed_indexquals = NIL;
4984
4985 foreach(lc, index_path->indexclauses)
4986 {
4987 IndexClause *iclause = lfirst_node(IndexClause, lc);
4988 int indexcol = iclause->indexcol;
4989 ListCell *lc2;
4990
4991 foreach(lc2, iclause->indexquals)
4992 {
4993 RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
4994 Node *clause = (Node *) rinfo->clause;
4995
4996 stripped_indexquals = lappend(stripped_indexquals, clause);
4997 clause = fix_indexqual_clause(root, index, indexcol,
4998 clause, iclause->indexcols);
4999 fixed_indexquals = lappend(fixed_indexquals, clause);
5000 }
5001 }
5002
5003 *stripped_indexquals_p = stripped_indexquals;
5004 *fixed_indexquals_p = fixed_indexquals;
5005}
AttrNumber indexcol
Definition: pathnodes.h:1920
List * indexcols
Definition: pathnodes.h:1921

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

Referenced by create_indexscan_plan().

◆ get_gating_quals()

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

Definition at line 996 of file createplan.c.

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

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

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

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

Referenced by create_hashjoin_plan(), and create_mergejoin_plan().

◆ inject_projection_plan()

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

Definition at line 1960 of file createplan.c.

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

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

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

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

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

◆ is_projection_capable_plan()

bool is_projection_capable_plan ( Plan plan)

Definition at line 7283 of file createplan.c.

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

References CUSTOMPATH_SUPPORT_PROJECTION, nodeTag, and plan.

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

◆ label_incrementalsort_with_costsize()

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

Definition at line 5429 of file createplan.c.

5431{
5432 Plan *lefttree = plan->sort.plan.lefttree;
5433 Path sort_path; /* dummy for result of cost_incremental_sort */
5434
5436
5437 cost_incremental_sort(&sort_path, root, pathkeys,
5438 plan->nPresortedCols,
5439 plan->sort.plan.disabled_nodes,
5440 lefttree->startup_cost,
5441 lefttree->total_cost,
5442 lefttree->plan_rows,
5443 lefttree->plan_width,
5444 0.0,
5445 work_mem,
5446 limit_tuples);
5447 plan->sort.plan.startup_cost = sort_path.startup_cost;
5448 plan->sort.plan.total_cost = sort_path.total_cost;
5449 plan->sort.plan.plan_rows = lefttree->plan_rows;
5450 plan->sort.plan.plan_width = lefttree->plan_width;
5451 plan->sort.plan.parallel_aware = false;
5452 plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5453}
void cost_incremental_sort(Path *path, PlannerInfo *root, List *pathkeys, int presorted_keys, int input_disabled_nodes, Cost input_startup_cost, Cost input_total_cost, double input_tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2000
int work_mem
Definition: globals.c:131

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

Referenced by create_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 5401 of file createplan.c.

5402{
5403 Plan *lefttree = plan->plan.lefttree;
5404 Path sort_path; /* dummy for result of cost_sort */
5405
5406 Assert(IsA(plan, Sort));
5407
5408 cost_sort(&sort_path, root, NIL,
5409 plan->plan.disabled_nodes,
5410 lefttree->total_cost,
5411 lefttree->plan_rows,
5412 lefttree->plan_width,
5413 0.0,
5414 work_mem,
5415 limit_tuples);
5416 plan->plan.startup_cost = sort_path.startup_cost;
5417 plan->plan.total_cost = sort_path.total_cost;
5418 plan->plan.plan_rows = lefttree->plan_rows;
5419 plan->plan.plan_width = lefttree->plan_width;
5420 plan->plan.parallel_aware = false;
5421 plan->plan.parallel_safe = lefttree->parallel_safe;
5422}
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, int input_disabled_nodes, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:2144

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

Referenced by create_append_plan(), create_merge_append_plan(), 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,
double  dNumGroups,
Size  transitionSpace,
Plan lefttree 
)

Definition at line 6584 of file createplan.c.

6589{
6590 Agg *node = makeNode(Agg);
6591 Plan *plan = &node->plan;
6592 long numGroups;
6593
6594 /* Reduce to long, but 'ware overflow! */
6595 numGroups = clamp_cardinality_to_long(dNumGroups);
6596
6597 node->aggstrategy = aggstrategy;
6598 node->aggsplit = aggsplit;
6599 node->numCols = numGroupCols;
6600 node->grpColIdx = grpColIdx;
6601 node->grpOperators = grpOperators;
6602 node->grpCollations = grpCollations;
6603 node->numGroups = numGroups;
6604 node->transitionSpace = transitionSpace;
6605 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6606 node->groupingSets = groupingSets;
6607 node->chain = chain;
6608
6609 plan->qual = qual;
6610 plan->targetlist = tlist;
6611 plan->lefttree = lefttree;
6612 plan->righttree = NULL;
6613
6614 return node;
6615}
AggSplit aggsplit
Definition: plannodes.h:1189
List * chain
Definition: plannodes.h:1216
long numGroups
Definition: plannodes.h:1202
List * groupingSets
Definition: plannodes.h:1213
Bitmapset * aggParams
Definition: plannodes.h:1208
Plan plan
Definition: plannodes.h:1183
int numCols
Definition: plannodes.h:1192
uint64 transitionSpace
Definition: plannodes.h:1205
AggStrategy aggstrategy
Definition: plannodes.h:1186

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

Referenced by create_agg_plan(), and create_groupingsets_plan().

◆ make_bitmap_and()

static BitmapAnd * make_bitmap_and ( List bitmapplans)
static

Definition at line 5901 of file createplan.c.

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

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

Referenced by create_bitmap_subplan().

◆ make_bitmap_heapscan()

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

Definition at line 5608 of file createplan.c.

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

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

Referenced by create_bitmap_scan_plan().

◆ make_bitmap_indexscan()

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

Definition at line 5587 of file createplan.c.

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

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

Referenced by create_bitmap_subplan().

◆ make_bitmap_or()

static BitmapOr * make_bitmap_or ( List bitmapplans)
static

Definition at line 5916 of file createplan.c.

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

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

Referenced by create_bitmap_subplan().

◆ make_ctescan()

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

Definition at line 5745 of file createplan.c.

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

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

Referenced by create_ctescan_plan().

◆ make_foreignscan()

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

Definition at line 5805 of file createplan.c.

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

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

Referenced by fileGetForeignPlan(), and postgresGetForeignPlan().

◆ make_functionscan()

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

Definition at line 5686 of file createplan.c.

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

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

Referenced by create_functionscan_plan().

◆ make_gather()

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

Definition at line 6796 of file createplan.c.

6802{
6803 Gather *node = makeNode(Gather);
6804 Plan *plan = &node->plan;
6805
6806 plan->targetlist = qptlist;
6807 plan->qual = qpqual;
6808 plan->lefttree = subplan;
6809 plan->righttree = NULL;
6810 node->num_workers = nworkers;
6811 node->rescan_param = rescan_param;
6812 node->single_copy = single_copy;
6813 node->invisible = false;
6814 node->initParam = NULL;
6815
6816 return node;
6817}
int num_workers
Definition: plannodes.h:1332
bool invisible
Definition: plannodes.h:1338
Bitmapset * initParam
Definition: plannodes.h:1344
bool single_copy
Definition: plannodes.h:1336
int rescan_param
Definition: plannodes.h:1334

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

Referenced by create_gather_plan().

◆ make_gating_result()

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

Definition at line 6936 of file createplan.c.

6939{
6940 Result *node = makeNode(Result);
6941 Plan *plan = &node->plan;
6942
6943 Assert(subplan != NULL);
6944
6945 plan->targetlist = tlist;
6946 plan->qual = NIL;
6947 plan->lefttree = subplan;
6948 plan->righttree = NULL;
6950 node->resconstantqual = resconstantqual;
6951 node->relids = NULL;
6952
6953 return node;
6954}
@ RESULT_TYPE_GATING
Definition: plannodes.h:262
Node * resconstantqual
Definition: plannodes.h:290

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

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

6665{
6666 Group *node = makeNode(Group);
6667 Plan *plan = &node->plan;
6668
6669 node->numCols = numGroupCols;
6670 node->grpColIdx = grpColIdx;
6671 node->grpOperators = grpOperators;
6672 node->grpCollations = grpCollations;
6673
6674 plan->qual = qual;
6675 plan->targetlist = tlist;
6676 plan->lefttree = lefttree;
6677 plan->righttree = NULL;
6678
6679 return node;
6680}
int numCols
Definition: plannodes.h:1157
Plan plan
Definition: plannodes.h:1154

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

Referenced by create_group_plan().

◆ make_hash()

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

Definition at line 5987 of file createplan.c.

5992{
5993 Hash *node = makeNode(Hash);
5994 Plan *plan = &node->plan;
5995
5996 plan->targetlist = lefttree->targetlist;
5997 plan->qual = NIL;
5998 plan->lefttree = lefttree;
5999 plan->righttree = NULL;
6000
6001 node->hashkeys = hashkeys;
6002 node->skewTable = skewTable;
6003 node->skewColumn = skewColumn;
6004 node->skewInherit = skewInherit;
6005
6006 return node;
6007}
AttrNumber skewColumn
Definition: plannodes.h:1406
List * hashkeys
Definition: plannodes.h:1402
Oid skewTable
Definition: plannodes.h:1404
bool skewInherit
Definition: plannodes.h:1408

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

Referenced by create_hashjoin_plan().

◆ make_hashjoin()

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

Definition at line 5956 of file createplan.c.

5967{
5968 HashJoin *node = makeNode(HashJoin);
5969 Plan *plan = &node->join.plan;
5970
5971 plan->targetlist = tlist;
5972 plan->qual = otherclauses;
5973 plan->lefttree = lefttree;
5974 plan->righttree = righttree;
5975 node->hashclauses = hashclauses;
5976 node->hashoperators = hashoperators;
5977 node->hashcollations = hashcollations;
5978 node->hashkeys = hashkeys;
5979 node->join.jointype = jointype;
5980 node->join.inner_unique = inner_unique;
5981 node->join.joinqual = joinclauses;
5982
5983 return node;
5984}
List * hashcollations
Definition: plannodes.h:1041
List * hashclauses
Definition: plannodes.h:1039
List * hashoperators
Definition: plannodes.h:1040
List * hashkeys
Definition: plannodes.h:1047
List * joinqual
Definition: plannodes.h:964
JoinType jointype
Definition: plannodes.h:961
bool inner_unique
Definition: plannodes.h:962

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

Referenced by create_hashjoin_plan().

◆ make_incrementalsort()

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

Definition at line 6082 of file createplan.c.

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

References makeNode, NIL, IncrementalSort::nPresortedCols, Sort::numCols, Sort::plan, plan, 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 6365 of file createplan.c.

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

References make_incrementalsort(), and prepare_sort_from_pathkeys().

Referenced by create_incrementalsort_plan(), and create_mergejoin_plan().

◆ make_indexonlyscan()

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

Definition at line 5558 of file createplan.c.

5567{
5569 Plan *plan = &node->scan.plan;
5570
5571 plan->targetlist = qptlist;
5572 plan->qual = qpqual;
5573 plan->lefttree = NULL;
5574 plan->righttree = NULL;
5575 node->scan.scanrelid = scanrelid;
5576 node->indexid = indexid;
5577 node->indexqual = indexqual;
5578 node->recheckqual = recheckqual;
5579 node->indexorderby = indexorderby;
5580 node->indextlist = indextlist;
5581 node->indexorderdir = indexscandir;
5582
5583 return node;
5584}
List * indexqual
Definition: plannodes.h:632
List * recheckqual
Definition: plannodes.h:634
List * indextlist
Definition: plannodes.h:638
ScanDirection indexorderdir
Definition: plannodes.h:640
List * indexorderby
Definition: plannodes.h:636

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

Referenced by create_indexscan_plan().

◆ make_indexscan()

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

Definition at line 5527 of file createplan.c.

5537{
5538 IndexScan *node = makeNode(IndexScan);
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->indexid = indexid;
5547 node->indexqual = indexqual;
5548 node->indexqualorig = indexqualorig;
5549 node->indexorderby = indexorderby;
5550 node->indexorderbyorig = indexorderbyorig;
5551 node->indexorderbyops = indexorderbyops;
5552 node->indexorderdir = indexscandir;
5553
5554 return node;
5555}
List * indexorderby
Definition: plannodes.h:586
List * indexorderbyops
Definition: plannodes.h:590
ScanDirection indexorderdir
Definition: plannodes.h:592
List * indexorderbyorig
Definition: plannodes.h:588

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

Referenced by create_indexscan_plan().

◆ make_limit()

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

Definition at line 6907 of file createplan.c.

6910{
6911 Limit *node = makeNode(Limit);
6912 Plan *plan = &node->plan;
6913
6914 plan->targetlist = lefttree->targetlist;
6915 plan->qual = NIL;
6916 plan->lefttree = lefttree;
6917 plan->righttree = NULL;
6918
6919 node->limitOffset = limitOffset;
6920 node->limitCount = limitCount;
6921 node->limitOption = limitOption;
6922 node->uniqNumCols = uniqNumCols;
6923 node->uniqColIdx = uniqColIdx;
6924 node->uniqOperators = uniqOperators;
6925 node->uniqCollations = uniqCollations;
6926
6927 return node;
6928}
LimitOption limitOption
Definition: plannodes.h:1481
Plan plan
Definition: plannodes.h:1472
Node * limitCount
Definition: plannodes.h:1478
int uniqNumCols
Definition: plannodes.h:1484
Node * limitOffset
Definition: plannodes.h:1475

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

Referenced by create_limit_plan(), and create_minmaxagg_plan().

◆ make_lockrows()

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

Definition at line 6886 of file createplan.c.

6887{
6888 LockRows *node = makeNode(LockRows);
6889 Plan *plan = &node->plan;
6890
6891 plan->targetlist = lefttree->targetlist;
6892 plan->qual = NIL;
6893 plan->lefttree = lefttree;
6894 plan->righttree = NULL;
6895
6896 node->rowMarks = rowMarks;
6897 node->epqParam = epqParam;
6898
6899 return node;
6900}
int epqParam
Definition: plannodes.h:1460
List * rowMarks
Definition: plannodes.h:1458
Plan plan
Definition: plannodes.h:1456

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

Referenced by create_lockrows_plan().

◆ make_material()

static Material * make_material ( Plan lefttree)
static

Definition at line 6489 of file createplan.c.

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

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

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

◆ make_memoize()

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

Definition at line 6554 of file createplan.c.

6559{
6560 Memoize *node = makeNode(Memoize);
6561 Plan *plan = &node->plan;
6562
6563 plan->targetlist = lefttree->targetlist;
6564 plan->qual = NIL;
6565 plan->lefttree = lefttree;
6566 plan->righttree = NULL;
6567
6568 node->numKeys = list_length(param_exprs);
6569 node->hashOperators = hashoperators;
6570 node->collations = collations;
6571 node->param_exprs = param_exprs;
6572 node->singlerow = singlerow;
6573 node->binary_mode = binary_mode;
6574 node->est_entries = est_entries;
6575 node->keyparamids = keyparamids;
6576 node->est_calls = est_calls;
6577 node->est_unique_keys = est_unique_keys;
6578 node->est_hit_ratio = est_hit_ratio;
6579
6580 return node;
6581}
Plan plan
Definition: plannodes.h:1065
bool singlerow
Definition: plannodes.h:1083
Cardinality est_calls
Definition: plannodes.h:1101
Bitmapset * keyparamids
Definition: plannodes.h:1098
bool binary_mode
Definition: plannodes.h:1089
int numKeys
Definition: plannodes.h:1068
Cardinality est_unique_keys
Definition: plannodes.h:1104
List * param_exprs
Definition: plannodes.h:1077
double est_hit_ratio
Definition: plannodes.h:1107
uint32 est_entries
Definition: plannodes.h:1095

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

Referenced by create_memoize_plan().

◆ make_mergejoin()

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

Definition at line 6010 of file createplan.c.

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

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

Referenced by create_mergejoin_plan().

◆ make_modifytable()

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

Definition at line 7010 of file createplan.c.

7020{
7022 bool returning_old_or_new = false;
7023 bool returning_old_or_new_valid = false;
7024 bool transition_tables = false;
7025 bool transition_tables_valid = false;
7026 List *fdw_private_list;
7027 Bitmapset *direct_modify_plans;
7028 ListCell *lc;
7029 int i;
7030
7031 Assert(operation == CMD_MERGE ||
7032 (operation == CMD_UPDATE ?
7033 list_length(resultRelations) == list_length(updateColnosLists) :
7034 updateColnosLists == NIL));
7035 Assert(withCheckOptionLists == NIL ||
7036 list_length(resultRelations) == list_length(withCheckOptionLists));
7037 Assert(returningLists == NIL ||
7038 list_length(resultRelations) == list_length(returningLists));
7039
7040 node->plan.lefttree = subplan;
7041 node->plan.righttree = NULL;
7042 node->plan.qual = NIL;
7043 /* setrefs.c will fill in the targetlist, if needed */
7044 node->plan.targetlist = NIL;
7045
7046 node->operation = operation;
7047 node->canSetTag = canSetTag;
7048 node->nominalRelation = nominalRelation;
7049 node->rootRelation = rootRelation;
7050 node->partColsUpdated = partColsUpdated;
7051 node->resultRelations = resultRelations;
7052 if (!onconflict)
7053 {
7055 node->onConflictSet = NIL;
7056 node->onConflictCols = NIL;
7057 node->onConflictWhere = NULL;
7058 node->arbiterIndexes = NIL;
7059 node->exclRelRTI = 0;
7060 node->exclRelTlist = NIL;
7061 }
7062 else
7063 {
7064 node->onConflictAction = onconflict->action;
7065
7066 /*
7067 * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7068 * executor's convention of having consecutive resno's. The actual
7069 * target column numbers are saved in node->onConflictCols. (This
7070 * could be done earlier, but there seems no need to.)
7071 */
7072 node->onConflictSet = onconflict->onConflictSet;
7073 node->onConflictCols =
7075 node->onConflictWhere = onconflict->onConflictWhere;
7076
7077 /*
7078 * If a set of unique index inference elements was provided (an
7079 * INSERT...ON CONFLICT "inference specification"), then infer
7080 * appropriate unique indexes (or throw an error if none are
7081 * available).
7082 */
7084
7085 node->exclRelRTI = onconflict->exclRelIndex;
7086 node->exclRelTlist = onconflict->exclRelTlist;
7087 }
7088 node->updateColnosLists = updateColnosLists;
7089 node->withCheckOptionLists = withCheckOptionLists;
7090 node->returningOldAlias = root->parse->returningOldAlias;
7091 node->returningNewAlias = root->parse->returningNewAlias;
7092 node->returningLists = returningLists;
7093 node->rowMarks = rowMarks;
7094 node->mergeActionLists = mergeActionLists;
7095 node->mergeJoinConditions = mergeJoinConditions;
7096 node->epqParam = epqParam;
7097
7098 /*
7099 * For each result relation that is a foreign table, allow the FDW to
7100 * construct private plan data, and accumulate it all into a list.
7101 */
7102 fdw_private_list = NIL;
7103 direct_modify_plans = NULL;
7104 i = 0;
7105 foreach(lc, resultRelations)
7106 {
7107 Index rti = lfirst_int(lc);
7108 FdwRoutine *fdwroutine;
7109 List *fdw_private;
7110 bool direct_modify;
7111
7112 /*
7113 * If possible, we want to get the FdwRoutine from our RelOptInfo for
7114 * the table. But sometimes we don't have a RelOptInfo and must get
7115 * it the hard way. (In INSERT, the target relation is not scanned,
7116 * so it's not a baserel; and there are also corner cases for
7117 * updatable views where the target rel isn't a baserel.)
7118 */
7119 if (rti < root->simple_rel_array_size &&
7120 root->simple_rel_array[rti] != NULL)
7121 {
7122 RelOptInfo *resultRel = root->simple_rel_array[rti];
7123
7124 fdwroutine = resultRel->fdwroutine;
7125 }
7126 else
7127 {
7128 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7129
7130 if (rte->rtekind == RTE_RELATION &&
7131 rte->relkind == RELKIND_FOREIGN_TABLE)
7132 {
7133 /* Check if the access to foreign tables is restricted */
7135 {
7136 /* there must not be built-in foreign tables */
7137 Assert(rte->relid >= FirstNormalObjectId);
7138 ereport(ERROR,
7139 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7140 errmsg("access to non-system foreign table is restricted")));
7141 }
7142
7143 fdwroutine = GetFdwRoutineByRelId(rte->relid);
7144 }
7145 else
7146 fdwroutine = NULL;
7147 }
7148
7149 /*
7150 * MERGE is not currently supported for foreign tables. We already
7151 * checked that when the table mentioned in the query is foreign; but
7152 * we can still get here if a partitioned table has a foreign table as
7153 * partition. Disallow that now, to avoid an uglier error message
7154 * later.
7155 */
7156 if (operation == CMD_MERGE && fdwroutine != NULL)
7157 {
7158 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7159
7160 ereport(ERROR,
7161 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7162 errmsg("cannot execute MERGE on relation \"%s\"",
7163 get_rel_name(rte->relid)),
7164 errdetail_relkind_not_supported(rte->relkind));
7165 }
7166
7167 /*
7168 * Try to modify the foreign table directly if (1) the FDW provides
7169 * callback functions needed for that and (2) there are no local
7170 * structures that need to be run for each modified row: row-level
7171 * triggers on the foreign table, stored generated columns, WITH CHECK
7172 * OPTIONs from parent views, Vars returning OLD/NEW in the RETURNING
7173 * list, or transition tables on the named relation.
7174 */
7175 direct_modify = false;
7176 if (fdwroutine != NULL &&
7177 fdwroutine->PlanDirectModify != NULL &&
7178 fdwroutine->BeginDirectModify != NULL &&
7179 fdwroutine->IterateDirectModify != NULL &&
7180 fdwroutine->EndDirectModify != NULL &&
7181 withCheckOptionLists == NIL &&
7182 !has_row_triggers(root, rti, operation) &&
7184 {
7185 /*
7186 * returning_old_or_new and transition_tables are the same for all
7187 * result relations, respectively
7188 */
7189 if (!returning_old_or_new_valid)
7190 {
7191 returning_old_or_new =
7193 root->parse->returningList);
7194 returning_old_or_new_valid = true;
7195 }
7196 if (!returning_old_or_new)
7197 {
7198 if (!transition_tables_valid)
7199 {
7200 transition_tables = has_transition_tables(root,
7201 nominalRelation,
7202 operation);
7203 transition_tables_valid = true;
7204 }
7205 if (!transition_tables)
7206 direct_modify = fdwroutine->PlanDirectModify(root, node,
7207 rti, i);
7208 }
7209 }
7210 if (direct_modify)
7211 direct_modify_plans = bms_add_member(direct_modify_plans, i);
7212
7213 if (!direct_modify &&
7214 fdwroutine != NULL &&
7215 fdwroutine->PlanForeignModify != NULL)
7216 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7217 else
7218 fdw_private = NIL;
7219 fdw_private_list = lappend(fdw_private_list, fdw_private);
7220 i++;
7221 }
7222 node->fdwPrivLists = fdw_private_list;
7223 node->fdwDirectModifyPlans = direct_modify_plans;
7224
7225 return node;
7226}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define unlikely(x)
Definition: c.h:403
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:150
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:420
char * get_rel_name(Oid relid)
Definition: lsyscache.c:2095
@ ONCONFLICT_NONE
Definition: nodes.h:428
@ CMD_MERGE
Definition: nodes.h:279
@ CMD_UPDATE
Definition: nodes.h:276
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
bool has_stored_generated_columns(PlannerInfo *root, Index rti)
Definition: plancat.c:2461
bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
Definition: plancat.c:2357
bool has_transition_tables(PlannerInfo *root, Index rti, CmdType event)
Definition: plancat.c:2407
List * infer_arbiter_indexes(PlannerInfo *root)
Definition: plancat.c:794
int restrict_nonsystem_relation_kind
Definition: postgres.c:105
List * extract_update_targetlist_colnos(List *tlist)
Definition: preptlist.c:348
BeginDirectModify_function BeginDirectModify
Definition: fdwapi.h:242
PlanForeignModify_function PlanForeignModify
Definition: fdwapi.h:230
PlanDirectModify_function PlanDirectModify
Definition: fdwapi.h:241
IterateDirectModify_function IterateDirectModify
Definition: fdwapi.h:243
EndDirectModify_function EndDirectModify
Definition: fdwapi.h:244
List * updateColnosLists
Definition: plannodes.h:337
Index nominalRelation
Definition: plannodes.h:329
List * arbiterIndexes
Definition: plannodes.h:357
List * onConflictCols
Definition: plannodes.h:361
List * mergeJoinConditions
Definition: plannodes.h:371
char * returningOldAlias
Definition: plannodes.h:341
char * returningNewAlias
Definition: plannodes.h:343
CmdType operation
Definition: plannodes.h:325
int epqParam
Definition: plannodes.h:353
List * resultRelations
Definition: plannodes.h:335
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:349
List * onConflictSet
Definition: plannodes.h:359
List * exclRelTlist
Definition: plannodes.h:367
List * mergeActionLists
Definition: plannodes.h:369
bool canSetTag
Definition: plannodes.h:327
List * fdwPrivLists
Definition: plannodes.h:347
bool partColsUpdated
Definition: plannodes.h:333
List * returningLists
Definition: plannodes.h:345
List * withCheckOptionLists
Definition: plannodes.h:339
Index rootRelation
Definition: plannodes.h:331
Node * onConflictWhere
Definition: plannodes.h:363
List * rowMarks
Definition: plannodes.h:351
OnConflictAction onConflictAction
Definition: plannodes.h:355
Index exclRelRTI
Definition: plannodes.h:365
OnConflictAction action
Definition: primnodes.h:2359
List * onConflictSet
Definition: primnodes.h:2368
List * exclRelTlist
Definition: primnodes.h:2371
Node * onConflictWhere
Definition: primnodes.h:2369
struct Plan * righttree
Definition: plannodes.h:225
List * qual
Definition: plannodes.h:222
#define RESTRICT_RELKIND_FOREIGN_TABLE
Definition: tcopprot.h:44
#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(), ModifyTable::fdwDirectModifyPlans, ModifyTable::fdwPrivLists, FirstNormalObjectId, get_rel_name(), GetFdwRoutineByRelId(), has_row_triggers(), has_stored_generated_columns(), has_transition_tables(), i, infer_arbiter_indexes(), FdwRoutine::IterateDirectModify, lappend(), Plan::lefttree, lfirst_int, list_length(), makeNode, ModifyTable::mergeActionLists, ModifyTable::mergeJoinConditions, NIL, ModifyTable::nominalRelation, ONCONFLICT_NONE, ModifyTable::onConflictAction, ModifyTable::onConflictCols, ModifyTable::onConflictSet, OnConflictExpr::onConflictSet, ModifyTable::onConflictWhere, OnConflictExpr::onConflictWhere, ModifyTable::operation, ModifyTable::partColsUpdated, ModifyTable::plan, FdwRoutine::PlanDirectModify, FdwRoutine::PlanForeignModify, planner_rt_fetch, Plan::qual, 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, RangeTblEntry::rtekind, Plan::targetlist, unlikely, ModifyTable::updateColnosLists, and ModifyTable::withCheckOptionLists.

Referenced by create_modifytable_plan().

◆ make_namedtuplestorescan()

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

Definition at line 5766 of file createplan.c.

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

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

Referenced by create_namedtuplestorescan_plan().

◆ make_nestloop()

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

Definition at line 5931 of file createplan.c.

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

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

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

6970{
6971 Result *node = makeNode(Result);
6972 Plan *plan = &node->plan;
6973
6974 plan->targetlist = tlist;
6975 plan->qual = NIL;
6976 plan->lefttree = NULL;
6977 plan->righttree = NULL;
6980 node->resconstantqual = resconstantqual;
6981 node->relids = rel->relids;
6982
6983 return node;
6984}
#define IS_UPPER_REL(rel)
Definition: pathnodes.h:886
@ RESULT_TYPE_UPPER
Definition: plannodes.h:265
@ RESULT_TYPE_SCAN
Definition: plannodes.h:263
@ RESULT_TYPE_JOIN
Definition: plannodes.h:264

References 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, and RESULT_TYPE_UPPER.

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

6993{
6995 Plan *plan = &node->plan;
6996
6997 plan->targetlist = tlist;
6998 plan->qual = NIL;
6999 plan->lefttree = subplan;
7000 plan->righttree = NULL;
7001
7002 return node;
7003}
Plan plan
Definition: plannodes.h:302

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

Referenced by create_project_set_plan().

◆ make_recursive_union()

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

Definition at line 5845 of file createplan.c.

5851{
5853 Plan *plan = &node->plan;
5854 int numCols = list_length(distinctList);
5855
5856 plan->targetlist = tlist;
5857 plan->qual = NIL;
5858 plan->lefttree = lefttree;
5859 plan->righttree = righttree;
5860 node->wtParam = wtParam;
5861
5862 /*
5863 * convert SortGroupClause list into arrays of attr indexes and equality
5864 * operators, as wanted by executor
5865 */
5866 node->numCols = numCols;
5867 if (numCols > 0)
5868 {
5869 int keyno = 0;
5870 AttrNumber *dupColIdx;
5871 Oid *dupOperators;
5872 Oid *dupCollations;
5873 ListCell *slitem;
5874
5875 dupColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
5876 dupOperators = (Oid *) palloc(sizeof(Oid) * numCols);
5877 dupCollations = (Oid *) palloc(sizeof(Oid) * numCols);
5878
5879 foreach(slitem, distinctList)
5880 {
5881 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
5883 plan->targetlist);
5884
5885 dupColIdx[keyno] = tle->resno;
5886 dupOperators[keyno] = sortcl->eqop;
5887 dupCollations[keyno] = exprCollation((Node *) tle->expr);
5888 Assert(OidIsValid(dupOperators[keyno]));
5889 keyno++;
5890 }
5891 node->dupColIdx = dupColIdx;
5892 node->dupOperators = dupOperators;
5893 node->dupCollations = dupCollations;
5894 }
5895 node->numGroups = numGroups;
5896
5897 return node;
5898}

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

Referenced by create_recursiveunion_plan().

◆ make_samplescan()

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

Definition at line 5508 of file createplan.c.

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

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

Referenced by create_samplescan_plan().

◆ make_seqscan()

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

Definition at line 5491 of file createplan.c.

5494{
5495 SeqScan *node = makeNode(SeqScan);
5496 Plan *plan = &node->scan.plan;
5497
5498 plan->targetlist = qptlist;
5499 plan->qual = qpqual;
5500 plan->lefttree = NULL;
5501 plan->righttree = NULL;
5502 node->scan.scanrelid = scanrelid;
5503
5504 return node;
5505}

References 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,
long  numGroups 
)
static

Definition at line 6825 of file createplan.c.

6828{
6829 SetOp *node = makeNode(SetOp);
6830 Plan *plan = &node->plan;
6831 int numCols = list_length(groupList);
6832 int keyno = 0;
6833 AttrNumber *cmpColIdx;
6834 Oid *cmpOperators;
6835 Oid *cmpCollations;
6836 bool *cmpNullsFirst;
6837 ListCell *slitem;
6838
6839 plan->targetlist = tlist;
6840 plan->qual = NIL;
6841 plan->lefttree = lefttree;
6842 plan->righttree = righttree;
6843
6844 /*
6845 * convert SortGroupClause list into arrays of attr indexes and comparison
6846 * operators, as wanted by executor
6847 */
6848 cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6849 cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6850 cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6851 cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols);
6852
6853 foreach(slitem, groupList)
6854 {
6855 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6856 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6857
6858 cmpColIdx[keyno] = tle->resno;
6859 if (strategy == SETOP_HASHED)
6860 cmpOperators[keyno] = sortcl->eqop;
6861 else
6862 cmpOperators[keyno] = sortcl->sortop;
6863 Assert(OidIsValid(cmpOperators[keyno]));
6864 cmpCollations[keyno] = exprCollation((Node *) tle->expr);
6865 cmpNullsFirst[keyno] = sortcl->nulls_first;
6866 keyno++;
6867 }
6868
6869 node->cmd = cmd;
6870 node->strategy = strategy;
6871 node->numCols = numCols;
6872 node->cmpColIdx = cmpColIdx;
6873 node->cmpOperators = cmpOperators;
6874 node->cmpCollations = cmpCollations;
6875 node->cmpNullsFirst = cmpNullsFirst;
6876 node->numGroups = numGroups;
6877
6878 return node;
6879}
@ SETOP_HASHED
Definition: nodes.h:417
SetOpStrategy strategy
Definition: plannodes.h:1426
SetOpCmd cmd
Definition: plannodes.h:1423
int numCols
Definition: plannodes.h:1429
Plan plan
Definition: plannodes.h:1420
long numGroups
Definition: plannodes.h:1442

References Assert(), SetOp::cmd, SortGroupClause::eqop, TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, SortGroupClause::nulls_first, SetOp::numCols, SetOp::numGroups, OidIsValid, palloc(), SetOp::plan, plan, TargetEntry::resno, SETOP_HASHED, SortGroupClause::sortop, 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 6051 of file createplan.c.

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

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

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

◆ make_sort_from_groupcols()

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

Definition at line 6448 of file createplan.c.

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

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

Referenced by create_groupingsets_plan().

◆ make_sort_from_pathkeys()

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

Definition at line 6330 of file createplan.c.

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

References make_sort(), and prepare_sort_from_pathkeys().

Referenced by create_mergejoin_plan(), and create_sort_plan().

◆ make_sort_from_sortclauses()

Sort * make_sort_from_sortclauses ( List sortcls,
Plan lefttree 
)

Definition at line 6399 of file createplan.c.

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

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

◆ make_subqueryscan()

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

Definition at line 5666 of file createplan.c.

5670{
5672 Plan *plan = &node->scan.plan;
5673
5674 plan->targetlist = qptlist;
5675 plan->qual = qpqual;
5676 plan->lefttree = NULL;
5677 plan->righttree = NULL;
5678 node->scan.scanrelid = scanrelid;
5679 node->subplan = subplan;
5681
5682 return node;
5683}
@ SUBQUERY_SCAN_UNKNOWN
Definition: plannodes.h:740
SubqueryScanStatus scanstatus
Definition: plannodes.h:749
Plan * subplan
Definition: plannodes.h:748

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

Referenced by create_subqueryscan_plan().

◆ make_tablefuncscan()

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

Definition at line 5707 of file createplan.c.

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

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

Referenced by create_tablefuncscan_plan().

◆ make_tidrangescan()

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

Definition at line 5647 of file createplan.c.

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

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

Referenced by create_tidrangescan_plan().

◆ make_tidscan()

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

Definition at line 5628 of file createplan.c.

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

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

Referenced by create_tidscan_plan().

◆ make_unique_from_pathkeys()

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

Definition at line 6689 of file createplan.c.

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

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

Referenced by create_unique_plan().

◆ make_valuesscan()

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

Definition at line 5726 of file createplan.c.

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

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

6622{
6623 WindowAgg *node = makeNode(WindowAgg);
6624 Plan *plan = &node->plan;
6625
6626 node->winname = wc->name;
6627 node->winref = wc->winref;
6628 node->partNumCols = partNumCols;
6629 node->partColIdx = partColIdx;
6630 node->partOperators = partOperators;
6631 node->partCollations = partCollations;
6632 node->ordNumCols = ordNumCols;
6633 node->ordColIdx = ordColIdx;
6634 node->ordOperators = ordOperators;
6635 node->ordCollations = ordCollations;
6636 node->frameOptions = wc->frameOptions;
6637 node->startOffset = wc->startOffset;
6638 node->endOffset = wc->endOffset;
6639 node->runCondition = runCondition;
6640 /* a duplicate of the above for EXPLAIN */
6641 node->runConditionOrig = runCondition;
6642 node->startInRangeFunc = wc->startInRangeFunc;
6643 node->endInRangeFunc = wc->endInRangeFunc;
6644 node->inRangeColl = wc->inRangeColl;
6645 node->inRangeAsc = wc->inRangeAsc;
6646 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6647 node->topWindow = topWindow;
6648
6649 plan->targetlist = tlist;
6650 plan->lefttree = lefttree;
6651 plan->righttree = NULL;
6652 plan->qual = qual;
6653
6654 return node;
6655}
char * winname
Definition: plannodes.h:1228
int partNumCols
Definition: plannodes.h:1234
Oid endInRangeFunc
Definition: plannodes.h:1278
Node * endOffset
Definition: plannodes.h:1264
bool topWindow
Definition: plannodes.h:1293
Plan plan
Definition: plannodes.h:1225
List * runConditionOrig
Definition: plannodes.h:1270
Oid inRangeColl
Definition: plannodes.h:1281
Node * startOffset
Definition: plannodes.h:1261
List * runCondition
Definition: plannodes.h:1267
Oid startInRangeFunc
Definition: plannodes.h:1275
bool inRangeAsc
Definition: plannodes.h:1284
Index winref
Definition: plannodes.h:1231
bool inRangeNullsFirst
Definition: plannodes.h:1287
int ordNumCols
Definition: plannodes.h:1246
int frameOptions
Definition: plannodes.h:1258
Node * startOffset
Definition: parsenodes.h:1577
Node * endOffset
Definition: parsenodes.h:1578

References WindowAgg::endInRangeFunc, WindowClause::endOffset, WindowAgg::endOffset, WindowClause::frameOptions, WindowAgg::frameOptions, WindowAgg::inRangeAsc, WindowAgg::inRangeColl, WindowAgg::inRangeNullsFirst, makeNode, WindowAgg::ordNumCols, WindowAgg::partNumCols, WindowAgg::plan, plan, 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 5786 of file createplan.c.

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

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

Referenced by create_worktablescan_plan().

◆ mark_async_capable_plan()

static bool mark_async_capable_plan ( Plan plan,
Path path 
)
static

Definition at line 1134 of file createplan.c.

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

References Assert(), IsA, FdwRoutine::IsForeignPathAsyncCapable, mark_async_capable_plan(), nodeTag, plan, subpath(), SubqueryScan::subplan, 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 6511 of file createplan.c.

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

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

Referenced by build_subplan(), and standard_planner().

◆ order_qual_clauses()

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

Definition at line 5268 of file createplan.c.

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

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

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

◆ prepare_sort_from_pathkeys()

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

Definition at line 6148 of file createplan.c.

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

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

◆ remap_groupColIdx()

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

Definition at line 2202 of file createplan.c.

2203{
2204 AttrNumber *grouping_map = root->grouping_map;
2205 AttrNumber *new_grpColIdx;
2206 ListCell *lc;
2207 int i;
2208
2209 Assert(grouping_map);
2210
2211 new_grpColIdx = palloc0(sizeof(AttrNumber) * list_length(groupClause));
2212
2213 i = 0;
2214 foreach(lc, groupClause)
2215 {
2216 SortGroupClause *clause = lfirst(lc);
2217
2218 new_grpColIdx[i++] = grouping_map[clause->tleSortGroupRef];
2219 }
2220
2221 return new_grpColIdx;
2222}

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

Referenced by create_groupingsets_plan().

◆ replace_nestloop_params()

◆ replace_nestloop_params_mutator()

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

Definition at line 4897 of file createplan.c.

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

References Assert(), bms_is_member(), bms_is_subset(), expression_tree_mutator, find_placeholder_info(), IS_SPECIAL_VARNO, IsA, makeNode, PlaceHolderVar::phlevelsup, replace_nestloop_param_placeholdervar(), replace_nestloop_param_var(), 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 859 of file createplan.c.

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

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

Referenced by create_projection_plan(), and create_scan_plan().