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

Go to the source code of this file.

Macros

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

Functions

static Plancreate_plan_recurse (PlannerInfo *root, Path *best_path, int flags)
 
static Plancreate_scan_plan (PlannerInfo *root, Path *best_path, int flags)
 
static Listbuild_path_tlist (PlannerInfo *root, Path *path)
 
static bool use_physical_tlist (PlannerInfo *root, Path *path, int flags)
 
static Listget_gating_quals (PlannerInfo *root, List *quals)
 
static Plancreate_gating_plan (PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
 
static Plancreate_join_plan (PlannerInfo *root, JoinPath *best_path)
 
static bool mark_async_capable_plan (Plan *plan, Path *path)
 
static Plancreate_append_plan (PlannerInfo *root, AppendPath *best_path, int flags)
 
static Plancreate_merge_append_plan (PlannerInfo *root, MergeAppendPath *best_path, int flags)
 
static Resultcreate_group_result_plan (PlannerInfo *root, GroupResultPath *best_path)
 
static ProjectSetcreate_project_set_plan (PlannerInfo *root, ProjectSetPath *best_path)
 
static Materialcreate_material_plan (PlannerInfo *root, MaterialPath *best_path, int flags)
 
static Memoizecreate_memoize_plan (PlannerInfo *root, MemoizePath *best_path, int flags)
 
static 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 5547 of file createplan.c.

5548{
5549 if (IsA(plan, BitmapAnd))
5551 else if (IsA(plan, BitmapOr))
5552 {
5553 ((BitmapOr *) plan)->isshared = true;
5554 bitmap_subplan_mark_shared(linitial(((BitmapOr *) plan)->bitmapplans));
5555 }
5556 else if (IsA(plan, BitmapIndexScan))
5557 ((BitmapIndexScan *) plan)->isshared = true;
5558 else
5559 elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
5560}
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:5547
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#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:4976
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:7360
static Plan * inject_projection_plan(Plan *subplan, List *tlist, bool parallel_safe)
Definition: createplan.c:2117
bool parallel_safe
Definition: plannodes.h:188
List * targetlist
Definition: plannodes.h:202
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 5448 of file createplan.c.

5449{
5450 dest->disabled_nodes = src->disabled_nodes;
5451 dest->startup_cost = src->startup_cost;
5452 dest->total_cost = src->total_cost;
5453 dest->plan_rows = src->rows;
5454 dest->plan_width = src->pathtarget->width;
5455 dest->parallel_aware = src->parallel_aware;
5456 dest->parallel_safe = src->parallel_safe;
5457}
Cardinality rows
Definition: pathnodes.h:1793
Cost startup_cost
Definition: pathnodes.h:1795
int disabled_nodes
Definition: pathnodes.h:1794
Cost total_cost
Definition: pathnodes.h:1796
bool parallel_aware
Definition: pathnodes.h:1786
bool parallel_safe
Definition: pathnodes.h:1788

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

5465{
5466 dest->disabled_nodes = src->disabled_nodes;
5467 dest->startup_cost = src->startup_cost;
5468 dest->total_cost = src->total_cost;
5469 dest->plan_rows = src->plan_rows;
5470 dest->plan_width = src->plan_width;
5471 /* Assume the inserted node is not parallel-aware. */
5472 dest->parallel_aware = false;
5473 /* Assume the inserted node is parallel-safe, if child plan is. */
5474 dest->parallel_safe = src->parallel_safe;
5475}
Cost total_cost
Definition: plannodes.h:172
Cost startup_cost
Definition: plannodes.h:170
int plan_width
Definition: plannodes.h:180
Cardinality plan_rows
Definition: plannodes.h:178
int disabled_nodes
Definition: plannodes.h:168

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:5354
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:5448
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:6665
#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:2396
Cardinality numGroups
Definition: pathnodes.h:2399
AggSplit aggsplit
Definition: pathnodes.h:2398
List * groupClause
Definition: pathnodes.h:2401
uint64 transitionSpace
Definition: pathnodes.h:2400
AggStrategy aggstrategy
Definition: pathnodes.h:2397
Path path
Definition: pathnodes.h:2395
List * qual
Definition: pathnodes.h:2402
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:7063
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Definition: createplan.c:5487
#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:6137
#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:6234
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:2068
Cardinality limit_tuples
Definition: pathnodes.h:2069
List * subpaths
Definition: pathnodes.h:2066
List * pathkeys
Definition: pathnodes.h:1799
bool async_capable
Definition: plannodes.h:194
List * baserestrictinfo
Definition: pathnodes.h:1009
Relids relids
Definition: pathnodes.h:895

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:5694
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:1919
Expr * clause
Definition: pathnodes.h:2705

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:6002
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
Definition: createplan.c:5673
static BitmapAnd * make_bitmap_and(List *bitmapplans)
Definition: createplan.c:5987
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:1932
List * bitmapquals
Definition: pathnodes.h:1931
Selectivity bitmapselectivity
Definition: pathnodes.h:1945
List * bitmapquals
Definition: pathnodes.h:1944
List * indexquals
Definition: pathnodes.h:1893
struct RestrictInfo * rinfo
Definition: pathnodes.h:1892
List * indpred
Definition: pathnodes.h:1197
List * indexclauses
Definition: pathnodes.h:1845
Path path
Definition: pathnodes.h:1843
Selectivity indexselectivity
Definition: pathnodes.h:1850
Cost indextotalcost
Definition: pathnodes.h:1849
IndexOptInfo * indexinfo
Definition: pathnodes.h:1844
Scan scan
Definition: plannodes.h:538
List * indexqualorig
Definition: plannodes.h:544
Oid indexid
Definition: plannodes.h:540
List * indexqual
Definition: plannodes.h:542
Index scanrelid
Definition: plannodes.h:476

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:5831
@ RTE_CTE
Definition: parsenodes.h:1032
#define planner_rt_fetch(rti, root)
Definition: pathnodes.h:594
#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:753
List * cte_plan_ids
Definition: pathnodes.h:326
List * init_plans
Definition: pathnodes.h:320
Query * parse
Definition: pathnodes.h:223
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:2045
List * custom_paths
Definition: pathnodes.h:2042
Scan scan
Definition: plannodes.h:866
Bitmapset * custom_relids
Definition: plannodes.h:878
List * custom_exprs
Definition: plannodes.h:872

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:855
#define InvalidOid
Definition: postgres_ext.h:35
Path * fdw_outerpath
Definition: pathnodes.h:2004
Oid checkAsUser
Definition: plannodes.h:830
Oid fs_server
Definition: plannodes.h:832
List * fdw_exprs
Definition: plannodes.h:834
bool fsSystemCol
Definition: plannodes.h:846
Bitmapset * fs_relids
Definition: plannodes.h:842
Bitmapset * fs_base_relids
Definition: plannodes.h:844
List * fdw_recheck_quals
Definition: plannodes.h:840
List * exprs
Definition: pathnodes.h:1666
bool useridiscurrent
Definition: pathnodes.h:992
struct PathTarget * reltarget
Definition: pathnodes.h:917
Index relid
Definition: pathnodes.h:942
RelOptKind reloptkind
Definition: pathnodes.h:889
Oid userid
Definition: pathnodes.h:990
Oid serverid
Definition: pathnodes.h:988
RTEKind rtekind
Definition: pathnodes.h:946
#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:5772
@ 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:1309
int num_workers
Definition: plannodes.h:1306
struct Plan * lefttree
Definition: plannodes.h:206

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:6924
bool single_copy
Definition: pathnodes.h:2177
Path * subpath
Definition: pathnodes.h:2176
int num_workers
Definition: pathnodes.h:2178
Plan plan
Definition: plannodes.h:1280

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:5464
Node * resconstantqual
Definition: plannodes.h:251
Plan plan
Definition: plannodes.h:250

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:6739
List * qual
Definition: pathnodes.h:2370
List * groupClause
Definition: pathnodes.h:2369
Path * subpath
Definition: pathnodes.h:2368
Path path
Definition: pathnodes.h:2367

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:6534
void * palloc0(Size size)
Definition: mcxt.c:1351
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:2442
AggStrategy aggstrategy
Definition: pathnodes.h:2439
Cardinality numGroups
Definition: pathnodes.h:2426
List * groupClause
Definition: pathnodes.h:2423
List * gsets
Definition: pathnodes.h:2424
bool is_hashed
Definition: pathnodes.h:2428
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 4787 of file createplan.c.

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

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:5061
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:5102
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:5644
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:5613
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:1200
ScanDirection indexscandir
Definition: pathnodes.h:1848
List * indexorderbys
Definition: pathnodes.h:1846
CompareType pk_cmptype
Definition: pathnodes.h:1603
Oid pk_opfamily
Definition: pathnodes.h:1602

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:4787
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:7035
void * palloc(Size size)
Definition: mcxt.c:1321
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:2542
LimitOption limitOption
Definition: pathnodes.h:2545
Node * limitOffset
Definition: pathnodes.h:2543
Node * limitCount
Definition: pathnodes.h:2544
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:7014
Path * subpath
Definition: pathnodes.h:2502
List * rowMarks
Definition: pathnodes.h:2503

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:6575
Path * subpath
Definition: pathnodes.h:2116

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:6640
#define lfirst_oid(lc)
Definition: pg_list.h:174
bool singlerow
Definition: pathnodes.h:2130
List * hash_operators
Definition: pathnodes.h:2128
uint32 est_entries
Definition: pathnodes.h:2135
bool binary_mode
Definition: pathnodes.h:2132
Path * subpath
Definition: pathnodes.h:2127
List * param_exprs
Definition: pathnodes.h:2129

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:2091
int part_prune_index
Definition: plannodes.h:400
Bitmapset * apprelids
Definition: plannodes.h:374
List * mergeplans
Definition: plannodes.h:376

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

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

Referenced by create_join_plan().

◆ create_minmaxagg_plan()

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

Definition at line 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:3274
List * quals
Definition: pathnodes.h:2452
List * mmaggregates
Definition: pathnodes.h:2451
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:7103
bool partColsUpdated
Definition: pathnodes.h:2522
List * returningLists
Definition: pathnodes.h:2526
List * resultRelations
Definition: pathnodes.h:2523
List * withCheckOptionLists
Definition: pathnodes.h:2525
List * mergeJoinConditions
Definition: pathnodes.h:2532
List * updateColnosLists
Definition: pathnodes.h:2524
OnConflictExpr * onconflict
Definition: pathnodes.h:2528
CmdType operation
Definition: pathnodes.h:2518
Index rootRelation
Definition: pathnodes.h:2521
Index nominalRelation
Definition: pathnodes.h:2520
List * mergeActionLists
Definition: pathnodes.h:2530
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:5852
@ 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:6017
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:4272
Join join
Definition: plannodes.h:940
JoinPath jpath
Definition: pathnodes.h:2226

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:1759

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:7084
Path * subpath
Definition: pathnodes.h:2328

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:7310
#define CP_IGNORE_TLIST
Definition: createplan.c:73
Path * subpath
Definition: pathnodes.h:2316
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:5931
Cardinality numGroups
Definition: pathnodes.h:2493

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}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:224
@ 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:5594
struct TableSampleClause * tablesample
Definition: parsenodes.h:1112
Scan scan
Definition: plannodes.h:494

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:868
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:5577
Scan scan
Definition: plannodes.h:485

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:6953
Path * rightpath
Definition: pathnodes.h:2476
Cardinality numGroups
Definition: pathnodes.h:2480
Path * leftpath
Definition: pathnodes.h:2475
SetOpCmd cmd
Definition: pathnodes.h:2477
Path path
Definition: pathnodes.h:2474
SetOpStrategy strategy
Definition: pathnodes.h:2478
List * groupList
Definition: pathnodes.h:2479

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:5752
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:978
PlannerInfo * subroot
Definition: pathnodes.h:977

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:5793
@ 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:5733
List * tidrangequals
Definition: pathnodes.h:1970

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:5714
bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)
Definition: equivclass.c:3550
List * tidquals
Definition: pathnodes.h:1958
Path path
Definition: pathnodes.h:1957
Scan scan
Definition: plannodes.h:659

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:6769
Sort * make_sort_from_sortclauses(List *sortcls, Plan *lefttree)
Definition: createplan.c:6485
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:2156
@ UNIQUE_PATH_NOOP
Definition: pathnodes.h:2154
@ UNIQUE_PATH_HASH
Definition: pathnodes.h:2155
Path * subpath
Definition: pathnodes.h:2162
List * uniq_exprs
Definition: pathnodes.h:2165
UniquePathMethod umethod
Definition: pathnodes.h:2163
List * in_operators
Definition: pathnodes.h:2164
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:6818

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:5812
@ RTE_VALUES
Definition: parsenodes.h:1031
List * values_lists
Definition: parsenodes.h:1204
Scan scan
Definition: plannodes.h:731

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:6699
List * runCondition
Definition: pathnodes.h:2464
Path * subpath
Definition: pathnodes.h:2461
WindowClause * winclause
Definition: pathnodes.h:2462
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:5872
int wt_param_id
Definition: pathnodes.h:557

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

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

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

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

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

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

5278{
5279 List *t_list = NIL;
5280 ListCell *l;
5281
5282 foreach(l, clauses)
5283 {
5284 RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
5285 OpExpr *clause = (OpExpr *) restrictinfo->clause;
5286
5287 Assert(is_opclause(clause));
5288 if (bms_is_subset(restrictinfo->right_relids, outerrelids))
5289 {
5290 /*
5291 * Duplicate just enough of the structure to allow commuting the
5292 * clause without changing the original list. Could use
5293 * copyObject, but a complete deep copy is overkill.
5294 */
5295 OpExpr *temp = makeNode(OpExpr);
5296
5297 temp->opno = clause->opno;
5298 temp->opfuncid = InvalidOid;
5299 temp->opresulttype = clause->opresulttype;
5300 temp->opretset = clause->opretset;
5301 temp->opcollid = clause->opcollid;
5302 temp->inputcollid = clause->inputcollid;
5303 temp->args = list_copy(clause->args);
5304 temp->location = clause->location;
5305 /* Commute it --- note this modifies the temp node in-place. */
5306 CommuteOpExpr(temp);
5307 t_list = lappend(t_list, temp);
5308 restrictinfo->outer_is_left = false;
5309 }
5310 else
5311 {
5312 Assert(bms_is_subset(restrictinfo->left_relids, outerrelids));
5313 t_list = lappend(t_list, clause);
5314 restrictinfo->outer_is_left = true;
5315 }
5316 }
5317 return t_list;
5318}
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 7310 of file createplan.c.

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

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

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

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

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

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

Referenced by create_mergejoin_plan().

◆ label_sort_with_costsize()

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

Definition at line 5487 of file createplan.c.

5488{
5489 Plan *lefttree = plan->plan.lefttree;
5490 Path sort_path; /* dummy for result of cost_sort */
5491
5492 Assert(IsA(plan, Sort));
5493
5494 cost_sort(&sort_path, root, NIL,
5495 plan->plan.disabled_nodes,
5496 lefttree->total_cost,
5497 lefttree->plan_rows,
5498 lefttree->plan_width,
5499 0.0,
5500 work_mem,
5501 limit_tuples);
5502 plan->plan.startup_cost = sort_path.startup_cost;
5503 plan->plan.total_cost = sort_path.total_cost;
5504 plan->plan.plan_rows = lefttree->plan_rows;
5505 plan->plan.plan_width = lefttree->plan_width;
5506 plan->plan.parallel_aware = false;
5507 plan->plan.parallel_safe = lefttree->parallel_safe;
5508}
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 6665 of file createplan.c.

6670{
6671 Agg *node = makeNode(Agg);
6672 Plan *plan = &node->plan;
6673 long numGroups;
6674
6675 /* Reduce to long, but 'ware overflow! */
6676 numGroups = clamp_cardinality_to_long(dNumGroups);
6677
6678 node->aggstrategy = aggstrategy;
6679 node->aggsplit = aggsplit;
6680 node->numCols = numGroupCols;
6681 node->grpColIdx = grpColIdx;
6682 node->grpOperators = grpOperators;
6683 node->grpCollations = grpCollations;
6684 node->numGroups = numGroups;
6685 node->transitionSpace = transitionSpace;
6686 node->aggParams = NULL; /* SS_finalize_plan() will fill this */
6687 node->groupingSets = groupingSets;
6688 node->chain = chain;
6689
6690 plan->qual = qual;
6691 plan->targetlist = tlist;
6692 plan->lefttree = lefttree;
6693 plan->righttree = NULL;
6694
6695 return node;
6696}
AggSplit aggsplit
Definition: plannodes.h:1139
List * chain
Definition: plannodes.h:1166
long numGroups
Definition: plannodes.h:1152
List * groupingSets
Definition: plannodes.h:1163
Bitmapset * aggParams
Definition: plannodes.h:1158
Plan plan
Definition: plannodes.h:1133
int numCols
Definition: plannodes.h:1142
uint64 transitionSpace
Definition: plannodes.h:1155
AggStrategy aggstrategy
Definition: plannodes.h:1136

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

5988{
5989 BitmapAnd *node = makeNode(BitmapAnd);
5990 Plan *plan = &node->plan;
5991
5992 plan->targetlist = NIL;
5993 plan->qual = NIL;
5994 plan->lefttree = NULL;
5995 plan->righttree = NULL;
5996 node->bitmapplans = bitmapplans;
5997
5998 return node;
5999}
Plan plan
Definition: plannodes.h:444
List * bitmapplans
Definition: plannodes.h:445

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

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

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

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

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

6003{
6004 BitmapOr *node = makeNode(BitmapOr);
6005 Plan *plan = &node->plan;
6006
6007 plan->targetlist = NIL;
6008 plan->qual = NIL;
6009 plan->lefttree = NULL;
6010 plan->righttree = NULL;
6011 node->bitmapplans = bitmapplans;
6012
6013 return node;
6014}
List * bitmapplans
Definition: plannodes.h:460
Plan plan
Definition: plannodes.h:458

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

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

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

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

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

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

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

6930{
6931 Gather *node = makeNode(Gather);
6932 Plan *plan = &node->plan;
6933
6934 plan->targetlist = qptlist;
6935 plan->qual = qpqual;
6936 plan->lefttree = subplan;
6937 plan->righttree = NULL;
6938 node->num_workers = nworkers;
6939 node->rescan_param = rescan_param;
6940 node->single_copy = single_copy;
6941 node->invisible = false;
6942 node->initParam = NULL;
6943
6944 return node;
6945}
int num_workers
Definition: plannodes.h:1282
bool invisible
Definition: plannodes.h:1288
Bitmapset * initParam
Definition: plannodes.h:1294
bool single_copy
Definition: plannodes.h:1286
int rescan_param
Definition: plannodes.h:1284

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

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

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

6078{
6079 Hash *node = makeNode(Hash);
6080 Plan *plan = &node->plan;
6081
6082 plan->targetlist = lefttree->targetlist;
6083 plan->qual = NIL;
6084 plan->lefttree = lefttree;
6085 plan->righttree = NULL;
6086
6087 node->hashkeys = hashkeys;
6088 node->skewTable = skewTable;
6089 node->skewColumn = skewColumn;
6090 node->skewInherit = skewInherit;
6091
6092 return node;
6093}
AttrNumber skewColumn
Definition: plannodes.h:1356
List * hashkeys
Definition: plannodes.h:1352
Oid skewTable
Definition: plannodes.h:1354
bool skewInherit
Definition: plannodes.h:1358

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

6053{
6054 HashJoin *node = makeNode(HashJoin);
6055 Plan *plan = &node->join.plan;
6056
6057 plan->targetlist = tlist;
6058 plan->qual = otherclauses;
6059 plan->lefttree = lefttree;
6060 plan->righttree = righttree;
6061 node->hashclauses = hashclauses;
6062 node->hashoperators = hashoperators;
6063 node->hashcollations = hashcollations;
6064 node->hashkeys = hashkeys;
6065 node->join.jointype = jointype;
6066 node->join.inner_unique = inner_unique;
6067 node->join.joinqual = joinclauses;
6068
6069 return node;
6070}
List * hashcollations
Definition: plannodes.h:1001
List * hashclauses
Definition: plannodes.h:999
List * hashoperators
Definition: plannodes.h:1000
List * hashkeys
Definition: plannodes.h:1007
List * joinqual
Definition: plannodes.h:924
JoinType jointype
Definition: plannodes.h:921
bool inner_unique
Definition: plannodes.h:922

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

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

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

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

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

5653{
5655 Plan *plan = &node->scan.plan;
5656
5657 plan->targetlist = qptlist;
5658 plan->qual = qpqual;
5659 plan->lefttree = NULL;
5660 plan->righttree = NULL;
5661 node->scan.scanrelid = scanrelid;
5662 node->indexid = indexid;
5663 node->indexqual = indexqual;
5664 node->recheckqual = recheckqual;
5665 node->indexorderby = indexorderby;
5666 node->indextlist = indextlist;
5667 node->indexorderdir = indexscandir;
5668
5669 return node;
5670}
List * indexqual
Definition: plannodes.h:592
List * recheckqual
Definition: plannodes.h:594
List * indextlist
Definition: plannodes.h:598
ScanDirection indexorderdir
Definition: plannodes.h:600
List * indexorderby
Definition: plannodes.h:596

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

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

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

7038{
7039 Limit *node = makeNode(Limit);
7040 Plan *plan = &node->plan;
7041
7042 plan->targetlist = lefttree->targetlist;
7043 plan->qual = NIL;
7044 plan->lefttree = lefttree;
7045 plan->righttree = NULL;
7046
7047 node->limitOffset = limitOffset;
7048 node->limitCount = limitCount;
7049 node->limitOption = limitOption;
7050 node->uniqNumCols = uniqNumCols;
7051 node->uniqColIdx = uniqColIdx;
7052 node->uniqOperators = uniqOperators;
7053 node->uniqCollations = uniqCollations;
7054
7055 return node;
7056}
LimitOption limitOption
Definition: plannodes.h:1431
Plan plan
Definition: plannodes.h:1422
Node * limitCount
Definition: plannodes.h:1428
int uniqNumCols
Definition: plannodes.h:1434
Node * limitOffset
Definition: plannodes.h:1425

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

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

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

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

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

6643{
6644 Memoize *node = makeNode(Memoize);
6645 Plan *plan = &node->plan;
6646
6647 plan->targetlist = lefttree->targetlist;
6648 plan->qual = NIL;
6649 plan->lefttree = lefttree;
6650 plan->righttree = NULL;
6651
6652 node->numKeys = list_length(param_exprs);
6653 node->hashOperators = hashoperators;
6654 node->collations = collations;
6655 node->param_exprs = param_exprs;
6656 node->singlerow = singlerow;
6657 node->binary_mode = binary_mode;
6658 node->est_entries = est_entries;
6659 node->keyparamids = keyparamids;
6660
6661 return node;
6662}
Plan plan
Definition: plannodes.h:1025
bool singlerow
Definition: plannodes.h:1043
Bitmapset * keyparamids
Definition: plannodes.h:1058
bool binary_mode
Definition: plannodes.h:1049
int numKeys
Definition: plannodes.h:1028
List * param_exprs
Definition: plannodes.h:1037
uint32 est_entries
Definition: plannodes.h:1055

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5756{
5758 Plan *plan = &node->scan.plan;
5759
5760 plan->targetlist = qptlist;
5761 plan->qual = qpqual;
5762 plan->lefttree = NULL;
5763 plan->righttree = NULL;
5764 node->scan.scanrelid = scanrelid;
5765 node->subplan = subplan;
5767
5768 return node;
5769}
@ SUBQUERY_SCAN_UNKNOWN
Definition: plannodes.h:700
SubqueryScanStatus scanstatus
Definition: plannodes.h:709
Plan * subplan
Definition: plannodes.h:708

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

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

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

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

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

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

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

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

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

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

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

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

6703{
6704 WindowAgg *node = makeNode(WindowAgg);
6705 Plan *plan = &node->plan;
6706
6707 node->winname = wc->name;
6708 node->winref = wc->winref;
6709 node->partNumCols = partNumCols;
6710 node->partColIdx = partColIdx;
6711 node->partOperators = partOperators;
6712 node->partCollations = partCollations;
6713 node->ordNumCols = ordNumCols;
6714 node->ordColIdx = ordColIdx;
6715 node->ordOperators = ordOperators;
6716 node->ordCollations = ordCollations;
6717 node->frameOptions = wc->frameOptions;
6718 node->startOffset = wc->startOffset;
6719 node->endOffset = wc->endOffset;
6720 node->runCondition = runCondition;
6721 /* a duplicate of the above for EXPLAIN */
6722 node->runConditionOrig = runCondition;
6723 node->startInRangeFunc = wc->startInRangeFunc;
6724 node->endInRangeFunc = wc->endInRangeFunc;
6725 node->inRangeColl = wc->inRangeColl;
6726 node->inRangeAsc = wc->inRangeAsc;
6727 node->inRangeNullsFirst = wc->inRangeNullsFirst;
6728 node->topWindow = topWindow;
6729
6730 plan->targetlist = tlist;
6731 plan->lefttree = lefttree;
6732 plan->righttree = NULL;
6733 plan->qual = qual;
6734
6735 return node;
6736}
char * winname
Definition: plannodes.h:1178
int partNumCols
Definition: plannodes.h:1184
Oid endInRangeFunc
Definition: plannodes.h:1228
Node * endOffset
Definition: plannodes.h:1214
bool topWindow
Definition: plannodes.h:1243
Plan plan
Definition: plannodes.h:1175
List * runConditionOrig
Definition: plannodes.h:1220
Oid inRangeColl
Definition: plannodes.h:1231
Node * startOffset
Definition: plannodes.h:1211
List * runCondition
Definition: plannodes.h:1217
Oid startInRangeFunc
Definition: plannodes.h:1225
bool inRangeAsc
Definition: plannodes.h:1234
Index winref
Definition: plannodes.h:1181
bool inRangeNullsFirst
Definition: plannodes.h:1237
int ordNumCols
Definition: plannodes.h:1196
int frameOptions
Definition: plannodes.h:1208
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 5872 of file createplan.c.

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

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:1472
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 6597 of file createplan.c.

6598{
6599 Plan *matplan;
6600 Path matpath; /* dummy for result of cost_material */
6601 Cost initplan_cost;
6602 bool unsafe_initplans;
6603
6604 matplan = (Plan *) make_material(subplan);
6605
6606 /*
6607 * XXX horrid kluge: if there are any initPlans attached to the subplan,
6608 * move them up to the Material node, which is now effectively the top
6609 * plan node in its query level. This prevents failure in
6610 * SS_finalize_plan(), which see for comments.
6611 */
6612 matplan->initPlan = subplan->initPlan;
6613 subplan->initPlan = NIL;
6614
6615 /* Move the initplans' cost delta, as well */
6617 &initplan_cost, &unsafe_initplans);
6618 subplan->startup_cost -= initplan_cost;
6619 subplan->total_cost -= initplan_cost;
6620
6621 /* Set cost data */
6622 cost_material(&matpath,
6623 subplan->disabled_nodes,
6624 subplan->startup_cost,
6625 subplan->total_cost,
6626 subplan->plan_rows,
6627 subplan->plan_width);
6628 matplan->disabled_nodes = subplan->disabled_nodes;
6629 matplan->startup_cost = matpath.startup_cost + initplan_cost;
6630 matplan->total_cost = matpath.total_cost + initplan_cost;
6631 matplan->plan_rows = subplan->plan_rows;
6632 matplan->plan_width = subplan->plan_width;
6633 matplan->parallel_aware = false;
6634 matplan->parallel_safe = subplan->parallel_safe;
6635
6636 return matplan;
6637}
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:209
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 5354 of file createplan.c.

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

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

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

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