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

Go to the source code of this file.

Macros

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

Functions

static Plancreate_plan_recurse (PlannerInfo *root, Path *best_path, int flags)
 
static Plancreate_scan_plan (PlannerInfo *root, Path *best_path, int flags)
 
static Listbuild_path_tlist (PlannerInfo *root, Path *path)
 
static bool use_physical_tlist (PlannerInfo *root, Path *path, int flags)
 
static Listget_gating_quals (PlannerInfo *root, List *quals)
 
static Plancreate_gating_plan (PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
 
static Plancreate_join_plan (PlannerInfo *root, JoinPath *best_path)
 
static bool mark_async_capable_plan (Plan *plan, Path *path)
 
static Plancreate_append_plan (PlannerInfo *root, AppendPath *best_path, int flags)
 
static Plancreate_merge_append_plan (PlannerInfo *root, MergeAppendPath *best_path, int flags)
 
static Resultcreate_group_result_plan (PlannerInfo *root, GroupResultPath *best_path)
 
static ProjectSetcreate_project_set_plan (PlannerInfo *root, ProjectSetPath *best_path)
 
static Materialcreate_material_plan (PlannerInfo *root, MaterialPath *best_path, int flags)
 
static Memoizecreate_memoize_plan (PlannerInfo *root, MemoizePath *best_path, int flags)
 
static Plancreate_unique_plan (PlannerInfo *root, UniquePath *best_path, int flags)
 
static Gathercreate_gather_plan (PlannerInfo *root, GatherPath *best_path)
 
static Plancreate_projection_plan (PlannerInfo *root, ProjectionPath *best_path, int flags)
 
static Planinject_projection_plan (Plan *subplan, List *tlist, bool parallel_safe)
 
static Sortcreate_sort_plan (PlannerInfo *root, SortPath *best_path, int flags)
 
static IncrementalSortcreate_incrementalsort_plan (PlannerInfo *root, IncrementalSortPath *best_path, int flags)
 
static Groupcreate_group_plan (PlannerInfo *root, GroupPath *best_path)
 
static Uniquecreate_upper_unique_plan (PlannerInfo *root, UpperUniquePath *best_path, int flags)
 
static Aggcreate_agg_plan (PlannerInfo *root, AggPath *best_path)
 
static Plancreate_groupingsets_plan (PlannerInfo *root, GroupingSetsPath *best_path)
 
static Resultcreate_minmaxagg_plan (PlannerInfo *root, MinMaxAggPath *best_path)
 
static WindowAggcreate_windowagg_plan (PlannerInfo *root, WindowAggPath *best_path)
 
static SetOpcreate_setop_plan (PlannerInfo *root, SetOpPath *best_path, int flags)
 
static RecursiveUnioncreate_recursiveunion_plan (PlannerInfo *root, RecursiveUnionPath *best_path)
 
static LockRowscreate_lockrows_plan (PlannerInfo *root, LockRowsPath *best_path, int flags)
 
static ModifyTablecreate_modifytable_plan (PlannerInfo *root, ModifyTablePath *best_path)
 
static Limitcreate_limit_plan (PlannerInfo *root, LimitPath *best_path, int flags)
 
static SeqScancreate_seqscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static SampleScancreate_samplescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static Scancreate_indexscan_plan (PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, bool indexonly)
 
static BitmapHeapScancreate_bitmap_scan_plan (PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses)
 
static Plancreate_bitmap_subplan (PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
 
static void bitmap_subplan_mark_shared (Plan *plan)
 
static TidScancreate_tidscan_plan (PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses)
 
static TidRangeScancreate_tidrangescan_plan (PlannerInfo *root, TidRangePath *best_path, List *tlist, List *scan_clauses)
 
static SubqueryScancreate_subqueryscan_plan (PlannerInfo *root, SubqueryScanPath *best_path, List *tlist, List *scan_clauses)
 
static FunctionScancreate_functionscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static ValuesScancreate_valuesscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static TableFuncScancreate_tablefuncscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static CteScancreate_ctescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static NamedTuplestoreScancreate_namedtuplestorescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static Resultcreate_resultscan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static WorkTableScancreate_worktablescan_plan (PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
 
static ForeignScancreate_foreignscan_plan (PlannerInfo *root, ForeignPath *best_path, List *tlist, List *scan_clauses)
 
static CustomScancreate_customscan_plan (PlannerInfo *root, CustomPath *best_path, List *tlist, List *scan_clauses)
 
static NestLoopcreate_nestloop_plan (PlannerInfo *root, NestPath *best_path)
 
static MergeJoincreate_mergejoin_plan (PlannerInfo *root, MergePath *best_path)
 
static HashJoincreate_hashjoin_plan (PlannerInfo *root, HashPath *best_path)
 
static Nodereplace_nestloop_params (PlannerInfo *root, Node *expr)
 
static Nodereplace_nestloop_params_mutator (Node *node, PlannerInfo *root)
 
static void fix_indexqual_references (PlannerInfo *root, IndexPath *index_path, List **stripped_indexquals_p, List **fixed_indexquals_p)
 
static Listfix_indexorderby_references (PlannerInfo *root, IndexPath *index_path)
 
static Nodefix_indexqual_clause (PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
 
static Nodefix_indexqual_operand (Node *node, IndexOptInfo *index, int indexcol)
 
static Listget_switched_clauses (List *clauses, Relids outerrelids)
 
static Listorder_qual_clauses (PlannerInfo *root, List *clauses)
 
static void copy_generic_path_info (Plan *dest, Path *src)
 
static void copy_plan_costsize (Plan *dest, Plan *src)
 
static void label_sort_with_costsize (PlannerInfo *root, Sort *plan, double limit_tuples)
 
static void label_incrementalsort_with_costsize (PlannerInfo *root, IncrementalSort *plan, List *pathkeys, double limit_tuples)
 
static SeqScanmake_seqscan (List *qptlist, List *qpqual, Index scanrelid)
 
static SampleScanmake_samplescan (List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
 
static IndexScanmake_indexscan (List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig, List *indexorderby, List *indexorderbyorig, List *indexorderbyops, ScanDirection indexscandir)
 
static IndexOnlyScanmake_indexonlyscan (List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *recheckqual, List *indexorderby, List *indextlist, ScanDirection indexscandir)
 
static BitmapIndexScanmake_bitmap_indexscan (Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
 
static BitmapHeapScanmake_bitmap_heapscan (List *qptlist, List *qpqual, Plan *lefttree, List *bitmapqualorig, Index scanrelid)
 
static TidScanmake_tidscan (List *qptlist, List *qpqual, Index scanrelid, List *tidquals)
 
static TidRangeScanmake_tidrangescan (List *qptlist, List *qpqual, Index scanrelid, List *tidrangequals)
 
static SubqueryScanmake_subqueryscan (List *qptlist, List *qpqual, Index scanrelid, Plan *subplan)
 
static FunctionScanmake_functionscan (List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
 
static ValuesScanmake_valuesscan (List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
 
static TableFuncScanmake_tablefuncscan (List *qptlist, List *qpqual, Index scanrelid, TableFunc *tablefunc)
 
static CteScanmake_ctescan (List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
 
static NamedTuplestoreScanmake_namedtuplestorescan (List *qptlist, List *qpqual, Index scanrelid, char *enrname)
 
static WorkTableScanmake_worktablescan (List *qptlist, List *qpqual, Index scanrelid, int wtParam)
 
static RecursiveUnionmake_recursive_union (List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, long numGroups)
 
static BitmapAndmake_bitmap_and (List *bitmapplans)
 
static BitmapOrmake_bitmap_or (List *bitmapplans)
 
static NestLoopmake_nestloop (List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static HashJoinmake_hashjoin (List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, List *hashoperators, List *hashcollations, List *hashkeys, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique)
 
static Hashmake_hash (Plan *lefttree, List *hashkeys, Oid skewTable, AttrNumber skewColumn, bool skewInherit)
 
static MergeJoinmake_mergejoin (List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, bool *mergereversals, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype, bool inner_unique, bool skip_mark_restore)
 
static Sortmake_sort (Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static IncrementalSortmake_incrementalsort (Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
 
static Planprepare_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, const AttrNumber *reqColIdx, bool adjust_tlist_in_place, int *p_numsortkeys, AttrNumber **p_sortColIdx, Oid **p_sortOperators, Oid **p_collations, bool **p_nullsFirst)
 
static Sortmake_sort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids)
 
static IncrementalSortmake_incrementalsort_from_pathkeys (Plan *lefttree, List *pathkeys, Relids relids, int nPresortedCols)
 
static Sortmake_sort_from_groupcols (List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
 
static Materialmake_material (Plan *lefttree)
 
static Memoizemake_memoize (Plan *lefttree, Oid *hashoperators, Oid *collations, List *param_exprs, bool singlerow, bool binary_mode, uint32 est_entries, Bitmapset *keyparamids)
 
static WindowAggmake_windowagg (List *tlist, 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_sortclauses (Plan *lefttree, List *distinctList)
 
static Uniquemake_unique_from_pathkeys (Plan *lefttree, List *pathkeys, int numCols)
 
static Gathermake_gather (List *qptlist, List *qpqual, int nworkers, int rescan_param, bool single_copy, Plan *subplan)
 
static SetOpmake_setop (SetOpCmd cmd, SetOpStrategy strategy, List *tlist, Plan *lefttree, Plan *righttree, List *groupList, long numGroups)
 
static LockRowsmake_lockrows (Plan *lefttree, List *rowMarks, int epqParam)
 
static Resultmake_result (List *tlist, Node *resconstantqual, Plan *subplan)
 
static ProjectSetmake_project_set (List *tlist, Plan *subplan)
 
static ModifyTablemake_modifytable (PlannerInfo *root, Plan *subplan, CmdType operation, bool canSetTag, Index nominalRelation, Index rootRelation, bool partColsUpdated, List *resultRelations, List *updateColnosLists, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, List *mergeActionLists, List *mergeJoinConditions, int epqParam)
 
static GatherMergecreate_gather_merge_plan (PlannerInfo *root, GatherMergePath *best_path)
 
Plancreate_plan (PlannerInfo *root, Path *best_path)
 
Planchange_plan_targetlist (Plan *subplan, List *tlist, bool tlist_parallel_safe)
 
static AttrNumberremap_groupColIdx (PlannerInfo *root, List *groupClause)
 
ForeignScanmake_foreignscan (List *qptlist, List *qpqual, Index scanrelid, List *fdw_exprs, List *fdw_private, List *fdw_scan_tlist, List *fdw_recheck_quals, Plan *outer_plan)
 
Sortmake_sort_from_sortclauses (List *sortcls, Plan *lefttree)
 
Planmaterialize_finished_plan (Plan *subplan)
 
Aggmake_agg (List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Oid *grpCollations, List *groupingSets, List *chain, double dNumGroups, Size transitionSpace, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount, LimitOption limitOption, int uniqNumCols, AttrNumber *uniqColIdx, Oid *uniqOperators, Oid *uniqCollations)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 

Macro Definition Documentation

◆ CP_EXACT_TLIST

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

Definition at line 70 of file createplan.c.

◆ CP_IGNORE_TLIST

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

Definition at line 73 of file createplan.c.

◆ CP_LABEL_TLIST

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

Definition at line 72 of file createplan.c.

◆ CP_SMALL_TLIST

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

Definition at line 71 of file createplan.c.

Function Documentation

◆ bitmap_subplan_mark_shared()

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 5544 of file createplan.c.

5545{
5546 if (IsA(plan, BitmapAnd))
5548 else if (IsA(plan, BitmapOr))
5549 {
5550 ((BitmapOr *) plan)->isshared = true;
5551 bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5552 }
5553 else if (IsA(plan, BitmapIndexScan))
5554 ((BitmapIndexScan *) plan)->isshared = true;
5555 else
5556 elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5557}
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:5544
#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 825 of file createplan.c.

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

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(), create_unique_plan(), and create_windowagg_plan().

◆ change_plan_targetlist()

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

Definition at line 2149 of file createplan.c.

2150{
2151 /*
2152 * If the top plan node can't do projections and its existing target list
2153 * isn't already what we need, we need to add a Result node to help it
2154 * along.
2155 */
2156 if (!is_projection_capable_plan(subplan) &&
2157 !tlist_same_exprs(tlist, subplan->targetlist))
2158 subplan = inject_projection_plan(subplan, tlist,
2159 subplan->parallel_safe &&
2160 tlist_parallel_safe);
2161 else
2162 {
2163 /* Else we can just replace the plan node's tlist */
2164 subplan->targetlist = tlist;
2165 subplan->parallel_safe &= tlist_parallel_safe;
2166 }
2167 return subplan;
2168}
bool is_projection_capable_plan(Plan *plan)
Definition: createplan.c:7357
static Plan * inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
Definition: createplan.c:2117
bool parallel_safe
Definition: plannodes.h:195
List * targetlist
Definition: plannodes.h:209
bool tlist_same_exprs(List *tlist1, List *tlist2)
Definition: tlist.c:218

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

Referenced by create_unique_plan(), and postgresGetForeignPlan().

◆ copy_generic_path_info()

static void copy_generic_path_info ( Plan dest,
Path src 
)
static

Definition at line 5445 of file createplan.c.

5446{
5447 dest->disabled_nodes = src->disabled_nodes;
5448 dest->startup_cost = src->startup_cost;
5449 dest->total_cost = src->total_cost;
5450 dest->plan_rows = src->rows;
5451 dest->plan_width = src->pathtarget->width;
5452 dest->parallel_aware = src->parallel_aware;
5453 dest->parallel_safe = src->parallel_safe;
5454}
Cardinality rows
Definition: pathnodes.h:1796
Cost startup_cost
Definition: pathnodes.h:1798
int disabled_nodes
Definition: pathnodes.h:1797
Cost total_cost
Definition: pathnodes.h:1799
bool parallel_aware
Definition: pathnodes.h:1789
bool parallel_safe
Definition: pathnodes.h:1791

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

Referenced by create_agg_plan(), create_append_plan(), create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_hashjoin_plan(), create_incrementalsort_plan(), create_indexscan_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_namedtuplestorescan_plan(), create_nestloop_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_resultscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_setop_plan(), create_sort_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidrangescan_plan(), create_tidscan_plan(), create_unique_plan(), create_upper_unique_plan(), create_valuesscan_plan(), create_windowagg_plan(), and create_worktablescan_plan().

◆ copy_plan_costsize()

static void copy_plan_costsize ( Plan dest,
Plan src 
)
static

Definition at line 5461 of file createplan.c.

5462{
5463 dest->disabled_nodes = src->disabled_nodes;
5464 dest->startup_cost = src->startup_cost;
5465 dest->total_cost = src->total_cost;
5466 dest->plan_rows = src->plan_rows;
5467 dest->plan_width = src->plan_width;
5468 /* Assume the inserted node is not parallel-aware. */
5469 dest->parallel_aware = false;
5470 /* Assume the inserted node is parallel-safe, if child plan is. */
5471 dest->parallel_safe = src->parallel_safe;
5472}
Cost total_cost
Definition: plannodes.h:179
Cost startup_cost
Definition: plannodes.h:177
int plan_width
Definition: plannodes.h:187
Cardinality plan_rows
Definition: plannodes.h:185
int disabled_nodes
Definition: plannodes.h:175

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

2306{
2307 Agg *plan;
2308 Plan *subplan;
2309 List *tlist;
2310 List *quals;
2311
2312 /*
2313 * Agg can project, so no need to be terribly picky about child tlist, but
2314 * we do need grouping columns to be available
2315 */
2316 subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
2317
2318 tlist = build_path_tlist(root, &best_path->path);
2319
2320 quals = order_qual_clauses(root, best_path->qual);
2321
2322 plan = make_agg(tlist, quals,
2323 best_path->aggstrategy,
2324 best_path->aggsplit,
2325 list_length(best_path->groupClause),
2327 subplan->targetlist),
2330 subplan->targetlist),
2331 NIL,
2332 NIL,
2333 best_path->numGroups,
2334 best_path->transitionSpace,
2335 subplan);
2336
2337 copy_generic_path_info(&plan->plan, (Path *) best_path);
2338
2339 return plan;
2340}
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:5351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5445
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:388
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:825
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:6662
#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:2391
Cardinality numGroups
Definition: pathnodes.h:2394
AggSplit aggsplit
Definition: pathnodes.h:2393
List * groupClause
Definition: pathnodes.h:2396
uint64 transitionSpace
Definition: pathnodes.h:2395
AggStrategy aggstrategy
Definition: pathnodes.h:2392
Path path
Definition: pathnodes.h:2390
List * qual
Definition: pathnodes.h:2397
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 1216 of file createplan.c.

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

References Assert(), Plan::async_capable, RelOptInfo::baserestrictinfo, build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, CP_SMALL_TLIST, create_plan_recurse(), elog, enable_async_append, enable_partition_pruning, ERROR, extract_actual_clauses(), AppendPath::first_partial_path, inject_projection_plan(), label_sort_with_costsize(), lappend(), lfirst, AppendPath::limit_tuples, list_concat(), list_copy_head(), list_length(), list_make1, make_partition_pruneinfo(), make_result(), make_sort(), makeBoolConst(), makeNode, mark_async_capable_plan(), NIL, Path::parallel_safe, AppendPath::path, Path::pathkeys, pathkeys_contained_in(), plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, replace_nestloop_params(), root, sort(), subpath(), and AppendPath::subpaths.

Referenced by create_plan_recurse().

◆ create_bitmap_scan_plan()

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

Definition at line 3195 of file createplan.c.

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

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

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

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

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

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

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

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

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

3756{
3757 FunctionScan *scan_plan;
3758 Index scan_relid = best_path->parent->relid;
3759 RangeTblEntry *rte;
3760 List *functions;
3761
3762 /* it should be a function base rel... */
3763 Assert(scan_relid > 0);
3764 rte = planner_rt_fetch(scan_relid, root);
3765 Assert(rte->rtekind == RTE_FUNCTION);
3766 functions = rte->functions;
3767
3768 /* Sort clauses into best execution order */
3769 scan_clauses = order_qual_clauses(root, scan_clauses);
3770
3771 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3772 scan_clauses = extract_actual_clauses(scan_clauses, false);
3773
3774 /* Replace any outer-relation variables with nestloop params */
3775 if (best_path->param_info)
3776 {
3777 scan_clauses = (List *)
3778 replace_nestloop_params(root, (Node *) scan_clauses);
3779 /* The function expressions could contain nestloop params, too */
3781 }
3782
3783 scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3785
3786 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3787
3788 return scan_plan;
3789}
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5769
@ RTE_FUNCTION
Definition: parsenodes.h:1029
static const struct fns functions
Definition: regcomp.c:358
bool funcordinality
Definition: parsenodes.h:1193
List * functions
Definition: parsenodes.h:1191

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

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

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

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

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

Referenced by create_plan_recurse().

◆ create_gating_plan()

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

Definition at line 1022 of file createplan.c.

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

References Assert(), build_path_tlist(), copy_plan_costsize(), IsA, Plan::lefttree, make_result(), Path::parallel_safe, Plan::parallel_safe, Result::plan, plan, Result::resconstantqual, 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 2238 of file createplan.c.

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

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

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

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

Referenced by create_plan_recurse().

◆ create_groupingsets_plan()

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

Definition at line 2389 of file createplan.c.

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

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

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

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

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

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

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

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

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

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

2787{
2788 LockRows *plan;
2789 Plan *subplan;
2790
2791 /* LockRows doesn't project, so tlist requirements pass through */
2792 subplan = create_plan_recurse(root, best_path->subpath, flags);
2793
2794 plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2795
2796 copy_generic_path_info(&plan->plan, (Path *) best_path);
2797
2798 return plan;
2799}
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:7011
Path * subpath
Definition: pathnodes.h:2497
List * rowMarks
Definition: pathnodes.h:2498

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

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

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

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

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

Referenced by create_plan_recurse().

◆ create_merge_append_plan()

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

Definition at line 1437 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_mergejoin_plan()

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

Definition at line 4433 of file createplan.c.

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

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(), JoinPath::outerjoinpath, MergePath::outersortkeys, palloc(), MergePath::path_mergeclauses, Path::pathkeys, pathkeys_count_contained_in(), PG_USED_FOR_ASSERTS_ONLY, 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 2547 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_modifytable_plan()

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

Definition at line 2808 of file createplan.c.

2809{
2811 Path *subpath = best_path->subpath;
2812 Plan *subplan;
2813
2814 /* Subplan must produce exactly the specified tlist */
2816
2817 /* Transfer resname/resjunk labeling, too, to keep executor happy */
2818 apply_tlist_labeling(subplan->targetlist, root->processed_tlist);
2819
2821 subplan,
2822 best_path->operation,
2823 best_path->canSetTag,
2824 best_path->nominalRelation,
2825 best_path->rootRelation,
2826 best_path->partColsUpdated,
2827 best_path->resultRelations,
2828 best_path->updateColnosLists,
2829 best_path->withCheckOptionLists,
2830 best_path->returningLists,
2831 best_path->rowMarks,
2832 best_path->onconflict,
2833 best_path->mergeActionLists,
2834 best_path->mergeJoinConditions,
2835 best_path->epqParam);
2836
2837 copy_generic_path_info(&plan->plan, &best_path->path);
2838
2839 return plan;
2840}
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:7100
bool partColsUpdated
Definition: pathnodes.h:2517
List * returningLists
Definition: pathnodes.h:2521
List * resultRelations
Definition: pathnodes.h:2518
List * withCheckOptionLists
Definition: pathnodes.h:2520
List * mergeJoinConditions
Definition: pathnodes.h:2527
List * updateColnosLists
Definition: pathnodes.h:2519
OnConflictExpr * onconflict
Definition: pathnodes.h:2523
CmdType operation
Definition: pathnodes.h:2513
Index rootRelation
Definition: pathnodes.h:2516
Index nominalRelation
Definition: pathnodes.h:2515
List * mergeActionLists
Definition: pathnodes.h:2525
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 3979 of file createplan.c.

3981{
3982 NamedTuplestoreScan *scan_plan;
3983 Index scan_relid = best_path->parent->relid;
3984 RangeTblEntry *rte;
3985
3986 Assert(scan_relid > 0);
3987 rte = planner_rt_fetch(scan_relid, root);
3989
3990 /* Sort clauses into best execution order */
3991 scan_clauses = order_qual_clauses(root, scan_clauses);
3992
3993 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3994 scan_clauses = extract_actual_clauses(scan_clauses, false);
3995
3996 /* Replace any outer-relation variables with nestloop params */
3997 if (best_path->param_info)
3998 {
3999 scan_clauses = (List *)
4000 replace_nestloop_params(root, (Node *) scan_clauses);
4001 }
4002
4003 scan_plan = make_namedtuplestorescan(tlist, scan_clauses, scan_relid,
4004 rte->enrname);
4005
4006 copy_generic_path_info(&scan_plan->scan.plan, best_path);
4007
4008 return scan_plan;
4009}
static NamedTuplestoreScan * make_namedtuplestorescan(List *qptlist, List *qpqual, Index scanrelid, char *enrname)
Definition: createplan.c:5849
@ RTE_NAMEDTUPLESTORE
Definition: parsenodes.h:1033
char * enrname
Definition: parsenodes.h:1245

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

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

References Assert(), bms_free(), bms_union(), build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), extract_actual_clauses(), extract_actual_join_clauses(), identify_current_nestloop_params(), JoinPath::inner_unique, JoinPath::innerjoinpath, IS_OUTER_JOIN, NestLoop::join, JoinPath::joinrestrictinfo, JoinPath::jointype, NestPath::jpath, make_nestloop(), NIL, order_qual_clauses(), JoinPath::outerjoinpath, reparameterize_path_by_child(), replace_nestloop_params(), and root.

Referenced by create_join_plan().

◆ create_plan()

Plan * create_plan ( PlannerInfo root,
Path best_path 
)

Definition at line 337 of file createplan.c.

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

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

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

◆ create_plan_recurse()

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

Definition at line 388 of file createplan.c.

389{
390 Plan *plan;
391
392 /* Guard against stack overflow due to overly complex plans */
394
395 switch (best_path->pathtype)
396 {
397 case T_SeqScan:
398 case T_SampleScan:
399 case T_IndexScan:
400 case T_IndexOnlyScan:
401 case T_BitmapHeapScan:
402 case T_TidScan:
403 case T_TidRangeScan:
404 case T_SubqueryScan:
405 case T_FunctionScan:
406 case T_TableFuncScan:
407 case T_ValuesScan:
408 case T_CteScan:
409 case T_WorkTableScan:
410 case T_NamedTuplestoreScan:
411 case T_ForeignScan:
412 case T_CustomScan:
413 plan = create_scan_plan(root, best_path, flags);
414 break;
415 case T_HashJoin:
416 case T_MergeJoin:
417 case T_NestLoop:
419 (JoinPath *) best_path);
420 break;
421 case T_Append:
423 (AppendPath *) best_path,
424 flags);
425 break;
426 case T_MergeAppend:
428 (MergeAppendPath *) best_path,
429 flags);
430 break;
431 case T_Result:
432 if (IsA(best_path, ProjectionPath))
433 {
435 (ProjectionPath *) best_path,
436 flags);
437 }
438 else if (IsA(best_path, MinMaxAggPath))
439 {
441 (MinMaxAggPath *) best_path);
442 }
443 else if (IsA(best_path, GroupResultPath))
444 {
446 (GroupResultPath *) best_path);
447 }
448 else
449 {
450 /* Simple RTE_RESULT base relation */
451 Assert(IsA(best_path, Path));
452 plan = create_scan_plan(root, best_path, flags);
453 }
454 break;
455 case T_ProjectSet:
457 (ProjectSetPath *) best_path);
458 break;
459 case T_Material:
461 (MaterialPath *) best_path,
462 flags);
463 break;
464 case T_Memoize:
466 (MemoizePath *) best_path,
467 flags);
468 break;
469 case T_Unique:
470 if (IsA(best_path, UpperUniquePath))
471 {
473 (UpperUniquePath *) best_path,
474 flags);
475 }
476 else
477 {
478 Assert(IsA(best_path, UniquePath));
480 (UniquePath *) best_path,
481 flags);
482 }
483 break;
484 case T_Gather:
486 (GatherPath *) best_path);
487 break;
488 case T_Sort:
490 (SortPath *) best_path,
491 flags);
492 break;
493 case T_IncrementalSort:
495 (IncrementalSortPath *) best_path,
496 flags);
497 break;
498 case T_Group:
500 (GroupPath *) best_path);
501 break;
502 case T_Agg:
503 if (IsA(best_path, GroupingSetsPath))
505 (GroupingSetsPath *) best_path);
506 else
507 {
508 Assert(IsA(best_path, AggPath));
510 (AggPath *) best_path);
511 }
512 break;
513 case T_WindowAgg:
515 (WindowAggPath *) best_path);
516 break;
517 case T_SetOp:
519 (SetOpPath *) best_path,
520 flags);
521 break;
522 case T_RecursiveUnion:
524 (RecursiveUnionPath *) best_path);
525 break;
526 case T_LockRows:
528 (LockRowsPath *) best_path,
529 flags);
530 break;
531 case T_ModifyTable:
533 (ModifyTablePath *) best_path);
534 break;
535 case T_Limit:
537 (LimitPath *) best_path,
538 flags);
539 break;
540 case T_GatherMerge:
542 (GatherMergePath *) best_path);
543 break;
544 default:
545 elog(ERROR, "unrecognized node type: %d",
546 (int) best_path->pathtype);
547 plan = NULL; /* keep compiler quiet */
548 break;
549 }
550
551 return plan;
552}
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
Definition: createplan.c:1081
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path, int flags)
Definition: createplan.c:1437
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
Definition: createplan.c:1959
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path, int flags)
Definition: createplan.c:1216
static Result * create_group_result_plan(PlannerInfo *root, GroupResultPath *best_path)
Definition: createplan.c:1588
static Limit * create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
Definition: createplan.c:2849
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
Definition: createplan.c:2305
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
Definition: createplan.c:2709
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
Definition: createplan.c:2177
static Unique * create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
Definition: createplan.c:2277
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
Definition: createplan.c:1921
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
Definition: createplan.c:1613
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
Definition: createplan.c:2238
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
Definition: createplan.c:2808
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
Definition: createplan.c:2547
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
Definition: createplan.c:2785
static Material * create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
Definition: createplan.c:1639
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:559
static IncrementalSort * create_incrementalsort_plan(PlannerInfo *root, IncrementalSortPath *best_path, int flags)
Definition: createplan.c:2211
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path, int flags)
Definition: createplan.c:2015
static Memoize * create_memoize_plan(PlannerInfo *root, MemoizePath *best_path, int flags)
Definition: createplan.c:1667
static WindowAgg * create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
Definition: createplan.c:2614
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
Definition: createplan.c:2389
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
Definition: createplan.c:2749
static Plan * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
Definition: createplan.c:1721
void check_stack_depth(void)
Definition: stack_depth.c:95
NodeTag pathtype
Definition: pathnodes.h:1762

References Assert(), check_stack_depth(), create_agg_plan(), create_append_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_group_result_plan(), create_groupingsets_plan(), create_incrementalsort_plan(), create_join_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_memoize_plan(), create_merge_append_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_scan_plan(), create_setop_plan(), create_sort_plan(), create_unique_plan(), create_upper_unique_plan(), create_windowagg_plan(), elog, ERROR, IsA, Path::pathtype, plan, and root.

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

◆ create_project_set_plan()

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

Definition at line 1613 of file createplan.c.

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

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

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

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

Referenced by create_plan_recurse().

◆ create_recursiveunion_plan()

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

Definition at line 2749 of file createplan.c.

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

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

4020{
4021 Result *scan_plan;
4022 Index scan_relid = best_path->parent->relid;
4024
4025 Assert(scan_relid > 0);
4026 rte = planner_rt_fetch(scan_relid, root);
4027 Assert(rte->rtekind == RTE_RESULT);
4028
4029 /* Sort clauses into best execution order */
4030 scan_clauses = order_qual_clauses(root, scan_clauses);
4031
4032 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
4033 scan_clauses = extract_actual_clauses(scan_clauses, false);
4034
4035 /* Replace any outer-relation variables with nestloop params */
4036 if (best_path->param_info)
4037 {
4038 scan_clauses = (List *)
4039 replace_nestloop_params(root, (Node *) scan_clauses);
4040 }
4041
4042 scan_plan = make_result(tlist, (Node *) scan_clauses, NULL);
4043
4044 copy_generic_path_info(&scan_plan->plan, best_path);
4045
4046 return scan_plan;
4047}
@ RTE_RESULT
Definition: parsenodes.h:1034

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

Referenced by create_scan_plan().

◆ create_samplescan_plan()

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

Definition at line 2948 of file createplan.c.

2950{
2951 SampleScan *scan_plan;
2952 Index scan_relid = best_path->parent->relid;
2953 RangeTblEntry *rte;
2954 TableSampleClause *tsc;
2955
2956 /* it should be a base rel with a tablesample clause... */
2957 Assert(scan_relid > 0);
2958 rte = planner_rt_fetch(scan_relid, root);
2959 Assert(rte->rtekind == RTE_RELATION);
2960 tsc = rte->tablesample;
2961 Assert(tsc != NULL);
2962
2963 /* Sort clauses into best execution order */
2964 scan_clauses = order_qual_clauses(root, scan_clauses);
2965
2966 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2967 scan_clauses = extract_actual_clauses(scan_clauses, false);
2968
2969 /* Replace any outer-relation variables with nestloop params */
2970 if (best_path->param_info)
2971 {
2972 scan_clauses = (List *)
2973 replace_nestloop_params(root, (Node *) scan_clauses);
2974 tsc = (TableSampleClause *)
2976 }
2977
2978 scan_plan = make_samplescan(tlist,
2979 scan_clauses,
2980 scan_relid,
2981 tsc);
2982
2983 copy_generic_path_info(&scan_plan->scan.plan, best_path);
2984
2985 return scan_plan;
2986}
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:5591
struct TableSampleClause * tablesample
Definition: parsenodes.h:1112
Scan scan
Definition: plannodes.h:501

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

Referenced by create_scan_plan().

◆ create_scan_plan()

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

Definition at line 559 of file createplan.c.

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

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

2912{
2913 SeqScan *scan_plan;
2914 Index scan_relid = best_path->parent->relid;
2915
2916 /* it should be a base rel... */
2917 Assert(scan_relid > 0);
2918 Assert(best_path->parent->rtekind == RTE_RELATION);
2919
2920 /* Sort clauses into best execution order */
2921 scan_clauses = order_qual_clauses(root, scan_clauses);
2922
2923 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2924 scan_clauses = extract_actual_clauses(scan_clauses, false);
2925
2926 /* Replace any outer-relation variables with nestloop params */
2927 if (best_path->param_info)
2928 {
2929 scan_clauses = (List *)
2930 replace_nestloop_params(root, (Node *) scan_clauses);
2931 }
2932
2933 scan_plan = make_seqscan(tlist,
2934 scan_clauses,
2935 scan_relid);
2936
2937 copy_generic_path_info(&scan_plan->scan.plan, best_path);
2938
2939 return scan_plan;
2940}
static SeqScan * make_seqscan(List *qptlist, List *qpqual, Index scanrelid)
Definition: createplan.c:5574
Scan scan
Definition: plannodes.h:492

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

2710{
2711 SetOp *plan;
2712 List *tlist = build_path_tlist(root, &best_path->path);
2713 Plan *leftplan;
2714 Plan *rightplan;
2715 long numGroups;
2716
2717 /*
2718 * SetOp doesn't project, so tlist requirements pass through; moreover we
2719 * need grouping columns to be labeled.
2720 */
2721 leftplan = create_plan_recurse(root, best_path->leftpath,
2722 flags | CP_LABEL_TLIST);
2723 rightplan = create_plan_recurse(root, best_path->rightpath,
2724 flags | CP_LABEL_TLIST);
2725
2726 /* Convert numGroups to long int --- but 'ware overflow! */
2727 numGroups = clamp_cardinality_to_long(best_path->numGroups);
2728
2729 plan = make_setop(best_path->cmd,
2730 best_path->strategy,
2731 tlist,
2732 leftplan,
2733 rightplan,
2734 best_path->groupList,
2735 numGroups);
2736
2737 copy_generic_path_info(&plan->plan, (Path *) best_path);
2738
2739 return plan;
2740}
static SetOp * make_setop(SetOpCmd cmd, SetOpStrategy strategy, List *tlist, Plan *lefttree, Plan *righttree, List *groupList, long numGroups)
Definition: createplan.c:6950
Path * rightpath
Definition: pathnodes.h:2471
Cardinality numGroups
Definition: pathnodes.h:2475
Path * leftpath
Definition: pathnodes.h:2470
SetOpCmd cmd
Definition: pathnodes.h:2472
Path path
Definition: pathnodes.h:2469
SetOpStrategy strategy
Definition: pathnodes.h:2473
List * groupList
Definition: pathnodes.h:2474

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

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

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

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

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

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

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

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

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

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

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

Referenced by create_scan_plan().

◆ create_unique_plan()

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

Definition at line 1721 of file createplan.c.

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

References AGG_HASHED, AGGSPLIT_SIMPLE, Assert(), assignSortGroupRef(), build_path_tlist(), change_plan_targetlist(), copy_generic_path_info(), create_plan_recurse(), elog, SortGroupClause::eqop, ERROR, TargetEntry::expr, exprCollation(), get_compatible_hash_operators(), get_equality_op_for_ordering_op(), get_ordering_op_for_equality_op(), get_tle_by_resno(), UniquePath::in_operators, label_sort_with_costsize(), lappend(), lfirst, lfirst_oid, list_length(), make_agg(), make_sort_from_sortclauses(), make_unique_from_sortclauses(), makeNode, makeTargetEntry(), NIL, SortGroupClause::nulls_first, OidIsValid, palloc(), Path::parallel_safe, UniquePath::path, plan, TargetEntry::resno, SortGroupClause::reverse_sort, root, Path::rows, sort(), SortGroupClause::sortop, UniquePath::subpath, Plan::targetlist, SortGroupClause::tleSortGroupRef, tlist_member(), UniquePath::umethod, UniquePath::uniq_exprs, UNIQUE_PATH_HASH, UNIQUE_PATH_NOOP, and UNIQUE_PATH_SORT.

Referenced by create_plan_recurse().

◆ create_upper_unique_plan()

static Unique * create_upper_unique_plan ( PlannerInfo root,
UpperUniquePath best_path,
int  flags 
)
static

Definition at line 2277 of file createplan.c.

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

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

Referenced by create_plan_recurse().

◆ create_valuesscan_plan()

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

Definition at line 3840 of file createplan.c.

3842{
3843 ValuesScan *scan_plan;
3844 Index scan_relid = best_path->parent->relid;
3845 RangeTblEntry *rte;
3846 List *values_lists;
3847
3848 /* it should be a values base rel... */
3849 Assert(scan_relid > 0);
3850 rte = planner_rt_fetch(scan_relid, root);
3851 Assert(rte->rtekind == RTE_VALUES);
3852 values_lists = rte->values_lists;
3853
3854 /* Sort clauses into best execution order */
3855 scan_clauses = order_qual_clauses(root, scan_clauses);
3856
3857 /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3858 scan_clauses = extract_actual_clauses(scan_clauses, false);
3859
3860 /* Replace any outer-relation variables with nestloop params */
3861 if (best_path->param_info)
3862 {
3863 scan_clauses = (List *)
3864 replace_nestloop_params(root, (Node *) scan_clauses);
3865 /* The values lists could contain nestloop params, too */
3866 values_lists = (List *)
3867 replace_nestloop_params(root, (Node *) values_lists);
3868 }
3869
3870 scan_plan = make_valuesscan(tlist, scan_clauses, scan_relid,
3871 values_lists);
3872
3873 copy_generic_path_info(&scan_plan->scan.plan, best_path);
3874
3875 return scan_plan;
3876}
static ValuesScan * make_valuesscan(List *qptlist, List *qpqual, Index scanrelid, List *values_lists)
Definition: createplan.c:5809
@ RTE_VALUES
Definition: parsenodes.h:1031
List * values_lists
Definition: parsenodes.h:1204
Scan scan
Definition: plannodes.h:738

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

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

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

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

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

5100{
5101 IndexOptInfo *index = index_path->indexinfo;
5102 List *fixed_indexorderbys;
5103 ListCell *lcc,
5104 *lci;
5105
5106 fixed_indexorderbys = NIL;
5107
5108 forboth(lcc, index_path->indexorderbys, lci, index_path->indexorderbycols)
5109 {
5110 Node *clause = (Node *) lfirst(lcc);
5111 int indexcol = lfirst_int(lci);
5112
5113 clause = fix_indexqual_clause(root, index, indexcol, clause, NIL);
5114 fixed_indexorderbys = lappend(fixed_indexorderbys, clause);
5115 }
5116
5117 return fixed_indexorderbys;
5118}
static Node * fix_indexqual_clause(PlannerInfo *root, IndexOptInfo *index, int indexcol, Node *clause, List *indexcolnos)
Definition: createplan.c:5128
#define lfirst_int(lc)
Definition: pg_list.h:173
List * indexorderbycols
Definition: pathnodes.h:1850
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 5128 of file createplan.c.

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

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

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

5060{
5061 IndexOptInfo *index = index_path->indexinfo;
5062 List *stripped_indexquals;
5063 List *fixed_indexquals;
5064 ListCell *lc;
5065
5066 stripped_indexquals = fixed_indexquals = NIL;
5067
5068 foreach(lc, index_path->indexclauses)
5069 {
5070 IndexClause *iclause = lfirst_node(IndexClause, lc);
5071 int indexcol = iclause->indexcol;
5072 ListCell *lc2;
5073
5074 foreach(lc2, iclause->indexquals)
5075 {
5076 RestrictInfo *rinfo = lfirst_node(RestrictInfo, lc2);
5077 Node *clause = (Node *) rinfo->clause;
5078
5079 stripped_indexquals = lappend(stripped_indexquals, clause);
5080 clause = fix_indexqual_clause(root, index, indexcol,
5081 clause, iclause->indexcols);
5082 fixed_indexquals = lappend(fixed_indexquals, clause);
5083 }
5084 }
5085
5086 *stripped_indexquals_p = stripped_indexquals;
5087 *fixed_indexquals_p = fixed_indexquals;
5088}
AttrNumber indexcol
Definition: pathnodes.h:1898
List * indexcols
Definition: pathnodes.h:1899

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

Referenced by create_indexscan_plan().

◆ get_gating_quals()

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

Definition at line 1002 of file createplan.c.

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

References extract_actual_clauses(), NIL, order_qual_clauses(), and root.

Referenced by create_join_plan(), and create_scan_plan().

◆ get_switched_clauses()

static List * get_switched_clauses ( List clauses,
Relids  outerrelids 
)
static

Definition at line 5274 of file createplan.c.

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

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

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

References copy_plan_costsize(), make_result(), and plan.

Referenced by change_plan_targetlist(), create_append_plan(), create_merge_append_plan(), and prepare_sort_from_pathkeys().

◆ is_projection_capable_path()

bool is_projection_capable_path ( Path path)

Definition at line 7307 of file createplan.c.

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

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

7358{
7359 /* Most plan types can project, so just list the ones that can't */
7360 switch (nodeTag(plan))
7361 {
7362 case T_Hash:
7363 case T_Material:
7364 case T_Memoize:
7365 case T_Sort:
7366 case T_Unique:
7367 case T_SetOp:
7368 case T_LockRows:
7369 case T_Limit:
7370 case T_ModifyTable:
7371 case T_Append:
7372 case T_MergeAppend:
7373 case T_RecursiveUnion:
7374 return false;
7375 case T_CustomScan:
7377 return true;
7378 return false;
7379 case T_ProjectSet:
7380
7381 /*
7382 * Although ProjectSet certainly projects, say "no" because we
7383 * don't want the planner to randomly replace its tlist with
7384 * something else; the SRFs have to stay at top level. This might
7385 * get relaxed later.
7386 */
7387 return false;
7388 default:
7389 break;
7390 }
7391 return true;
7392}

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

5514{
5515 Plan *lefttree = plan->sort.plan.lefttree;
5516 Path sort_path; /* dummy for result of cost_incremental_sort */
5517
5519
5520 cost_incremental_sort(&sort_path, root, pathkeys,
5521 plan->nPresortedCols,
5522 plan->sort.plan.disabled_nodes,
5523 lefttree->startup_cost,
5524 lefttree->total_cost,
5525 lefttree->plan_rows,
5526 lefttree->plan_width,
5527 0.0,
5528 work_mem,
5529 limit_tuples);
5530 plan->sort.plan.startup_cost = sort_path.startup_cost;
5531 plan->sort.plan.total_cost = sort_path.total_cost;
5532 plan->sort.plan.plan_rows = lefttree->plan_rows;
5533 plan->sort.plan.plan_width = lefttree->plan_width;
5534 plan->sort.plan.parallel_aware = false;
5535 plan->sort.plan.parallel_safe = lefttree->parallel_safe;
5536}
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:132

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

Referenced by create_mergejoin_plan().

◆ label_sort_with_costsize()

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

Definition at line 5484 of file createplan.c.

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

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

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

◆ make_agg()

Agg * make_agg ( List tlist,
List qual,
AggStrategy  aggstrategy,
AggSplit  aggsplit,
int  numGroupCols,
AttrNumber grpColIdx,
Oid grpOperators,
Oid grpCollations,
List groupingSets,
List chain,
double  dNumGroups,
Size  transitionSpace,
Plan lefttree 
)

Definition at line 6662 of file createplan.c.

6667{
6668 Agg *node = makeNode(Agg);
6669 Plan *plan = &node->plan;
6670 long numGroups;
6671
6672 /* Reduce to long, but 'ware overflow! */
6673 numGroups = clamp_cardinality_to_long(dNumGroups);
6674
6675 node->aggstrategy = aggstrategy;
6676 node->aggsplit = aggsplit;
6677 node->numCols = numGroupCols;
6678 node->grpColIdx = grpColIdx;
6679 node->grpOperators = grpOperators;
6680 node->grpCollations = grpCollations;
6681 node->numGroups = numGroups;
6682 node->transitionSpace = transitionSpace;
6683 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6684 node->groupingSets = groupingSets;
6685 node->chain = chain;
6686
6687 plan->qual = qual;
6688 plan->targetlist = tlist;
6689 plan->lefttree = lefttree;
6690 plan->righttree = NULL;
6691
6692 return node;
6693}
AggSplit aggsplit
Definition: plannodes.h:1146
List * chain
Definition: plannodes.h:1173
long numGroups
Definition: plannodes.h:1159
List * groupingSets
Definition: plannodes.h:1170
Bitmapset * aggParams
Definition: plannodes.h:1165
Plan plan
Definition: plannodes.h:1140
int numCols
Definition: plannodes.h:1149
uint64 transitionSpace
Definition: plannodes.h:1162
AggStrategy aggstrategy
Definition: plannodes.h:1143

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

Referenced by create_agg_plan(), create_groupingsets_plan(), and create_unique_plan().

◆ make_bitmap_and()

static BitmapAnd * make_bitmap_and ( List bitmapplans)
static

Definition at line 5984 of file createplan.c.

5985{
5986 BitmapAnd *node = makeNode(BitmapAnd);
5987 Plan *plan = &node->plan;
5988
5989 plan->targetlist = NIL;
5990 plan->qual = NIL;
5991 plan->lefttree = NULL;
5992 plan->righttree = NULL;
5993 node->bitmapplans = bitmapplans;
5994
5995 return node;
5996}
Plan plan
Definition: plannodes.h:451
List * bitmapplans
Definition: plannodes.h:452

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

5696{
5698 Plan *plan = &node->scan.plan;
5699
5700 plan->targetlist = qptlist;
5701 plan->qual = qpqual;
5702 plan->lefttree = lefttree;
5703 plan->righttree = NULL;
5704 node->scan.scanrelid = scanrelid;
5705 node->bitmapqualorig = bitmapqualorig;
5706
5707 return node;
5708}
List * bitmapqualorig
Definition: plannodes.h:653

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

5674{
5676 Plan *plan = &node->scan.plan;
5677
5678 plan->targetlist = NIL; /* not used */
5679 plan->qual = NIL; /* not used */
5680 plan->lefttree = NULL;
5681 plan->righttree = NULL;
5682 node->scan.scanrelid = scanrelid;
5683 node->indexid = indexid;
5684 node->indexqual = indexqual;
5685 node->indexqualorig = indexqualorig;
5686
5687 return node;
5688}
List * indexqualorig
Definition: plannodes.h:637
List * indexqual
Definition: plannodes.h:635

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

6000{
6001 BitmapOr *node = makeNode(BitmapOr);
6002 Plan *plan = &node->plan;
6003
6004 plan->targetlist = NIL;
6005 plan->qual = NIL;
6006 plan->lefttree = NULL;
6007 plan->righttree = NULL;
6008 node->bitmapplans = bitmapplans;
6009
6010 return node;
6011}
List * bitmapplans
Definition: plannodes.h:467
Plan plan
Definition: plannodes.h:465

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

5833{
5834 CteScan *node = makeNode(CteScan);
5835 Plan *plan = &node->scan.plan;
5836
5837 plan->targetlist = qptlist;
5838 plan->qual = qpqual;
5839 plan->lefttree = NULL;
5840 plan->righttree = NULL;
5841 node->scan.scanrelid = scanrelid;
5842 node->ctePlanId = ctePlanId;
5843 node->cteParam = cteParam;
5844
5845 return node;
5846}
int ctePlanId
Definition: plannodes.h:762
int cteParam
Definition: plannodes.h:764

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

5896{
5898 Plan *plan = &node->scan.plan;
5899
5900 /* cost will be filled in by create_foreignscan_plan */
5901 plan->targetlist = qptlist;
5902 plan->qual = qpqual;
5903 plan->lefttree = outer_plan;
5904 plan->righttree = NULL;
5905 node->scan.scanrelid = scanrelid;
5906
5907 /* these may be overridden by the FDW's PlanDirectModify callback. */
5908 node->operation = CMD_SELECT;
5909 node->resultRelation = 0;
5910
5911 /* checkAsUser, fs_server will be filled in by create_foreignscan_plan */
5912 node->checkAsUser = InvalidOid;
5913 node->fs_server = InvalidOid;
5914 node->fdw_exprs = fdw_exprs;
5915 node->fdw_private = fdw_private;
5916 node->fdw_scan_tlist = fdw_scan_tlist;
5917 node->fdw_recheck_quals = fdw_recheck_quals;
5918 /* fs_relids, fs_base_relids will be filled by create_foreignscan_plan */
5919 node->fs_relids = NULL;
5920 node->fs_base_relids = NULL;
5921 /* fsSystemCol will be filled in by create_foreignscan_plan */
5922 node->fsSystemCol = false;
5923
5924 return node;
5925}
@ CMD_SELECT
Definition: nodes.h:271
CmdType operation
Definition: plannodes.h:833
List * fdw_private
Definition: plannodes.h:843
Index resultRelation
Definition: plannodes.h:835
List * fdw_scan_tlist
Definition: plannodes.h:845

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

5774{
5776 Plan *plan = &node->scan.plan;
5777
5778 plan->targetlist = qptlist;
5779 plan->qual = qpqual;
5780 plan->lefttree = NULL;
5781 plan->righttree = NULL;
5782 node->scan.scanrelid = scanrelid;
5783 node->functions = functions;
5784 node->funcordinality = funcordinality;
5785
5786 return node;
5787}
List * functions
Definition: plannodes.h:727
bool funcordinality
Definition: plannodes.h:729

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

6927{
6928 Gather *node = makeNode(Gather);
6929 Plan *plan = &node->plan;
6930
6931 plan->targetlist = qptlist;
6932 plan->qual = qpqual;
6933 plan->lefttree = subplan;
6934 plan->righttree = NULL;
6935 node->num_workers = nworkers;
6936 node->rescan_param = rescan_param;
6937 node->single_copy = single_copy;
6938 node->invisible = false;
6939 node->initParam = NULL;
6940
6941 return node;
6942}
int num_workers
Definition: plannodes.h:1289
bool invisible
Definition: plannodes.h:1295
Bitmapset * initParam
Definition: plannodes.h:1301
bool single_copy
Definition: plannodes.h:1293
int rescan_param
Definition: plannodes.h:1291

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

Referenced by create_gather_plan().

◆ make_group()

static Group * make_group ( List tlist,
List qual,
int  numGroupCols,
AttrNumber grpColIdx,
Oid grpOperators,
Oid grpCollations,
Plan lefttree 
)
static

Definition at line 6736 of file createplan.c.

6743{
6744 Group *node = makeNode(Group);
6745 Plan *plan = &node->plan;
6746
6747 node->numCols = numGroupCols;
6748 node->grpColIdx = grpColIdx;
6749 node->grpOperators = grpOperators;
6750 node->grpCollations = grpCollations;
6751
6752 plan->qual = qual;
6753 plan->targetlist = tlist;
6754 plan->lefttree = lefttree;
6755 plan->righttree = NULL;
6756
6757 return node;
6758}
int numCols
Definition: plannodes.h:1114
Plan plan
Definition: plannodes.h:1111

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

6075{
6076 Hash *node = makeNode(Hash);
6077 Plan *plan = &node->plan;
6078
6079 plan->targetlist = lefttree->targetlist;
6080 plan->qual = NIL;
6081 plan->lefttree = lefttree;
6082 plan->righttree = NULL;
6083
6084 node->hashkeys = hashkeys;
6085 node->skewTable = skewTable;
6086 node->skewColumn = skewColumn;
6087 node->skewInherit = skewInherit;
6088
6089 return node;
6090}
AttrNumber skewColumn
Definition: plannodes.h:1363
List * hashkeys
Definition: plannodes.h:1359
Oid skewTable
Definition: plannodes.h:1361
bool skewInherit
Definition: plannodes.h:1365

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

6050{
6051 HashJoin *node = makeNode(HashJoin);
6052 Plan *plan = &node->join.plan;
6053
6054 plan->targetlist = tlist;
6055 plan->qual = otherclauses;
6056 plan->lefttree = lefttree;
6057 plan->righttree = righttree;
6058 node->hashclauses = hashclauses;
6059 node->hashoperators = hashoperators;
6060 node->hashcollations = hashcollations;
6061 node->hashkeys = hashkeys;
6062 node->join.jointype = jointype;
6063 node->join.inner_unique = inner_unique;
6064 node->join.joinqual = joinclauses;
6065
6066 return node;
6067}
List * hashcollations
Definition: plannodes.h:1008
List * hashclauses
Definition: plannodes.h:1006
List * hashoperators
Definition: plannodes.h:1007
List * hashkeys
Definition: plannodes.h:1014
List * joinqual
Definition: plannodes.h:931
JoinType jointype
Definition: plannodes.h:928
bool inner_unique
Definition: plannodes.h:929

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

6168{
6169 IncrementalSort *node;
6170 Plan *plan;
6171
6172 node = makeNode(IncrementalSort);
6173
6174 plan = &node->sort.plan;
6175 plan->targetlist = lefttree->targetlist;
6176 plan->qual = NIL;
6177 plan->lefttree = lefttree;
6178 plan->righttree = NULL;
6179 node->nPresortedCols = nPresortedCols;
6180 node->sort.numCols = numCols;
6181 node->sort.sortColIdx = sortColIdx;
6182 node->sort.sortOperators = sortOperators;
6183 node->sort.collations = collations;
6184 node->sort.nullsFirst = nullsFirst;
6185
6186 return node;
6187}
int numCols
Definition: plannodes.h:1077
Plan plan
Definition: plannodes.h:1074

References makeNode, NIL, IncrementalSort::nPresortedCols, Sort::numCols, Sort::plan, plan, IncrementalSort::sort, and Plan::targetlist.

Referenced by make_incrementalsort_from_pathkeys().

◆ make_incrementalsort_from_pathkeys()

static IncrementalSort * make_incrementalsort_from_pathkeys ( Plan lefttree,
List pathkeys,
Relids  relids,
int  nPresortedCols 
)
static

Definition at line 6448 of file createplan.c.

6450{
6451 int numsortkeys;
6452 AttrNumber *sortColIdx;
6453 Oid *sortOperators;
6454 Oid *collations;
6455 bool *nullsFirst;
6456
6457 /* Compute sort column info, and adjust lefttree as needed */
6458 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6459 relids,
6460 NULL,
6461 false,
6462 &numsortkeys,
6463 &sortColIdx,
6464 &sortOperators,
6465 &collations,
6466 &nullsFirst);
6467
6468 /* Now build the Sort node */
6469 return make_incrementalsort(lefttree, numsortkeys, nPresortedCols,
6470 sortColIdx, sortOperators,
6471 collations, nullsFirst);
6472}
static IncrementalSort * make_incrementalsort(Plan *lefttree, int numCols, int nPresortedCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:6165

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

5650{
5652 Plan *plan = &node->scan.plan;
5653
5654 plan->targetlist = qptlist;
5655 plan->qual = qpqual;
5656 plan->lefttree = NULL;
5657 plan->righttree = NULL;
5658 node->scan.scanrelid = scanrelid;
5659 node->indexid = indexid;
5660 node->indexqual = indexqual;
5661 node->recheckqual = recheckqual;
5662 node->indexorderby = indexorderby;
5663 node->indextlist = indextlist;
5664 node->indexorderdir = indexscandir;
5665
5666 return node;
5667}
List * indexqual
Definition: plannodes.h:599
List * recheckqual
Definition: plannodes.h:601
List * indextlist
Definition: plannodes.h:605
ScanDirection indexorderdir
Definition: plannodes.h:607
List * indexorderby
Definition: plannodes.h:603

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

5620{
5621 IndexScan *node = makeNode(IndexScan);
5622 Plan *plan = &node->scan.plan;
5623
5624 plan->targetlist = qptlist;
5625 plan->qual = qpqual;
5626 plan->lefttree = NULL;
5627 plan->righttree = NULL;
5628 node->scan.scanrelid = scanrelid;
5629 node->indexid = indexid;
5630 node->indexqual = indexqual;
5631 node->indexqualorig = indexqualorig;
5632 node->indexorderby = indexorderby;
5633 node->indexorderbyorig = indexorderbyorig;
5634 node->indexorderbyops = indexorderbyops;
5635 node->indexorderdir = indexscandir;
5636
5637 return node;
5638}
List * indexorderby
Definition: plannodes.h:553
List * indexorderbyops
Definition: plannodes.h:557
ScanDirection indexorderdir
Definition: plannodes.h:559
List * indexorderbyorig
Definition: plannodes.h:555

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

7035{
7036 Limit *node = makeNode(Limit);
7037 Plan *plan = &node->plan;
7038
7039 plan->targetlist = lefttree->targetlist;
7040 plan->qual = NIL;
7041 plan->lefttree = lefttree;
7042 plan->righttree = NULL;
7043
7044 node->limitOffset = limitOffset;
7045 node->limitCount = limitCount;
7046 node->limitOption = limitOption;
7047 node->uniqNumCols = uniqNumCols;
7048 node->uniqColIdx = uniqColIdx;
7049 node->uniqOperators = uniqOperators;
7050 node->uniqCollations = uniqCollations;
7051
7052 return node;
7053}
LimitOption limitOption
Definition: plannodes.h:1438
Plan plan
Definition: plannodes.h:1429
Node * limitCount
Definition: plannodes.h:1435
int uniqNumCols
Definition: plannodes.h:1441
Node * limitOffset
Definition: plannodes.h:1432

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

7012{
7013 LockRows *node = makeNode(LockRows);
7014 Plan *plan = &node->plan;
7015
7016 plan->targetlist = lefttree->targetlist;
7017 plan->qual = NIL;
7018 plan->lefttree = lefttree;
7019 plan->righttree = NULL;
7020
7021 node->rowMarks = rowMarks;
7022 node->epqParam = epqParam;
7023
7024 return node;
7025}
int epqParam
Definition: plannodes.h:1417
List * rowMarks
Definition: plannodes.h:1415
Plan plan
Definition: plannodes.h:1413

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

6573{
6574 Material *node = makeNode(Material);
6575 Plan *plan = &node->plan;
6576
6577 plan->targetlist = lefttree->targetlist;
6578 plan->qual = NIL;
6579 plan->lefttree = lefttree;
6580 plan->righttree = NULL;
6581
6582 return node;
6583}
Plan plan
Definition: plannodes.h:1023

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

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

◆ make_memoize()

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

Definition at line 6637 of file createplan.c.

6640{
6641 Memoize *node = makeNode(Memoize);
6642 Plan *plan = &node->plan;
6643
6644 plan->targetlist = lefttree->targetlist;
6645 plan->qual = NIL;
6646 plan->lefttree = lefttree;
6647 plan->righttree = NULL;
6648
6649 node->numKeys = list_length(param_exprs);
6650 node->hashOperators = hashoperators;
6651 node->collations = collations;
6652 node->param_exprs = param_exprs;
6653 node->singlerow = singlerow;
6654 node->binary_mode = binary_mode;
6655 node->est_entries = est_entries;
6656 node->keyparamids = keyparamids;
6657
6658 return node;
6659}
Plan plan
Definition: plannodes.h:1032
bool singlerow
Definition: plannodes.h:1050
Bitmapset * keyparamids
Definition: plannodes.h:1065
bool binary_mode
Definition: plannodes.h:1056
int numKeys
Definition: plannodes.h:1035
List * param_exprs
Definition: plannodes.h:1044
uint32 est_entries
Definition: plannodes.h:1062

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

Referenced by create_memoize_plan().

◆ make_mergejoin()

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

Definition at line 6093 of file createplan.c.

6106{
6107 MergeJoin *node = makeNode(MergeJoin);
6108 Plan *plan = &node->join.plan;
6109
6110 plan->targetlist = tlist;
6111 plan->qual = otherclauses;
6112 plan->lefttree = lefttree;
6113 plan->righttree = righttree;
6114 node->skip_mark_restore = skip_mark_restore;
6115 node->mergeclauses = mergeclauses;
6116 node->mergeFamilies = mergefamilies;
6117 node->mergeCollations = mergecollations;
6118 node->mergeReversals = mergereversals;
6119 node->mergeNullsFirst = mergenullsfirst;
6120 node->join.jointype = jointype;
6121 node->join.inner_unique = inner_unique;
6122 node->join.joinqual = joinclauses;
6123
6124 return node;
6125}
List * mergeclauses
Definition: plannodes.h:982
bool skip_mark_restore
Definition: plannodes.h:979

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

7110{
7112 bool returning_old_or_new = false;
7113 bool returning_old_or_new_valid = false;
7114 List *fdw_private_list;
7115 Bitmapset *direct_modify_plans;
7116 ListCell *lc;
7117 int i;
7118
7119 Assert(operation == CMD_MERGE ||
7120 (operation == CMD_UPDATE ?
7121 list_length(resultRelations) == list_length(updateColnosLists) :
7122 updateColnosLists == NIL));
7123 Assert(withCheckOptionLists == NIL ||
7124 list_length(resultRelations) == list_length(withCheckOptionLists));
7125 Assert(returningLists == NIL ||
7126 list_length(resultRelations) == list_length(returningLists));
7127
7128 node->plan.lefttree = subplan;
7129 node->plan.righttree = NULL;
7130 node->plan.qual = NIL;
7131 /* setrefs.c will fill in the targetlist, if needed */
7132 node->plan.targetlist = NIL;
7133
7134 node->operation = operation;
7135 node->canSetTag = canSetTag;
7136 node->nominalRelation = nominalRelation;
7137 node->rootRelation = rootRelation;
7138 node->partColsUpdated = partColsUpdated;
7139 node->resultRelations = resultRelations;
7140 if (!onconflict)
7141 {
7143 node->onConflictSet = NIL;
7144 node->onConflictCols = NIL;
7145 node->onConflictWhere = NULL;
7146 node->arbiterIndexes = NIL;
7147 node->exclRelRTI = 0;
7148 node->exclRelTlist = NIL;
7149 }
7150 else
7151 {
7152 node->onConflictAction = onconflict->action;
7153
7154 /*
7155 * Here we convert the ON CONFLICT UPDATE tlist, if any, to the
7156 * executor's convention of having consecutive resno's. The actual
7157 * target column numbers are saved in node->onConflictCols. (This
7158 * could be done earlier, but there seems no need to.)
7159 */
7160 node->onConflictSet = onconflict->onConflictSet;
7161 node->onConflictCols =
7163 node->onConflictWhere = onconflict->onConflictWhere;
7164
7165 /*
7166 * If a set of unique index inference elements was provided (an
7167 * INSERT...ON CONFLICT "inference specification"), then infer
7168 * appropriate unique indexes (or throw an error if none are
7169 * available).
7170 */
7172
7173 node->exclRelRTI = onconflict->exclRelIndex;
7174 node->exclRelTlist = onconflict->exclRelTlist;
7175 }
7176 node->updateColnosLists = updateColnosLists;
7177 node->withCheckOptionLists = withCheckOptionLists;
7178 node->returningOldAlias = root->parse->returningOldAlias;
7179 node->returningNewAlias = root->parse->returningNewAlias;
7180 node->returningLists = returningLists;
7181 node->rowMarks = rowMarks;
7182 node->mergeActionLists = mergeActionLists;
7183 node->mergeJoinConditions = mergeJoinConditions;
7184 node->epqParam = epqParam;
7185
7186 /*
7187 * For each result relation that is a foreign table, allow the FDW to
7188 * construct private plan data, and accumulate it all into a list.
7189 */
7190 fdw_private_list = NIL;
7191 direct_modify_plans = NULL;
7192 i = 0;
7193 foreach(lc, resultRelations)
7194 {
7195 Index rti = lfirst_int(lc);
7196 FdwRoutine *fdwroutine;
7197 List *fdw_private;
7198 bool direct_modify;
7199
7200 /*
7201 * If possible, we want to get the FdwRoutine from our RelOptInfo for
7202 * the table. But sometimes we don't have a RelOptInfo and must get
7203 * it the hard way. (In INSERT, the target relation is not scanned,
7204 * so it's not a baserel; and there are also corner cases for
7205 * updatable views where the target rel isn't a baserel.)
7206 */
7207 if (rti < root->simple_rel_array_size &&
7208 root->simple_rel_array[rti] != NULL)
7209 {
7210 RelOptInfo *resultRel = root->simple_rel_array[rti];
7211
7212 fdwroutine = resultRel->fdwroutine;
7213 }
7214 else
7215 {
7216 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7217
7218 if (rte->rtekind == RTE_RELATION &&
7219 rte->relkind == RELKIND_FOREIGN_TABLE)
7220 {
7221 /* Check if the access to foreign tables is restricted */
7223 {
7224 /* there must not be built-in foreign tables */
7225 Assert(rte->relid >= FirstNormalObjectId);
7226 ereport(ERROR,
7227 (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
7228 errmsg("access to non-system foreign table is restricted")));
7229 }
7230
7231 fdwroutine = GetFdwRoutineByRelId(rte->relid);
7232 }
7233 else
7234 fdwroutine = NULL;
7235 }
7236
7237 /*
7238 * MERGE is not currently supported for foreign tables. We already
7239 * checked that when the table mentioned in the query is foreign; but
7240 * we can still get here if a partitioned table has a foreign table as
7241 * partition. Disallow that now, to avoid an uglier error message
7242 * later.
7243 */
7244 if (operation == CMD_MERGE && fdwroutine != NULL)
7245 {
7246 RangeTblEntry *rte = planner_rt_fetch(rti, root);
7247
7248 ereport(ERROR,
7249 errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
7250 errmsg("cannot execute MERGE on relation \"%s\"",
7251 get_rel_name(rte->relid)),
7252 errdetail_relkind_not_supported(rte->relkind));
7253 }
7254
7255 /*
7256 * Try to modify the foreign table directly if (1) the FDW provides
7257 * callback functions needed for that and (2) there are no local
7258 * structures that need to be run for each modified row: row-level
7259 * triggers on the foreign table, stored generated columns, WITH CHECK
7260 * OPTIONs from parent views, or Vars returning OLD/NEW in the
7261 * RETURNING list.
7262 */
7263 direct_modify = false;
7264 if (fdwroutine != NULL &&
7265 fdwroutine->PlanDirectModify != NULL &&
7266 fdwroutine->BeginDirectModify != NULL &&
7267 fdwroutine->IterateDirectModify != NULL &&
7268 fdwroutine->EndDirectModify != NULL &&
7269 withCheckOptionLists == NIL &&
7270 !has_row_triggers(root, rti, operation) &&
7272 {
7273 /* returning_old_or_new is the same for all result relations */
7274 if (!returning_old_or_new_valid)
7275 {
7276 returning_old_or_new =
7278 root->parse->returningList);
7279 returning_old_or_new_valid = true;
7280 }
7281 if (!returning_old_or_new)
7282 direct_modify = fdwroutine->PlanDirectModify(root, node, rti, i);
7283 }
7284 if (direct_modify)
7285 direct_modify_plans = bms_add_member(direct_modify_plans, i);
7286
7287 if (!direct_modify &&
7288 fdwroutine != NULL &&
7289 fdwroutine->PlanForeignModify != NULL)
7290 fdw_private = fdwroutine->PlanForeignModify(root, node, rti, i);
7291 else
7292 fdw_private = NIL;
7293 fdw_private_list = lappend(fdw_private_list, fdw_private);
7294 i++;
7295 }
7296 node->fdwPrivLists = fdw_private_list;
7297 node->fdwDirectModifyPlans = direct_modify_plans;
7298
7299 return node;
7300}
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:815
#define unlikely(x)
Definition: c.h:347
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#define ereport(elevel,...)
Definition: elog.h:149
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:419
char * get_rel_name(Oid relid)
Definition: lsyscache.c:2068
@ ONCONFLICT_NONE
Definition: nodes.h:424
@ CMD_MERGE
Definition: nodes.h:275
@ CMD_UPDATE
Definition: nodes.h:272
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
bool has_stored_generated_columns(PlannerInfo *root, Index rti)
Definition: plancat.c:2312
bool has_row_triggers(PlannerInfo *root, Index rti, CmdType event)
Definition: plancat.c:2262
List * infer_arbiter_indexes(PlannerInfo *root)
Definition: plancat.c:707
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:304
Index nominalRelation
Definition: plannodes.h:296
List * arbiterIndexes
Definition: plannodes.h:324
List * onConflictCols
Definition: plannodes.h:328
List * mergeJoinConditions
Definition: plannodes.h:338
char * returningOldAlias
Definition: plannodes.h:308
char * returningNewAlias
Definition: plannodes.h:310
CmdType operation
Definition: plannodes.h:292
int epqParam
Definition: plannodes.h:320
List * resultRelations
Definition: plannodes.h:302
Bitmapset * fdwDirectModifyPlans
Definition: plannodes.h:316
List * onConflictSet
Definition: plannodes.h:326
List * exclRelTlist
Definition: plannodes.h:334
List * mergeActionLists
Definition: plannodes.h:336
bool canSetTag
Definition: plannodes.h:294
List * fdwPrivLists
Definition: plannodes.h:314
bool partColsUpdated
Definition: plannodes.h:300
List * returningLists
Definition: plannodes.h:312
List * withCheckOptionLists
Definition: plannodes.h:306
Index rootRelation
Definition: plannodes.h:298
Node * onConflictWhere
Definition: plannodes.h:330
List * rowMarks
Definition: plannodes.h:318
OnConflictAction onConflictAction
Definition: plannodes.h:322
Index exclRelRTI
Definition: plannodes.h:332
OnConflictAction action
Definition: primnodes.h:2353
List * onConflictSet
Definition: primnodes.h:2362
List * exclRelTlist
Definition: primnodes.h:2365
Node * onConflictWhere
Definition: primnodes.h:2363
struct Plan * righttree
Definition: plannodes.h:214
List * qual
Definition: plannodes.h:211
#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(), 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 5849 of file createplan.c.

5853{
5855 Plan *plan = &node->scan.plan;
5856
5857 /* cost should be inserted by caller */
5858 plan->targetlist = qptlist;
5859 plan->qual = qpqual;
5860 plan->lefttree = NULL;
5861 plan->righttree = NULL;
5862 node->scan.scanrelid = scanrelid;
5863 node->enrname = enrname;
5864
5865 return node;
5866}

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

6022{
6023 NestLoop *node = makeNode(NestLoop);
6024 Plan *plan = &node->join.plan;
6025
6026 plan->targetlist = tlist;
6027 plan->qual = otherclauses;
6028 plan->lefttree = lefttree;
6029 plan->righttree = righttree;
6030 node->join.jointype = jointype;
6031 node->join.inner_unique = inner_unique;
6032 node->join.joinqual = joinclauses;
6033 node->nestParams = nestParams;
6034
6035 return node;
6036}
List * nestParams
Definition: plannodes.h:949

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

Referenced by create_nestloop_plan().

◆ make_project_set()

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

Definition at line 7081 of file createplan.c.

7083{
7085 Plan *plan = &node->plan;
7086
7087 plan->targetlist = tlist;
7088 plan->qual = NIL;
7089 plan->lefttree = subplan;
7090 plan->righttree = NULL;
7091
7092 return node;
7093}
Plan plan
Definition: plannodes.h:269

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

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

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

Referenced by create_recursiveunion_plan().

◆ make_result()

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

Definition at line 7060 of file createplan.c.

7063{
7064 Result *node = makeNode(Result);
7065 Plan *plan = &node->plan;
7066
7067 plan->targetlist = tlist;
7068 plan->qual = NIL;
7069 plan->lefttree = subplan;
7070 plan->righttree = NULL;
7071 node->resconstantqual = resconstantqual;
7072
7073 return node;
7074}

References makeNode, NIL, Result::plan, plan, and Result::resconstantqual.

Referenced by create_append_plan(), create_gating_plan(), create_group_result_plan(), create_minmaxagg_plan(), create_projection_plan(), create_resultscan_plan(), and inject_projection_plan().

◆ make_samplescan()

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

Definition at line 5591 of file createplan.c.

5595{
5597 Plan *plan = &node->scan.plan;
5598
5599 plan->targetlist = qptlist;
5600 plan->qual = qpqual;
5601 plan->lefttree = NULL;
5602 plan->righttree = NULL;
5603 node->scan.scanrelid = scanrelid;
5604 node->tablesample = tsc;
5605
5606 return node;
5607}
struct TableSampleClause * tablesample
Definition: plannodes.h:503

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

5577{
5578 SeqScan *node = makeNode(SeqScan);
5579 Plan *plan = &node->scan.plan;
5580
5581 plan->targetlist = qptlist;
5582 plan->qual = qpqual;
5583 plan->lefttree = NULL;
5584 plan->righttree = NULL;
5585 node->scan.scanrelid = scanrelid;
5586
5587 return node;
5588}

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

6953{
6954 SetOp *node = makeNode(SetOp);
6955 Plan *plan = &node->plan;
6956 int numCols = list_length(groupList);
6957 int keyno = 0;
6958 AttrNumber *cmpColIdx;
6959 Oid *cmpOperators;
6960 Oid *cmpCollations;
6961 bool *cmpNullsFirst;
6962 ListCell *slitem;
6963
6964 plan->targetlist = tlist;
6965 plan->qual = NIL;
6966 plan->lefttree = lefttree;
6967 plan->righttree = righttree;
6968
6969 /*
6970 * convert SortGroupClause list into arrays of attr indexes and comparison
6971 * operators, as wanted by executor
6972 */
6973 cmpColIdx = (AttrNumber *) palloc(sizeof(AttrNumber) * numCols);
6974 cmpOperators = (Oid *) palloc(sizeof(Oid) * numCols);
6975 cmpCollations = (Oid *) palloc(sizeof(Oid) * numCols);
6976 cmpNullsFirst = (bool *) palloc(sizeof(bool) * numCols);
6977
6978 foreach(slitem, groupList)
6979 {
6980 SortGroupClause *sortcl = (SortGroupClause *) lfirst(slitem);
6981 TargetEntry *tle = get_sortgroupclause_tle(sortcl, plan->targetlist);
6982
6983 cmpColIdx[keyno] = tle->resno;
6984 if (strategy == SETOP_HASHED)
6985 cmpOperators[keyno] = sortcl->eqop;
6986 else
6987 cmpOperators[keyno] = sortcl->sortop;
6988 Assert(OidIsValid(cmpOperators[keyno]));
6989 cmpCollations[keyno] = exprCollation((Node *) tle->expr);
6990 cmpNullsFirst[keyno] = sortcl->nulls_first;
6991 keyno++;
6992 }
6993
6994 node->cmd = cmd;
6995 node->strategy = strategy;
6996 node->numCols = numCols;
6997 node->cmpColIdx = cmpColIdx;
6998 node->cmpOperators = cmpOperators;
6999 node->cmpCollations = cmpCollations;
7000 node->cmpNullsFirst = cmpNullsFirst;
7001 node->numGroups = numGroups;
7002
7003 return node;
7004}
@ SETOP_HASHED
Definition: nodes.h:413
SetOpStrategy strategy
Definition: plannodes.h:1383
SetOpCmd cmd
Definition: plannodes.h:1380
int numCols
Definition: plannodes.h:1386
Plan plan
Definition: plannodes.h:1377
long numGroups
Definition: plannodes.h:1399

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

6137{
6138 Sort *node;
6139 Plan *plan;
6140
6141 node = makeNode(Sort);
6142
6143 plan = &node->plan;
6144 plan->targetlist = lefttree->targetlist;
6145 plan->disabled_nodes = lefttree->disabled_nodes + (enable_sort == false);
6146 plan->qual = NIL;
6147 plan->lefttree = lefttree;
6148 plan->righttree = NULL;
6149 node->numCols = numCols;
6150 node->sortColIdx = sortColIdx;
6151 node->sortOperators = sortOperators;
6152 node->collations = collations;
6153 node->nullsFirst = nullsFirst;
6154
6155 return node;
6156}
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 6531 of file createplan.c.

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

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

6414{
6415 int numsortkeys;
6416 AttrNumber *sortColIdx;
6417 Oid *sortOperators;
6418 Oid *collations;
6419 bool *nullsFirst;
6420
6421 /* Compute sort column info, and adjust lefttree as needed */
6422 lefttree = prepare_sort_from_pathkeys(lefttree, pathkeys,
6423 relids,
6424 NULL,
6425 false,
6426 &numsortkeys,
6427 &sortColIdx,
6428 &sortOperators,
6429 &collations,
6430 &nullsFirst);
6431
6432 /* Now build the Sort node */
6433 return make_sort(lefttree, numsortkeys,
6434 sortColIdx, sortOperators,
6435 collations, nullsFirst);
6436}

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

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

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

Referenced by create_unique_plan().

◆ make_subqueryscan()

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

Definition at line 5749 of file createplan.c.

5753{
5755 Plan *plan = &node->scan.plan;
5756
5757 plan->targetlist = qptlist;
5758 plan->qual = qpqual;
5759 plan->lefttree = NULL;
5760 plan->righttree = NULL;
5761 node->scan.scanrelid = scanrelid;
5762 node->subplan = subplan;
5764
5765 return node;
5766}
@ SUBQUERY_SCAN_UNKNOWN
Definition: plannodes.h:707
SubqueryScanStatus scanstatus
Definition: plannodes.h:716
Plan * subplan
Definition: plannodes.h:715

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

5794{
5796 Plan *plan = &node->scan.plan;
5797
5798 plan->targetlist = qptlist;
5799 plan->qual = qpqual;
5800 plan->lefttree = NULL;
5801 plan->righttree = NULL;
5802 node->scan.scanrelid = scanrelid;
5803 node->tablefunc = tablefunc;
5804
5805 return node;
5806}
TableFunc * tablefunc
Definition: plannodes.h:751

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

5734{
5736 Plan *plan = &node->scan.plan;
5737
5738 plan->targetlist = qptlist;
5739 plan->qual = qpqual;
5740 plan->lefttree = NULL;
5741 plan->righttree = NULL;
5742 node->scan.scanrelid = scanrelid;
5743 node->tidrangequals = tidrangequals;
5744
5745 return node;
5746}
List * tidrangequals
Definition: plannodes.h:682

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

5715{
5716 TidScan *node = makeNode(TidScan);
5717 Plan *plan = &node->scan.plan;
5718
5719 plan->targetlist = qptlist;
5720 plan->qual = qpqual;
5721 plan->lefttree = NULL;
5722 plan->righttree = NULL;
5723 node->scan.scanrelid = scanrelid;
5724 node->tidquals = tidquals;
5725
5726 return node;
5727}
List * tidquals
Definition: plannodes.h:668

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

Referenced by create_tidscan_plan().

◆ make_unique_from_pathkeys()

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

Definition at line 6815 of file createplan.c.

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

◆ make_unique_from_sortclauses()

static Unique * make_unique_from_sortclauses ( Plan lefttree,
List distinctList 
)
static

Definition at line 6766 of file createplan.c.

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

References Assert(), SortGroupClause::eqop, TargetEntry::expr, exprCollation(), get_sortgroupclause_tle(), lfirst, list_length(), makeNode, NIL, Unique::numCols, OidIsValid, palloc(), Unique::plan, plan, TargetEntry::resno, and Plan::targetlist.

Referenced by create_unique_plan().

◆ make_valuesscan()

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

Definition at line 5809 of file createplan.c.

5813{
5815 Plan *plan = &node->scan.plan;
5816
5817 plan->targetlist = qptlist;
5818 plan->qual = qpqual;
5819 plan->lefttree = NULL;
5820 plan->righttree = NULL;
5821 node->scan.scanrelid = scanrelid;
5822 node->values_lists = values_lists;
5823
5824 return node;
5825}
List * values_lists
Definition: plannodes.h:740

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

6700{
6701 WindowAgg *node = makeNode(WindowAgg);
6702 Plan *plan = &node->plan;
6703
6704 node->winname = wc->name;
6705 node->winref = wc->winref;
6706 node->partNumCols = partNumCols;
6707 node->partColIdx = partColIdx;
6708 node->partOperators = partOperators;
6709 node->partCollations = partCollations;
6710 node->ordNumCols = ordNumCols;
6711 node->ordColIdx = ordColIdx;
6712 node->ordOperators = ordOperators;
6713 node->ordCollations = ordCollations;
6714 node->frameOptions = wc->frameOptions;
6715 node->startOffset = wc->startOffset;
6716 node->endOffset = wc->endOffset;
6717 node->runCondition = runCondition;
6718 /* a duplicate of the above for EXPLAIN */
6719 node->runConditionOrig = runCondition;
6720 node->startInRangeFunc = wc->startInRangeFunc;
6721 node->endInRangeFunc = wc->endInRangeFunc;
6722 node->inRangeColl = wc->inRangeColl;
6723 node->inRangeAsc = wc->inRangeAsc;
6724 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6725 node->topWindow = topWindow;
6726
6727 plan->targetlist = tlist;
6728 plan->lefttree = lefttree;
6729 plan->righttree = NULL;
6730 plan->qual = qual;
6731
6732 return node;
6733}
char * winname
Definition: plannodes.h:1185
int partNumCols
Definition: plannodes.h:1191
Oid endInRangeFunc
Definition: plannodes.h:1235
Node * endOffset
Definition: plannodes.h:1221
bool topWindow
Definition: plannodes.h:1250
Plan plan
Definition: plannodes.h:1182
List * runConditionOrig
Definition: plannodes.h:1227
Oid inRangeColl
Definition: plannodes.h:1238
Node * startOffset
Definition: plannodes.h:1218
List * runCondition
Definition: plannodes.h:1224
Oid startInRangeFunc
Definition: plannodes.h:1232
bool inRangeAsc
Definition: plannodes.h:1241
Index winref
Definition: plannodes.h:1188
bool inRangeNullsFirst
Definition: plannodes.h:1244
int ordNumCols
Definition: plannodes.h:1203
int frameOptions
Definition: plannodes.h:1215
Node * startOffset
Definition: parsenodes.h:1561
Node * endOffset
Definition: parsenodes.h:1562

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

5873{
5875 Plan *plan = &node->scan.plan;
5876
5877 plan->targetlist = qptlist;
5878 plan->qual = qpqual;
5879 plan->lefttree = NULL;
5880 plan->righttree = NULL;
5881 node->scan.scanrelid = scanrelid;
5882 node->wtParam = wtParam;
5883
5884 return node;
5885}

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

Referenced by create_worktablescan_plan().

◆ mark_async_capable_plan()

static bool mark_async_capable_plan ( Plan plan,
Path path 
)
static

Definition at line 1140 of file createplan.c.

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

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

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

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

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

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

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

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

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

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