PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
createplan.c File Reference
#include "postgres.h"
#include <limits.h>
#include <math.h>
#include "access/stratnum.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/paths.h"
#include "optimizer/placeholder.h"
#include "optimizer/plancat.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/predtest.h"
#include "optimizer/restrictinfo.h"
#include "optimizer/subselect.h"
#include "optimizer/tlist.h"
#include "optimizer/var.h"
#include "parser/parse_clause.h"
#include "parser/parsetree.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 */
 

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 Plancreate_append_plan (PlannerInfo *root, AppendPath *best_path)
 
static Plancreate_merge_append_plan (PlannerInfo *root, MergeAppendPath *best_path)
 
static Resultcreate_result_plan (PlannerInfo *root, ResultPath *best_path)
 
static ProjectSetcreate_project_set_plan (PlannerInfo *root, ProjectSetPath *best_path)
 
static Materialcreate_material_plan (PlannerInfo *root, MaterialPath *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)
 
static Planinject_projection_plan (Plan *subplan, List *tlist)
 
static Sortcreate_sort_plan (PlannerInfo *root, SortPath *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 void get_column_info_for_window (PlannerInfo *root, WindowClause *wc, List *tlist, int numSortCols, AttrNumber *sortColIdx, int *partNumCols, AttrNumber **partColIdx, Oid **partOperators, int *ordNumCols, AttrNumber **ordColIdx, Oid **ordOperators)
 
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 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 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 process_subquery_nestloop_params (PlannerInfo *root, List *subplan_params)
 
static Listfix_indexqual_references (PlannerInfo *root, IndexPath *index_path)
 
static Listfix_indexorderby_references (PlannerInfo *root, IndexPath *index_path)
 
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 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 *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 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 WorkTableScanmake_worktablescan (List *qptlist, List *qpqual, Index scanrelid, int wtParam)
 
static Appendmake_append (List *appendplans, List *tlist, List *partitioned_rels)
 
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)
 
static HashJoinmake_hashjoin (List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, Plan *lefttree, Plan *righttree, JoinType jointype)
 
static Hashmake_hash (Plan *lefttree, Oid skewTable, AttrNumber skewColumn, bool skewInherit, Oid skewColType, int32 skewColTypmod)
 
static MergeJoinmake_mergejoin (List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype)
 
static Sortmake_sort (Plan *lefttree, int numCols, 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 EquivalenceMemberfind_ec_member_for_tle (EquivalenceClass *ec, TargetEntry *tle, Relids relids)
 
static Sortmake_sort_from_pathkeys (Plan *lefttree, List *pathkeys)
 
static Sortmake_sort_from_groupcols (List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
 
static Materialmake_material (Plan *lefttree)
 
static WindowAggmake_windowagg (List *tlist, Index winref, int partNumCols, AttrNumber *partColIdx, Oid *partOperators, int ordNumCols, AttrNumber *ordColIdx, Oid *ordOperators, int frameOptions, Node *startOffset, Node *endOffset, Plan *lefttree)
 
static Groupmake_group (List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, 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, bool single_copy, Plan *subplan)
 
static SetOpmake_setop (SetOpCmd cmd, SetOpStrategy strategy, Plan *lefttree, List *distinctList, AttrNumber flagColIdx, int firstFlag, 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, CmdType operation, bool canSetTag, Index nominalRelation, List *partitioned_rels, List *resultRelations, List *subplans, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam)
 
static GatherMergecreate_gather_merge_plan (PlannerInfo *root, GatherMergePath *best_path)
 
Plancreate_plan (PlannerInfo *root, Path *best_path)
 
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, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree)
 
Limitmake_limit (Plan *lefttree, Node *limitOffset, Node *limitCount)
 
bool is_projection_capable_path (Path *path)
 
bool is_projection_capable_plan (Plan *plan)
 

Macro Definition Documentation

#define CP_LABEL_TLIST   0x0004 /* tlist must contain sortgrouprefs */
#define CP_SMALL_TLIST   0x0002 /* Prefer narrower tlists */

Function Documentation

static void bitmap_subplan_mark_shared ( Plan plan)
static

Definition at line 4832 of file createplan.c.

References elog, ERROR, IsA, linitial, and nodeTag.

Referenced by create_bitmap_scan_plan().

4833 {
4834  if (IsA(plan, BitmapAnd))
4836  linitial(((BitmapAnd *) plan)->bitmapplans));
4837  else if (IsA(plan, BitmapOr))
4838  ((BitmapOr *) plan)->isshared = true;
4839  else if (IsA(plan, BitmapIndexScan))
4840  ((BitmapIndexScan *) plan)->isshared = true;
4841  else
4842  elog(ERROR, "unrecognized node type: %d", nodeTag(plan));
4843 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:4832
bool isshared
Definition: dynahash.c:203
#define nodeTag(nodeptr)
Definition: nodes.h:523
#define elog
Definition: elog.h:219
static List * build_path_tlist ( PlannerInfo root,
Path path 
)
static

Definition at line 717 of file createplan.c.

References PathTarget::exprs, lappend(), lfirst, makeTargetEntry(), NIL, NULL, Path::param_info, Path::pathtarget, replace_nestloop_params(), TargetEntry::ressortgroupref, and PathTarget::sortgrouprefs.

Referenced by create_agg_plan(), create_append_plan(), create_gather_merge_plan(), create_gather_plan(), create_gating_plan(), create_group_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_result_plan(), create_scan_plan(), create_unique_plan(), and create_windowagg_plan().

718 {
719  List *tlist = NIL;
720  Index *sortgrouprefs = path->pathtarget->sortgrouprefs;
721  int resno = 1;
722  ListCell *v;
723 
724  foreach(v, path->pathtarget->exprs)
725  {
726  Node *node = (Node *) lfirst(v);
727  TargetEntry *tle;
728 
729  /*
730  * If it's a parameterized path, there might be lateral references in
731  * the tlist, which need to be replaced with Params. There's no need
732  * to remake the TargetEntry nodes, so apply this to each list item
733  * separately.
734  */
735  if (path->param_info)
736  node = replace_nestloop_params(root, node);
737 
738  tle = makeTargetEntry((Expr *) node,
739  resno,
740  NULL,
741  false);
742  if (sortgrouprefs)
743  tle->ressortgroupref = sortgrouprefs[resno - 1];
744 
745  tlist = lappend(tlist, tle);
746  resno++;
747  }
748  return tlist;
749 }
#define NIL
Definition: pg_list.h:69
PathTarget * pathtarget
Definition: relation.h:899
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
Index * sortgrouprefs
Definition: relation.h:829
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
List * lappend(List *list, void *datum)
Definition: list.c:128
List * exprs
Definition: relation.h:828
unsigned int Index
Definition: c.h:365
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Index ressortgroupref
Definition: primnodes.h:1355
Definition: pg_list.h:45
static void copy_generic_path_info ( Plan dest,
Path src 
)
static

Definition at line 4773 of file createplan.c.

References Plan::parallel_aware, Path::parallel_aware, Path::pathtarget, Plan::plan_rows, Plan::plan_width, Path::rows, Plan::startup_cost, Path::startup_cost, Plan::total_cost, Path::total_cost, and PathTarget::width.

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_groupingsets_plan(), create_hashjoin_plan(), create_indexscan_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_merge_append_plan(), create_mergejoin_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_nestloop_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_result_plan(), create_samplescan_plan(), create_seqscan_plan(), create_setop_plan(), create_sort_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidscan_plan(), create_unique_plan(), create_upper_unique_plan(), create_valuesscan_plan(), create_windowagg_plan(), and create_worktablescan_plan().

4774 {
4775  dest->startup_cost = src->startup_cost;
4776  dest->total_cost = src->total_cost;
4777  dest->plan_rows = src->rows;
4778  dest->plan_width = src->pathtarget->width;
4779  dest->parallel_aware = src->parallel_aware;
4780 }
double plan_rows
Definition: plannodes.h:120
PathTarget * pathtarget
Definition: relation.h:899
Cost startup_cost
Definition: relation.h:910
Cost startup_cost
Definition: plannodes.h:114
bool parallel_aware
Definition: plannodes.h:126
Cost total_cost
Definition: relation.h:911
int plan_width
Definition: plannodes.h:121
double rows
Definition: relation.h:909
int width
Definition: relation.h:831
Cost total_cost
Definition: plannodes.h:115
bool parallel_aware
Definition: relation.h:903
static void copy_plan_costsize ( Plan dest,
Plan src 
)
static

Definition at line 4787 of file createplan.c.

References Plan::parallel_aware, 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().

4788 {
4789  dest->startup_cost = src->startup_cost;
4790  dest->total_cost = src->total_cost;
4791  dest->plan_rows = src->plan_rows;
4792  dest->plan_width = src->plan_width;
4793  /* Assume the inserted node is not parallel-aware. */
4794  dest->parallel_aware = false;
4795 }
double plan_rows
Definition: plannodes.h:120
Cost startup_cost
Definition: plannodes.h:114
bool parallel_aware
Definition: plannodes.h:126
int plan_width
Definition: plannodes.h:121
Cost total_cost
Definition: plannodes.h:115
static Agg * create_agg_plan ( PlannerInfo root,
AggPath best_path 
)
static

Definition at line 1701 of file createplan.c.

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

Referenced by create_plan_recurse().

1702 {
1703  Agg *plan;
1704  Plan *subplan;
1705  List *tlist;
1706  List *quals;
1707 
1708  /*
1709  * Agg can project, so no need to be terribly picky about child tlist, but
1710  * we do need grouping columns to be available
1711  */
1712  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1713 
1714  tlist = build_path_tlist(root, &best_path->path);
1715 
1716  quals = order_qual_clauses(root, best_path->qual);
1717 
1718  plan = make_agg(tlist, quals,
1719  best_path->aggstrategy,
1720  best_path->aggsplit,
1721  list_length(best_path->groupClause),
1723  subplan->targetlist),
1724  extract_grouping_ops(best_path->groupClause),
1725  NIL,
1726  NIL,
1727  best_path->numGroups,
1728  subplan);
1729 
1730  copy_generic_path_info(&plan->plan, (Path *) best_path);
1731 
1732  return plan;
1733 }
#define NIL
Definition: pg_list.h:69
AggStrategy aggstrategy
Definition: relation.h:1394
List * qual
Definition: relation.h:1398
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
AggSplit aggsplit
Definition: relation.h:1395
Oid * extract_grouping_ops(List *groupClause)
Definition: tlist.c:466
double numGroups
Definition: relation.h:1396
AttrNumber * extract_grouping_cols(List *groupClause, List *tlist)
Definition: tlist.c:492
Agg * make_agg(List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree)
Definition: createplan.c:5888
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
List * groupClause
Definition: relation.h:1397
Plan plan
Definition: plannodes.h:753
#define CP_LABEL_TLIST
Definition: createplan.c:68
static int list_length(const List *l)
Definition: pg_list.h:89
Path * subpath
Definition: relation.h:1393
List * targetlist
Definition: plannodes.h:132
Definition: plannodes.h:751
Definition: pg_list.h:45
Path path
Definition: relation.h:1392
Definition: relation.h:892
static Plan * create_append_plan ( PlannerInfo root,
AppendPath best_path 
)
static

Definition at line 979 of file createplan.c.

References build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), lappend(), lfirst, list_make1, make_append(), make_result(), makeBoolConst(), NIL, NULL, AppendPath::partitioned_rels, AppendPath::path, Append::plan, subpath(), and AppendPath::subpaths.

Referenced by create_plan_recurse().

980 {
981  Append *plan;
982  List *tlist = build_path_tlist(root, &best_path->path);
983  List *subplans = NIL;
984  ListCell *subpaths;
985 
986  /*
987  * The subpaths list could be empty, if every child was proven empty by
988  * constraint exclusion. In that case generate a dummy plan that returns
989  * no rows.
990  *
991  * Note that an AppendPath with no members is also generated in certain
992  * cases where there was no appending construct at all, but we know the
993  * relation is empty (see set_dummy_rel_pathlist).
994  */
995  if (best_path->subpaths == NIL)
996  {
997  /* Generate a Result plan with constant-FALSE gating qual */
998  Plan *plan;
999 
1000  plan = (Plan *) make_result(tlist,
1001  (Node *) list_make1(makeBoolConst(false,
1002  false)),
1003  NULL);
1004 
1005  copy_generic_path_info(plan, (Path *) best_path);
1006 
1007  return plan;
1008  }
1009 
1010  /* Build the plan for each child */
1011  foreach(subpaths, best_path->subpaths)
1012  {
1013  Path *subpath = (Path *) lfirst(subpaths);
1014  Plan *subplan;
1015 
1016  /* Must insist that all children return the same tlist */
1017  subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
1018 
1019  subplans = lappend(subplans, subplan);
1020  }
1021 
1022  /*
1023  * XXX ideally, if there's just one child, we'd not bother to generate an
1024  * Append node but just return the single child. At the moment this does
1025  * not work because the varno of the child scan plan won't match the
1026  * parent-rel Vars it'll be asked to emit.
1027  */
1028 
1029  plan = make_append(subplans, tlist, best_path->partitioned_rels);
1030 
1031  copy_generic_path_info(&plan->plan, (Path *) best_path);
1032 
1033  return (Plan *) plan;
1034 }
#define NIL
Definition: pg_list.h:69
static Append * make_append(List *appendplans, List *tlist, List *partitioned_rels)
Definition: createplan.c:5166
Definition: nodes.h:518
Path path
Definition: relation.h:1122
#define list_make1(x1)
Definition: pg_list.h:133
List * subpaths
Definition: relation.h:1125
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:354
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6246
List * lappend(List *list, void *datum)
Definition: list.c:128
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
List * partitioned_rels
Definition: relation.h:1124
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
Definition: relation.h:892
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
static BitmapHeapScan * create_bitmap_scan_plan ( PlannerInfo root,
BitmapHeapPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 2634 of file createplan.c.

References Assert, bitmap_subplan_mark_shared(), BitmapHeapPath::bitmapqual, castNode, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), create_bitmap_subplan(), extract_actual_clauses(), lappend(), lfirst, list_difference_ptr(), list_make1, list_member(), list_member_ptr(), make_bitmap_heapscan(), NIL, order_qual_clauses(), Path::parallel_aware, Path::param_info, Path::parent, RestrictInfo::parent_ec, BitmapHeapPath::path, Scan::plan, predicate_implied_by(), RestrictInfo::pseudoconstant, RelOptInfo::relid, replace_nestloop_params(), RTE_RELATION, RelOptInfo::rtekind, and BitmapHeapScan::scan.

Referenced by create_scan_plan().

2638 {
2639  Index baserelid = best_path->path.parent->relid;
2640  Plan *bitmapqualplan;
2641  List *bitmapqualorig;
2642  List *indexquals;
2643  List *indexECs;
2644  List *qpqual;
2645  ListCell *l;
2646  BitmapHeapScan *scan_plan;
2647 
2648  /* it should be a base rel... */
2649  Assert(baserelid > 0);
2650  Assert(best_path->path.parent->rtekind == RTE_RELATION);
2651 
2652  /* Process the bitmapqual tree into a Plan tree and qual lists */
2653  bitmapqualplan = create_bitmap_subplan(root, best_path->bitmapqual,
2654  &bitmapqualorig, &indexquals,
2655  &indexECs);
2656 
2657  if (best_path->path.parallel_aware)
2658  bitmap_subplan_mark_shared(bitmapqualplan);
2659 
2660  /*
2661  * The qpqual list must contain all restrictions not automatically handled
2662  * by the index, other than pseudoconstant clauses which will be handled
2663  * by a separate gating plan node. All the predicates in the indexquals
2664  * will be checked (either by the index itself, or by
2665  * nodeBitmapHeapscan.c), but if there are any "special" operators
2666  * involved then they must be added to qpqual. The upshot is that qpqual
2667  * must contain scan_clauses minus whatever appears in indexquals.
2668  *
2669  * This loop is similar to the comparable code in create_indexscan_plan(),
2670  * but with some differences because it has to compare the scan clauses to
2671  * stripped (no RestrictInfos) indexquals. See comments there for more
2672  * info.
2673  *
2674  * In normal cases simple equal() checks will be enough to spot duplicate
2675  * clauses, so we try that first. We next see if the scan clause is
2676  * redundant with any top-level indexqual by virtue of being generated
2677  * from the same EC. After that, try predicate_implied_by().
2678  *
2679  * Unlike create_indexscan_plan(), the predicate_implied_by() test here is
2680  * useful for getting rid of qpquals that are implied by index predicates,
2681  * because the predicate conditions are included in the "indexquals"
2682  * returned by create_bitmap_subplan(). Bitmap scans have to do it that
2683  * way because predicate conditions need to be rechecked if the scan
2684  * becomes lossy, so they have to be included in bitmapqualorig.
2685  */
2686  qpqual = NIL;
2687  foreach(l, scan_clauses)
2688  {
2689  RestrictInfo *rinfo = castNode(RestrictInfo, lfirst(l));
2690  Node *clause = (Node *) rinfo->clause;
2691 
2692  if (rinfo->pseudoconstant)
2693  continue; /* we may drop pseudoconstants here */
2694  if (list_member(indexquals, clause))
2695  continue; /* simple duplicate */
2696  if (rinfo->parent_ec && list_member_ptr(indexECs, rinfo->parent_ec))
2697  continue; /* derived from same EquivalenceClass */
2698  if (!contain_mutable_functions(clause) &&
2699  predicate_implied_by(list_make1(clause), indexquals))
2700  continue; /* provably implied by indexquals */
2701  qpqual = lappend(qpqual, rinfo);
2702  }
2703 
2704  /* Sort clauses into best execution order */
2705  qpqual = order_qual_clauses(root, qpqual);
2706 
2707  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2708  qpqual = extract_actual_clauses(qpqual, false);
2709 
2710  /*
2711  * When dealing with special operators, we will at this point have
2712  * duplicate clauses in qpqual and bitmapqualorig. We may as well drop
2713  * 'em from bitmapqualorig, since there's no point in making the tests
2714  * twice.
2715  */
2716  bitmapqualorig = list_difference_ptr(bitmapqualorig, qpqual);
2717 
2718  /*
2719  * We have to replace any outer-relation variables with nestloop params in
2720  * the qpqual and bitmapqualorig expressions. (This was already done for
2721  * expressions attached to plan nodes in the bitmapqualplan tree.)
2722  */
2723  if (best_path->path.param_info)
2724  {
2725  qpqual = (List *)
2726  replace_nestloop_params(root, (Node *) qpqual);
2727  bitmapqualorig = (List *)
2728  replace_nestloop_params(root, (Node *) bitmapqualorig);
2729  }
2730 
2731  /* Finally ready to build the plan node */
2732  scan_plan = make_bitmap_heapscan(tlist,
2733  qpqual,
2734  bitmapqualplan,
2735  bitmapqualorig,
2736  baserelid);
2737 
2738  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
2739 
2740  return scan_plan;
2741 }
#define NIL
Definition: pg_list.h:69
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
bool predicate_implied_by(List *predicate_list, List *restrictinfo_list)
Definition: predtest.c:128
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
List * list_difference_ptr(const List *list1, const List *list2)
Definition: list.c:884
bool pseudoconstant
Definition: relation.h:1668
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
static Plan * create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
Definition: createplan.c:2764
#define list_make1(x1)
Definition: pg_list.h:133
static BitmapHeapScan * make_bitmap_heapscan(List *qptlist, List *qpqual, Plan *lefttree, List *bitmapqualorig, Index scanrelid)
Definition: createplan.c:4975
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
bool list_member(const List *list, const void *datum)
Definition: list.c:444
EquivalenceClass * parent_ec
Definition: relation.h:1694
RelOptInfo * parent
Definition: relation.h:898
Path * bitmapqual
Definition: relation.h:1007
Index relid
Definition: relation.h:522
List * lappend(List *list, void *datum)
Definition: list.c:128
static void bitmap_subplan_mark_shared(Plan *plan)
Definition: createplan.c:4832
Expr * clause
Definition: relation.h:1660
unsigned int Index
Definition: c.h:365
RTEKind rtekind
Definition: relation.h:524
bool list_member_ptr(const List *list, const void *datum)
Definition: list.c:465
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:877
bool parallel_aware
Definition: relation.h:903
Definition: pg_list.h:45
static Plan * create_bitmap_subplan ( PlannerInfo root,
Path bitmapqual,
List **  qual,
List **  indexqual,
List **  indexECs 
)
static

Definition at line 2764 of file createplan.c.

References BitmapAndPath::bitmapquals, BitmapOrPath::bitmapquals, BitmapAndPath::bitmapselectivity, BitmapOrPath::bitmapselectivity, castNode, clamp_row_est(), create_indexscan_plan(), elog, ERROR, get_actual_clauses(), IndexPath::indexclauses, IndexScan::indexid, IndexPath::indexinfo, IndexScan::indexqual, IndexScan::indexqualorig, IndexPath::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, NULL, Plan::parallel_aware, Path::parent, RestrictInfo::parent_ec, IndexPath::path, BitmapAndPath::path, BitmapOrPath::path, Plan::plan_rows, Plan::plan_width, predicate_implied_by(), IndexScan::scan, Scan::scanrelid, Plan::startup_cost, Path::startup_cost, Plan::total_cost, Path::total_cost, and RelOptInfo::tuples.

Referenced by create_bitmap_scan_plan().

2766 {
2767  Plan *plan;
2768 
2769  if (IsA(bitmapqual, BitmapAndPath))
2770  {
2771  BitmapAndPath *apath = (BitmapAndPath *) bitmapqual;
2772  List *subplans = NIL;
2773  List *subquals = NIL;
2774  List *subindexquals = NIL;
2775  List *subindexECs = NIL;
2776  ListCell *l;
2777 
2778  /*
2779  * There may well be redundant quals among the subplans, since a
2780  * top-level WHERE qual might have gotten used to form several
2781  * different index quals. We don't try exceedingly hard to eliminate
2782  * redundancies, but we do eliminate obvious duplicates by using
2783  * list_concat_unique.
2784  */
2785  foreach(l, apath->bitmapquals)
2786  {
2787  Plan *subplan;
2788  List *subqual;
2789  List *subindexqual;
2790  List *subindexEC;
2791 
2792  subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
2793  &subqual, &subindexqual,
2794  &subindexEC);
2795  subplans = lappend(subplans, subplan);
2796  subquals = list_concat_unique(subquals, subqual);
2797  subindexquals = list_concat_unique(subindexquals, subindexqual);
2798  /* Duplicates in indexECs aren't worth getting rid of */
2799  subindexECs = list_concat(subindexECs, subindexEC);
2800  }
2801  plan = (Plan *) make_bitmap_and(subplans);
2802  plan->startup_cost = apath->path.startup_cost;
2803  plan->total_cost = apath->path.total_cost;
2804  plan->plan_rows =
2805  clamp_row_est(apath->bitmapselectivity * apath->path.parent->tuples);
2806  plan->plan_width = 0; /* meaningless */
2807  plan->parallel_aware = false;
2808  *qual = subquals;
2809  *indexqual = subindexquals;
2810  *indexECs = subindexECs;
2811  }
2812  else if (IsA(bitmapqual, BitmapOrPath))
2813  {
2814  BitmapOrPath *opath = (BitmapOrPath *) bitmapqual;
2815  List *subplans = NIL;
2816  List *subquals = NIL;
2817  List *subindexquals = NIL;
2818  bool const_true_subqual = false;
2819  bool const_true_subindexqual = false;
2820  ListCell *l;
2821 
2822  /*
2823  * Here, we only detect qual-free subplans. A qual-free subplan would
2824  * cause us to generate "... OR true ..." which we may as well reduce
2825  * to just "true". We do not try to eliminate redundant subclauses
2826  * because (a) it's not as likely as in the AND case, and (b) we might
2827  * well be working with hundreds or even thousands of OR conditions,
2828  * perhaps from a long IN list. The performance of list_append_unique
2829  * would be unacceptable.
2830  */
2831  foreach(l, opath->bitmapquals)
2832  {
2833  Plan *subplan;
2834  List *subqual;
2835  List *subindexqual;
2836  List *subindexEC;
2837 
2838  subplan = create_bitmap_subplan(root, (Path *) lfirst(l),
2839  &subqual, &subindexqual,
2840  &subindexEC);
2841  subplans = lappend(subplans, subplan);
2842  if (subqual == NIL)
2843  const_true_subqual = true;
2844  else if (!const_true_subqual)
2845  subquals = lappend(subquals,
2846  make_ands_explicit(subqual));
2847  if (subindexqual == NIL)
2848  const_true_subindexqual = true;
2849  else if (!const_true_subindexqual)
2850  subindexquals = lappend(subindexquals,
2851  make_ands_explicit(subindexqual));
2852  }
2853 
2854  /*
2855  * In the presence of ScalarArrayOpExpr quals, we might have built
2856  * BitmapOrPaths with just one subpath; don't add an OR step.
2857  */
2858  if (list_length(subplans) == 1)
2859  {
2860  plan = (Plan *) linitial(subplans);
2861  }
2862  else
2863  {
2864  plan = (Plan *) make_bitmap_or(subplans);
2865  plan->startup_cost = opath->path.startup_cost;
2866  plan->total_cost = opath->path.total_cost;
2867  plan->plan_rows =
2868  clamp_row_est(opath->bitmapselectivity * opath->path.parent->tuples);
2869  plan->plan_width = 0; /* meaningless */
2870  plan->parallel_aware = false;
2871  }
2872 
2873  /*
2874  * If there were constant-TRUE subquals, the OR reduces to constant
2875  * TRUE. Also, avoid generating one-element ORs, which could happen
2876  * due to redundancy elimination or ScalarArrayOpExpr quals.
2877  */
2878  if (const_true_subqual)
2879  *qual = NIL;
2880  else if (list_length(subquals) <= 1)
2881  *qual = subquals;
2882  else
2883  *qual = list_make1(make_orclause(subquals));
2884  if (const_true_subindexqual)
2885  *indexqual = NIL;
2886  else if (list_length(subindexquals) <= 1)
2887  *indexqual = subindexquals;
2888  else
2889  *indexqual = list_make1(make_orclause(subindexquals));
2890  *indexECs = NIL;
2891  }
2892  else if (IsA(bitmapqual, IndexPath))
2893  {
2894  IndexPath *ipath = (IndexPath *) bitmapqual;
2895  IndexScan *iscan;
2896  List *subindexECs;
2897  ListCell *l;
2898 
2899  /* Use the regular indexscan plan build machinery... */
2900  iscan = castNode(IndexScan,
2901  create_indexscan_plan(root, ipath,
2902  NIL, NIL, false));
2903  /* then convert to a bitmap indexscan */
2904  plan = (Plan *) make_bitmap_indexscan(iscan->scan.scanrelid,
2905  iscan->indexid,
2906  iscan->indexqual,
2907  iscan->indexqualorig);
2908  /* and set its cost/width fields appropriately */
2909  plan->startup_cost = 0.0;
2910  plan->total_cost = ipath->indextotalcost;
2911  plan->plan_rows =
2912  clamp_row_est(ipath->indexselectivity * ipath->path.parent->tuples);
2913  plan->plan_width = 0; /* meaningless */
2914  plan->parallel_aware = false;
2915  *qual = get_actual_clauses(ipath->indexclauses);
2916  *indexqual = get_actual_clauses(ipath->indexquals);
2917  foreach(l, ipath->indexinfo->indpred)
2918  {
2919  Expr *pred = (Expr *) lfirst(l);
2920 
2921  /*
2922  * We know that the index predicate must have been implied by the
2923  * query condition as a whole, but it may or may not be implied by
2924  * the conditions that got pushed into the bitmapqual. Avoid
2925  * generating redundant conditions.
2926  */
2927  if (!predicate_implied_by(list_make1(pred), ipath->indexclauses))
2928  {
2929  *qual = lappend(*qual, pred);
2930  *indexqual = lappend(*indexqual, pred);
2931  }
2932  }
2933  subindexECs = NIL;
2934  foreach(l, ipath->indexquals)
2935  {
2936  RestrictInfo *rinfo = (RestrictInfo *) lfirst(l);
2937 
2938  if (rinfo->parent_ec)
2939  subindexECs = lappend(subindexECs, rinfo->parent_ec);
2940  }
2941  *indexECs = subindexECs;
2942  }
2943  else
2944  {
2945  elog(ERROR, "unrecognized node type: %d", nodeTag(bitmapqual));
2946  plan = NULL; /* keep compiler quiet */
2947  }
2948 
2949  return plan;
2950 }
#define NIL
Definition: pg_list.h:69
double plan_rows
Definition: plannodes.h:120
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
Path path
Definition: relation.h:975
IndexOptInfo * indexinfo
Definition: relation.h:976
Index scanrelid
Definition: plannodes.h:316
bool predicate_implied_by(List *predicate_list, List *restrictinfo_list)
Definition: predtest.c:128
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
double tuples
Definition: relation.h:533
List * indexqualorig
Definition: plannodes.h:378
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:331
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * indexclauses
Definition: relation.h:977
static Plan * create_bitmap_subplan(PlannerInfo *root, Path *bitmapqual, List **qual, List **indexqual, List **indexECs)
Definition: createplan.c:2764
Selectivity bitmapselectivity
Definition: relation.h:1020
static BitmapAnd * make_bitmap_and(List *bitmapplans)
Definition: createplan.c:5234
Oid indexid
Definition: plannodes.h:376
List * bitmapquals
Definition: relation.h:1019
List * bitmapquals
Definition: relation.h:1032
Expr * make_ands_explicit(List *andclauses)
Definition: clauses.c:366
#define list_make1(x1)
Definition: pg_list.h:133
List * indexquals
Definition: relation.h:978
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
Cost indextotalcost
Definition: relation.h:983
Cost startup_cost
Definition: relation.h:910
Scan scan
Definition: plannodes.h:375
EquivalenceClass * parent_ec
Definition: relation.h:1694
RelOptInfo * parent
Definition: relation.h:898
Selectivity indexselectivity
Definition: relation.h:984
Cost startup_cost
Definition: plannodes.h:114
bool parallel_aware
Definition: plannodes.h:126
Selectivity bitmapselectivity
Definition: relation.h:1033
List * indexqual
Definition: plannodes.h:377
List * lappend(List *list, void *datum)
Definition: list.c:128
static BitmapOr * make_bitmap_or(List *bitmapplans)
Definition: createplan.c:5249
Cost total_cost
Definition: relation.h:911
int plan_width
Definition: plannodes.h:121
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
List * list_concat_unique(List *list1, List *list2)
Definition: list.c:1018
static BitmapIndexScan * make_bitmap_indexscan(Index scanrelid, Oid indexid, List *indexqual, List *indexqualorig)
Definition: createplan.c:4954
#define nodeTag(nodeptr)
Definition: nodes.h:523
Cost total_cost
Definition: plannodes.h:115
#define elog
Definition: elog.h:219
List * indpred
Definition: relation.h:615
double clamp_row_est(double nrows)
Definition: costsize.c:173
Definition: pg_list.h:45
Expr * make_orclause(List *orclauses)
Definition: clauses.c:292
static Scan * create_indexscan_plan(PlannerInfo *root, IndexPath *best_path, List *tlist, List *scan_clauses, bool indexonly)
Definition: createplan.c:2459
Definition: relation.h:892
static CteScan * create_ctescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3190 of file createplan.c.

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(), NULL, order_qual_clauses(), Path::param_info, Path::parent, PlannerInfo::parent_root, PlannerInfo::parse, Scan::plan, SubPlan::plan_id, planner_rt_fetch, RelOptInfo::relid, replace_nestloop_params(), RTE_CTE, RangeTblEntry::rtekind, CteScan::scan, RangeTblEntry::self_reference, and SubPlan::setParam.

Referenced by create_scan_plan().

3192 {
3193  CteScan *scan_plan;
3194  Index scan_relid = best_path->parent->relid;
3195  RangeTblEntry *rte;
3196  SubPlan *ctesplan = NULL;
3197  int plan_id;
3198  int cte_param_id;
3199  PlannerInfo *cteroot;
3200  Index levelsup;
3201  int ndx;
3202  ListCell *lc;
3203 
3204  Assert(scan_relid > 0);
3205  rte = planner_rt_fetch(scan_relid, root);
3206  Assert(rte->rtekind == RTE_CTE);
3207  Assert(!rte->self_reference);
3208 
3209  /*
3210  * Find the referenced CTE, and locate the SubPlan previously made for it.
3211  */
3212  levelsup = rte->ctelevelsup;
3213  cteroot = root;
3214  while (levelsup-- > 0)
3215  {
3216  cteroot = cteroot->parent_root;
3217  if (!cteroot) /* shouldn't happen */
3218  elog(ERROR, "bad levelsup for CTE \"%s\"", rte->ctename);
3219  }
3220 
3221  /*
3222  * Note: cte_plan_ids can be shorter than cteList, if we are still working
3223  * on planning the CTEs (ie, this is a side-reference from another CTE).
3224  * So we mustn't use forboth here.
3225  */
3226  ndx = 0;
3227  foreach(lc, cteroot->parse->cteList)
3228  {
3229  CommonTableExpr *cte = (CommonTableExpr *) lfirst(lc);
3230 
3231  if (strcmp(cte->ctename, rte->ctename) == 0)
3232  break;
3233  ndx++;
3234  }
3235  if (lc == NULL) /* shouldn't happen */
3236  elog(ERROR, "could not find CTE \"%s\"", rte->ctename);
3237  if (ndx >= list_length(cteroot->cte_plan_ids))
3238  elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3239  plan_id = list_nth_int(cteroot->cte_plan_ids, ndx);
3240  Assert(plan_id > 0);
3241  foreach(lc, cteroot->init_plans)
3242  {
3243  ctesplan = (SubPlan *) lfirst(lc);
3244  if (ctesplan->plan_id == plan_id)
3245  break;
3246  }
3247  if (lc == NULL) /* shouldn't happen */
3248  elog(ERROR, "could not find plan for CTE \"%s\"", rte->ctename);
3249 
3250  /*
3251  * We need the CTE param ID, which is the sole member of the SubPlan's
3252  * setParam list.
3253  */
3254  cte_param_id = linitial_int(ctesplan->setParam);
3255 
3256  /* Sort clauses into best execution order */
3257  scan_clauses = order_qual_clauses(root, scan_clauses);
3258 
3259  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3260  scan_clauses = extract_actual_clauses(scan_clauses, false);
3261 
3262  /* Replace any outer-relation variables with nestloop params */
3263  if (best_path->param_info)
3264  {
3265  scan_clauses = (List *)
3266  replace_nestloop_params(root, (Node *) scan_clauses);
3267  }
3268 
3269  scan_plan = make_ctescan(tlist, scan_clauses, scan_relid,
3270  plan_id, cte_param_id);
3271 
3272  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3273 
3274  return scan_plan;
3275 }
Plan plan
Definition: plannodes.h:315
Query * parse
Definition: relation.h:154
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
int plan_id
Definition: primnodes.h:688
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
#define linitial_int(l)
Definition: pg_list.h:111
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define planner_rt_fetch(rti, root)
Definition: relation.h:324
#define ERROR
Definition: elog.h:43
Scan scan
Definition: plannodes.h:525
RelOptInfo * parent
Definition: relation.h:898
Index relid
Definition: relation.h:522
struct PlannerInfo * parent_root
Definition: relation.h:160
static CteScan * make_ctescan(List *qptlist, List *qpqual, Index scanrelid, int ctePlanId, int cteParam)
Definition: createplan.c:5092
int list_nth_int(const List *list, int n)
Definition: list.c:421
List * cte_plan_ids
Definition: relation.h:229
bool self_reference
Definition: parsenodes.h:983
unsigned int Index
Definition: c.h:365
List * init_plans
Definition: relation.h:227
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
List * setParam
Definition: primnodes.h:705
static int list_length(const List *l)
Definition: pg_list.h:89
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
Index ctelevelsup
Definition: parsenodes.h:982
RTEKind rtekind
Definition: parsenodes.h:916
List * cteList
Definition: parsenodes.h:126
char * ctename
Definition: parsenodes.h:981
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static CustomScan * create_customscan_plan ( PlannerInfo root,
CustomPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3487 of file createplan.c.

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(), Path::param_info, Path::parent, CustomPath::path, Scan::plan, CustomPathMethods::PlanCustomPath, Plan::qual, RelOptInfo::relids, replace_nestloop_params(), and CustomScan::scan.

Referenced by create_scan_plan().

3489 {
3490  CustomScan *cplan;
3491  RelOptInfo *rel = best_path->path.parent;
3492  List *custom_plans = NIL;
3493  ListCell *lc;
3494 
3495  /* Recursively transform child paths. */
3496  foreach(lc, best_path->custom_paths)
3497  {
3498  Plan *plan = create_plan_recurse(root, (Path *) lfirst(lc),
3499  CP_EXACT_TLIST);
3500 
3501  custom_plans = lappend(custom_plans, plan);
3502  }
3503 
3504  /*
3505  * Sort clauses into the best execution order, although custom-scan
3506  * provider can reorder them again.
3507  */
3508  scan_clauses = order_qual_clauses(root, scan_clauses);
3509 
3510  /*
3511  * Invoke custom plan provider to create the Plan node represented by the
3512  * CustomPath.
3513  */
3514  cplan = castNode(CustomScan,
3515  best_path->methods->PlanCustomPath(root,
3516  rel,
3517  best_path,
3518  tlist,
3519  scan_clauses,
3520  custom_plans));
3521 
3522  /*
3523  * Copy cost data from Path to Plan; no need to make custom-plan providers
3524  * do this
3525  */
3526  copy_generic_path_info(&cplan->scan.plan, &best_path->path);
3527 
3528  /* Likewise, copy the relids that are represented by this custom scan */
3529  cplan->custom_relids = best_path->path.parent->relids;
3530 
3531  /*
3532  * Replace any outer-relation variables with nestloop params in the qual
3533  * and custom_exprs expressions. We do this last so that the custom-plan
3534  * provider doesn't have to be involved. (Note that parts of custom_exprs
3535  * could have come from join clauses, so doing this beforehand on the
3536  * scan_clauses wouldn't work.) We assume custom_scan_tlist contains no
3537  * such variables.
3538  */
3539  if (best_path->path.param_info)
3540  {
3541  cplan->scan.plan.qual = (List *)
3542  replace_nestloop_params(root, (Node *) cplan->scan.plan.qual);
3543  cplan->custom_exprs = (List *)
3544  replace_nestloop_params(root, (Node *) cplan->custom_exprs);
3545  }
3546 
3547  return cplan;
3548 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:133
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
List * custom_paths
Definition: relation.h:1106
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
struct Plan *(* PlanCustomPath)(PlannerInfo *root, RelOptInfo *rel, struct CustomPath *best_path, List *tlist, List *clauses, List *custom_plans)
Definition: extensible.h:93
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
List * custom_exprs
Definition: plannodes.h:607
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
const struct CustomPathMethods * methods
Definition: relation.h:1108
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
RelOptInfo * parent
Definition: relation.h:898
Relids relids
Definition: relation.h:494
Path path
Definition: relation.h:1103
List * lappend(List *list, void *datum)
Definition: list.c:128
Scan scan
Definition: plannodes.h:603
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * custom_relids
Definition: plannodes.h:611
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
Definition: relation.h:892
static ForeignScan * create_foreignscan_plan ( PlannerInfo root,
ForeignPath best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3343 of file createplan.c.

References PlannerInfo::all_baserels, Assert, RelOptInfo::baserestrictinfo, bms_free(), bms_is_member(), RestrictInfo::clause, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), PlannerGlobal::dependsOnRole, PathTarget::exprs, ForeignScan::fdw_exprs, ForeignPath::fdw_outerpath, ForeignScan::fdw_recheck_quals, RelOptInfo::fdwroutine, FirstLowInvalidHeapAttributeNumber, ForeignScan::fs_relids, ForeignScan::fs_server, ForeignScan::fsSystemCol, FdwRoutine::GetForeignPlan, PlannerInfo::glob, i, InvalidOid, lfirst, NULL, order_qual_clauses(), Path::param_info, Path::parent, ForeignPath::path, Scan::plan, planner_rt_fetch, pull_varattnos(), Plan::qual, RelOptInfo::relid, RangeTblEntry::relid, RelOptInfo::relids, RELOPT_UPPER_REL, RelOptInfo::reloptkind, RelOptInfo::reltarget, replace_nestloop_params(), RTE_RELATION, RelOptInfo::rtekind, RangeTblEntry::rtekind, ForeignScan::scan, RelOptInfo::serverid, and RelOptInfo::useridiscurrent.

Referenced by create_scan_plan().

3345 {
3346  ForeignScan *scan_plan;
3347  RelOptInfo *rel = best_path->path.parent;
3348  Index scan_relid = rel->relid;
3349  Oid rel_oid = InvalidOid;
3350  Plan *outer_plan = NULL;
3351 
3352  Assert(rel->fdwroutine != NULL);
3353 
3354  /* transform the child path if any */
3355  if (best_path->fdw_outerpath)
3356  outer_plan = create_plan_recurse(root, best_path->fdw_outerpath,
3357  CP_EXACT_TLIST);
3358 
3359  /*
3360  * If we're scanning a base relation, fetch its OID. (Irrelevant if
3361  * scanning a join relation.)
3362  */
3363  if (scan_relid > 0)
3364  {
3365  RangeTblEntry *rte;
3366 
3367  Assert(rel->rtekind == RTE_RELATION);
3368  rte = planner_rt_fetch(scan_relid, root);
3369  Assert(rte->rtekind == RTE_RELATION);
3370  rel_oid = rte->relid;
3371  }
3372 
3373  /*
3374  * Sort clauses into best execution order. We do this first since the FDW
3375  * might have more info than we do and wish to adjust the ordering.
3376  */
3377  scan_clauses = order_qual_clauses(root, scan_clauses);
3378 
3379  /*
3380  * Let the FDW perform its processing on the restriction clauses and
3381  * generate the plan node. Note that the FDW might remove restriction
3382  * clauses that it intends to execute remotely, or even add more (if it
3383  * has selected some join clauses for remote use but also wants them
3384  * rechecked locally).
3385  */
3386  scan_plan = rel->fdwroutine->GetForeignPlan(root, rel, rel_oid,
3387  best_path,
3388  tlist, scan_clauses,
3389  outer_plan);
3390 
3391  /* Copy cost data from Path to Plan; no need to make FDW do this */
3392  copy_generic_path_info(&scan_plan->scan.plan, &best_path->path);
3393 
3394  /* Copy foreign server OID; likewise, no need to make FDW do this */
3395  scan_plan->fs_server = rel->serverid;
3396 
3397  /*
3398  * Likewise, copy the relids that are represented by this foreign scan. An
3399  * upper rel doesn't have relids set, but it covers all the base relations
3400  * participating in the underlying scan, so use root's all_baserels.
3401  */
3402  if (rel->reloptkind == RELOPT_UPPER_REL)
3403  scan_plan->fs_relids = root->all_baserels;
3404  else
3405  scan_plan->fs_relids = best_path->path.parent->relids;
3406 
3407  /*
3408  * If this is a foreign join, and to make it valid to push down we had to
3409  * assume that the current user is the same as some user explicitly named
3410  * in the query, mark the finished plan as depending on the current user.
3411  */
3412  if (rel->useridiscurrent)
3413  root->glob->dependsOnRole = true;
3414 
3415  /*
3416  * Replace any outer-relation variables with nestloop params in the qual,
3417  * fdw_exprs and fdw_recheck_quals expressions. We do this last so that
3418  * the FDW doesn't have to be involved. (Note that parts of fdw_exprs or
3419  * fdw_recheck_quals could have come from join clauses, so doing this
3420  * beforehand on the scan_clauses wouldn't work.) We assume
3421  * fdw_scan_tlist contains no such variables.
3422  */
3423  if (best_path->path.param_info)
3424  {
3425  scan_plan->scan.plan.qual = (List *)
3426  replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
3427  scan_plan->fdw_exprs = (List *)
3428  replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
3429  scan_plan->fdw_recheck_quals = (List *)
3431  (Node *) scan_plan->fdw_recheck_quals);
3432  }
3433 
3434  /*
3435  * If rel is a base relation, detect whether any system columns are
3436  * requested from the rel. (If rel is a join relation, rel->relid will be
3437  * 0, but there can be no Var with relid 0 in the rel's targetlist or the
3438  * restriction clauses, so we skip this in that case. Note that any such
3439  * columns in base relations that were joined are assumed to be contained
3440  * in fdw_scan_tlist.) This is a bit of a kluge and might go away
3441  * someday, so we intentionally leave it out of the API presented to FDWs.
3442  */
3443  scan_plan->fsSystemCol = false;
3444  if (scan_relid > 0)
3445  {
3446  Bitmapset *attrs_used = NULL;
3447  ListCell *lc;
3448  int i;
3449 
3450  /*
3451  * First, examine all the attributes needed for joins or final output.
3452  * Note: we must look at rel's targetlist, not the attr_needed data,
3453  * because attr_needed isn't computed for inheritance child rels.
3454  */
3455  pull_varattnos((Node *) rel->reltarget->exprs, scan_relid, &attrs_used);
3456 
3457  /* Add all the attributes used by restriction clauses. */
3458  foreach(lc, rel->baserestrictinfo)
3459  {
3460  RestrictInfo *rinfo = (RestrictInfo *) lfirst(lc);
3461 
3462  pull_varattnos((Node *) rinfo->clause, scan_relid, &attrs_used);
3463  }
3464 
3465  /* Now, are any system columns requested from rel? */
3466  for (i = FirstLowInvalidHeapAttributeNumber + 1; i < 0; i++)
3467  {
3469  {
3470  scan_plan->fsSystemCol = true;
3471  break;
3472  }
3473  }
3474 
3475  bms_free(attrs_used);
3476  }
3477 
3478  return scan_plan;
3479 }
GetForeignPlan_function GetForeignPlan
Definition: fdwapi.h:176
List * qual
Definition: plannodes.h:133
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
Path * fdw_outerpath
Definition: relation.h:1076
RelOptKind reloptkind
Definition: relation.h:491
Oid fs_server
Definition: plannodes.h:576
List * baserestrictinfo
Definition: relation.h:548
List * fdw_exprs
Definition: plannodes.h:577
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
#define FirstLowInvalidHeapAttributeNumber
Definition: sysattr.h:28
bool useridiscurrent
Definition: relation.h:542
unsigned int Oid
Definition: postgres_ext.h:31
void pull_varattnos(Node *node, Index varno, Bitmapset **varattnos)
Definition: var.c:219
bool dependsOnRole
Definition: relation.h:126
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define planner_rt_fetch(rti, root)
Definition: relation.h:324
Relids all_baserels
Definition: relation.h:195
RelOptInfo * parent
Definition: relation.h:898
PlannerGlobal * glob
Definition: relation.h:156
struct FdwRoutine * fdwroutine
Definition: relation.h:544
Relids relids
Definition: relation.h:494
List * fdw_recheck_quals
Definition: plannodes.h:580
Index relid
Definition: relation.h:522
Expr * clause
Definition: relation.h:1660
Oid serverid
Definition: relation.h:540
List * exprs
Definition: relation.h:828
unsigned int Index
Definition: c.h:365
RTEKind rtekind
Definition: relation.h:524
#define InvalidOid
Definition: postgres_ext.h:36
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
RTEKind rtekind
Definition: parsenodes.h:916
int i
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
struct PathTarget * reltarget
Definition: relation.h:505
bool fsSystemCol
Definition: plannodes.h:583
Bitmapset * fs_relids
Definition: plannodes.h:582
static FunctionScan * create_functionscan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 3060 of file createplan.c.

References Assert, copy_generic_path_info(), extract_actual_clauses(), RangeTblEntry::funcordinality, functions, RangeTblEntry::functions, make_functionscan(), order_qual_clauses(), Path::param_info, Path::parent, Scan::plan, planner_rt_fetch, RelOptInfo::relid, replace_nestloop_params(), RTE_FUNCTION, RangeTblEntry::rtekind, and FunctionScan::scan.

Referenced by create_scan_plan().

3062 {
3063  FunctionScan *scan_plan;
3064  Index scan_relid = best_path->parent->relid;
3065  RangeTblEntry *rte;
3066  List *functions;
3067 
3068  /* it should be a function base rel... */
3069  Assert(scan_relid > 0);
3070  rte = planner_rt_fetch(scan_relid, root);
3071  Assert(rte->rtekind == RTE_FUNCTION);
3072  functions = rte->functions;
3073 
3074  /* Sort clauses into best execution order */
3075  scan_clauses = order_qual_clauses(root, scan_clauses);
3076 
3077  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
3078  scan_clauses = extract_actual_clauses(scan_clauses, false);
3079 
3080  /* Replace any outer-relation variables with nestloop params */
3081  if (best_path->param_info)
3082  {
3083  scan_clauses = (List *)
3084  replace_nestloop_params(root, (Node *) scan_clauses);
3085  /* The function expressions could contain nestloop params, too */
3086  functions = (List *) replace_nestloop_params(root, (Node *) functions);
3087  }
3088 
3089  scan_plan = make_functionscan(tlist, scan_clauses, scan_relid,
3090  functions, rte->funcordinality);
3091 
3092  copy_generic_path_info(&scan_plan->scan.plan, best_path);
3093 
3094  return scan_plan;
3095 }
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
bool funcordinality
Definition: parsenodes.h:966
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define planner_rt_fetch(rti, root)
Definition: relation.h:324
RelOptInfo * parent
Definition: relation.h:898
Index relid
Definition: relation.h:522
unsigned int Index
Definition: c.h:365
static FunctionScan * make_functionscan(List *qptlist, List *qpqual, Index scanrelid, List *functions, bool funcordinality)
Definition: createplan.c:5033
#define Assert(condition)
Definition: c.h:675
List * functions
Definition: parsenodes.h:965
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
static const struct fns functions
Definition: regcomp.c:299
RTEKind rtekind
Definition: parsenodes.h:916
Definition: pg_list.h:45
static GatherMerge * create_gather_merge_plan ( PlannerInfo root,
GatherMergePath best_path 
)
static

Definition at line 1468 of file createplan.c.

References Assert, build_path_tlist(), GatherMerge::collations, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), PlannerInfo::glob, Plan::lefttree, make_sort(), makeNode, NIL, GatherMerge::nullsFirst, GatherMerge::num_workers, GatherMergePath::num_workers, GatherMerge::numCols, PlannerGlobal::parallelModeNeeded, Path::parent, GatherMergePath::path, Path::pathkeys, pathkeys_contained_in(), GatherMerge::plan, prepare_sort_from_pathkeys(), RelOptInfo::relids, GatherMerge::sortColIdx, GatherMerge::sortOperators, GatherMergePath::subpath, and Plan::targetlist.

Referenced by create_plan_recurse().

1469 {
1470  GatherMerge *gm_plan;
1471  Plan *subplan;
1472  List *pathkeys = best_path->path.pathkeys;
1473  List *tlist = build_path_tlist(root, &best_path->path);
1474 
1475  /* As with Gather, it's best to project away columns in the workers. */
1476  subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1477 
1478  /* Create a shell for a GatherMerge plan. */
1479  gm_plan = makeNode(GatherMerge);
1480  gm_plan->plan.targetlist = tlist;
1481  gm_plan->num_workers = best_path->num_workers;
1482  copy_generic_path_info(&gm_plan->plan, &best_path->path);
1483 
1484  /* Gather Merge is pointless with no pathkeys; use Gather instead. */
1485  Assert(pathkeys != NIL);
1486 
1487  /* Compute sort column info, and adjust subplan's tlist as needed */
1488  subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1489  best_path->subpath->parent->relids,
1490  gm_plan->sortColIdx,
1491  false,
1492  &gm_plan->numCols,
1493  &gm_plan->sortColIdx,
1494  &gm_plan->sortOperators,
1495  &gm_plan->collations,
1496  &gm_plan->nullsFirst);
1497 
1498 
1499  /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1500  if (!pathkeys_contained_in(pathkeys, best_path->subpath->pathkeys))
1501  subplan = (Plan *) make_sort(subplan, gm_plan->numCols,
1502  gm_plan->sortColIdx,
1503  gm_plan->sortOperators,
1504  gm_plan->collations,
1505  gm_plan->nullsFirst);
1506 
1507  /* Now insert the subplan under GatherMerge. */
1508  gm_plan->plan.lefttree = subplan;
1509 
1510  /* use parallel mode for parallel plans. */
1511  root->glob->parallelModeNeeded = true;
1512 
1513  return gm_plan;
1514 }
#define NIL
Definition: pg_list.h:69
Oid * collations
Definition: plannodes.h:821
AttrNumber * sortColIdx
Definition: plannodes.h:819
bool * nullsFirst
Definition: plannodes.h:822
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
bool parallelModeNeeded
Definition: relation.h:130
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
RelOptInfo * parent
Definition: relation.h:898
PlannerGlobal * glob
Definition: relation.h:156
Relids relids
Definition: relation.h:494
Oid * sortOperators
Definition: plannodes.h:820
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
List * pathkeys
Definition: relation.h:913
static Sort * make_sort(Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:5372
#define makeNode(_type_)
Definition: nodes.h:566
#define Assert(condition)
Definition: c.h:675
struct Plan * lefttree
Definition: plannodes.h:134
List * targetlist
Definition: plannodes.h:132
Path * subpath
Definition: relation.h:1222
int num_workers
Definition: plannodes.h:816
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
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:5433
static Gather * create_gather_plan ( PlannerInfo root,
GatherPath best_path 
)
static

Definition at line 1433 of file createplan.c.

References build_path_tlist(), copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), PlannerInfo::glob, make_gather(), NIL, Path::parallel_workers, PlannerGlobal::parallelModeNeeded, GatherPath::path, Gather::plan, GatherPath::single_copy, and GatherPath::subpath.

Referenced by create_plan_recurse().

1434 {
1435  Gather *gather_plan;
1436  Plan *subplan;
1437  List *tlist;
1438 
1439  /*
1440  * Although the Gather node can project, we prefer to push down such work
1441  * to its child node, so demand an exact tlist from the child.
1442  */
1443  subplan = create_plan_recurse(root, best_path->subpath, CP_EXACT_TLIST);
1444 
1445  tlist = build_path_tlist(root, &best_path->path);
1446 
1447  gather_plan = make_gather(tlist,
1448  NIL,
1449  best_path->path.parallel_workers,
1450  best_path->single_copy,
1451  subplan);
1452 
1453  copy_generic_path_info(&gather_plan->plan, &best_path->path);
1454 
1455  /* use parallel mode for parallel plans. */
1456  root->glob->parallelModeNeeded = true;
1457 
1458  return gather_plan;
1459 }
#define NIL
Definition: pg_list.h:69
int parallel_workers
Definition: relation.h:905
bool single_copy
Definition: relation.h:1211
static Gather * make_gather(List *qptlist, List *qpqual, int nworkers, bool single_copy, Plan *subplan)
Definition: createplan.c:6125
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
bool parallelModeNeeded
Definition: relation.h:130
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Plan plan
Definition: plannodes.h:803
PlannerGlobal * glob
Definition: relation.h:156
Path * subpath
Definition: relation.h:1210
Path path
Definition: relation.h:1209
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
static Plan * create_gating_plan ( PlannerInfo root,
Path path,
Plan plan,
List gating_quals 
)
static

Definition at line 880 of file createplan.c.

References Assert, build_path_tlist(), copy_plan_costsize(), and make_result().

Referenced by create_join_plan(), and create_scan_plan().

882 {
883  Plan *gplan;
884 
885  Assert(gating_quals);
886 
887  /*
888  * Since we need a Result node anyway, always return the path's requested
889  * tlist; that's never a wrong choice, even if the parent node didn't ask
890  * for CP_EXACT_TLIST.
891  */
892  gplan = (Plan *) make_result(build_path_tlist(root, path),
893  (Node *) gating_quals,
894  plan);
895 
896  /*
897  * Notice that we don't change cost or size estimates when doing gating.
898  * The costs of qual eval were already included in the subplan's cost.
899  * Leaving the size alone amounts to assuming that the gating qual will
900  * succeed, which is the conservative estimate for planning upper queries.
901  * We certainly don't want to assume the output size is zero (unless the
902  * gating qual is actually constant FALSE, and that case is dealt with in
903  * clausesel.c). Interpolating between the two cases is silly, because it
904  * doesn't reflect what will really happen at runtime, and besides which
905  * in most cases we have only a very bad idea of the probability of the
906  * gating qual being true.
907  */
908  copy_plan_costsize(gplan, plan);
909 
910  return gplan;
911 }
Definition: nodes.h:518
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
static void copy_plan_costsize(Plan *dest, Plan *src)
Definition: createplan.c:4787
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6246
#define Assert(condition)
Definition: c.h:675
static Group * create_group_plan ( PlannerInfo root,
GroupPath best_path 
)
static

Definition at line 1636 of file createplan.c.

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

Referenced by create_plan_recurse().

1637 {
1638  Group *plan;
1639  Plan *subplan;
1640  List *tlist;
1641  List *quals;
1642 
1643  /*
1644  * Group can project, so no need to be terribly picky about child tlist,
1645  * but we do need grouping columns to be available
1646  */
1647  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1648 
1649  tlist = build_path_tlist(root, &best_path->path);
1650 
1651  quals = order_qual_clauses(root, best_path->qual);
1652 
1653  plan = make_group(tlist,
1654  quals,
1655  list_length(best_path->groupClause),
1657  subplan->targetlist),
1658  extract_grouping_ops(best_path->groupClause),
1659  subplan);
1660 
1661  copy_generic_path_info(&plan->plan, (Path *) best_path);
1662 
1663  return plan;
1664 }
List * qual
Definition: relation.h:1367
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
Oid * extract_grouping_ops(List *groupClause)
Definition: tlist.c:466
AttrNumber * extract_grouping_cols(List *groupClause, List *tlist)
Definition: tlist.c:492
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Path path
Definition: relation.h:1364
static Group * make_group(List *tlist, List *qual, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, Plan *lefttree)
Definition: createplan.c:5950
List * groupClause
Definition: relation.h:1366
#define CP_LABEL_TLIST
Definition: createplan.c:68
Path * subpath
Definition: relation.h:1365
Plan plan
Definition: plannodes.h:731
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:132
Definition: pg_list.h:45
Definition: relation.h:892
static Plan * create_groupingsets_plan ( PlannerInfo root,
GroupingSetsPath best_path 
)
static

Definition at line 1782 of file createplan.c.

References AGG_PLAIN, AGG_SORTED, AGGSPLIT_SIMPLE, Assert, build_path_tlist(), copy_generic_path_info(), CP_LABEL_TLIST, create_plan_recurse(), extract_grouping_ops(), forboth, get_sortgroupclause_tle(), Query::groupClause, PlannerInfo::grouping_map, Query::groupingSets, PlannerInfo::hasInheritedTarget, lappend(), Plan::lefttree, lfirst, linitial, list_length(), llast, lnext, make_agg(), make_sort_from_groupcols(), NIL, NULL, palloc0(), PlannerInfo::parse, GroupingSetsPath::path, Agg::plan, GroupingSetsPath::qual, remap_groupColIdx(), TargetEntry::resno, GroupingSetsPath::rollup_groupclauses, GroupingSetsPath::rollup_lists, GroupingSetsPath::subpath, Plan::targetlist, and SortGroupClause::tleSortGroupRef.

Referenced by create_plan_recurse().

1783 {
1784  Agg *plan;
1785  Plan *subplan;
1786  List *rollup_groupclauses = best_path->rollup_groupclauses;
1787  List *rollup_lists = best_path->rollup_lists;
1788  AttrNumber *grouping_map;
1789  int maxref;
1790  List *chain;
1791  ListCell *lc,
1792  *lc2;
1793 
1794  /* Shouldn't get here without grouping sets */
1795  Assert(root->parse->groupingSets);
1796  Assert(rollup_lists != NIL);
1797  Assert(list_length(rollup_lists) == list_length(rollup_groupclauses));
1798 
1799  /*
1800  * Agg can project, so no need to be terribly picky about child tlist, but
1801  * we do need grouping columns to be available
1802  */
1803  subplan = create_plan_recurse(root, best_path->subpath, CP_LABEL_TLIST);
1804 
1805  /*
1806  * Compute the mapping from tleSortGroupRef to column index in the child's
1807  * tlist. First, identify max SortGroupRef in groupClause, for array
1808  * sizing.
1809  */
1810  maxref = 0;
1811  foreach(lc, root->parse->groupClause)
1812  {
1813  SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
1814 
1815  if (gc->tleSortGroupRef > maxref)
1816  maxref = gc->tleSortGroupRef;
1817  }
1818 
1819  grouping_map = (AttrNumber *) palloc0((maxref + 1) * sizeof(AttrNumber));
1820 
1821  /* Now look up the column numbers in the child's tlist */
1822  foreach(lc, root->parse->groupClause)
1823  {
1824  SortGroupClause *gc = (SortGroupClause *) lfirst(lc);
1825  TargetEntry *tle = get_sortgroupclause_tle(gc, subplan->targetlist);
1826 
1827  grouping_map[gc->tleSortGroupRef] = tle->resno;
1828  }
1829 
1830  /*
1831  * During setrefs.c, we'll need the grouping_map to fix up the cols lists
1832  * in GroupingFunc nodes. Save it for setrefs.c to use.
1833  *
1834  * This doesn't work if we're in an inheritance subtree (see notes in
1835  * create_modifytable_plan). Fortunately we can't be because there would
1836  * never be grouping in an UPDATE/DELETE; but let's Assert that.
1837  */
1838  Assert(!root->hasInheritedTarget);
1839  Assert(root->grouping_map == NULL);
1840  root->grouping_map = grouping_map;
1841 
1842  /*
1843  * Generate the side nodes that describe the other sort and group
1844  * operations besides the top one. Note that we don't worry about putting
1845  * accurate cost estimates in the side nodes; only the topmost Agg node's
1846  * costs will be shown by EXPLAIN.
1847  */
1848  chain = NIL;
1849  if (list_length(rollup_groupclauses) > 1)
1850  {
1851  forboth(lc, rollup_groupclauses, lc2, rollup_lists)
1852  {
1853  List *groupClause = (List *) lfirst(lc);
1854  List *gsets = (List *) lfirst(lc2);
1855  AttrNumber *new_grpColIdx;
1856  Plan *sort_plan;
1857  Plan *agg_plan;
1858 
1859  /* We want to iterate over all but the last rollup list elements */
1860  if (lnext(lc) == NULL)
1861  break;
1862 
1863  new_grpColIdx = remap_groupColIdx(root, groupClause);
1864 
1865  sort_plan = (Plan *)
1866  make_sort_from_groupcols(groupClause,
1867  new_grpColIdx,
1868  subplan);
1869 
1870  agg_plan = (Plan *) make_agg(NIL,
1871  NIL,
1872  AGG_SORTED,
1874  list_length((List *) linitial(gsets)),
1875  new_grpColIdx,
1876  extract_grouping_ops(groupClause),
1877  gsets,
1878  NIL,
1879  0, /* numGroups not needed */
1880  sort_plan);
1881 
1882  /*
1883  * Nuke stuff we don't need to avoid bloating debug output.
1884  */
1885  sort_plan->targetlist = NIL;
1886  sort_plan->lefttree = NULL;
1887 
1888  chain = lappend(chain, agg_plan);
1889  }
1890  }
1891 
1892  /*
1893  * Now make the final Agg node
1894  */
1895  {
1896  List *groupClause = (List *) llast(rollup_groupclauses);
1897  List *gsets = (List *) llast(rollup_lists);
1898  AttrNumber *top_grpColIdx;
1899  int numGroupCols;
1900 
1901  top_grpColIdx = remap_groupColIdx(root, groupClause);
1902 
1903  numGroupCols = list_length((List *) linitial(gsets));
1904 
1905  plan = make_agg(build_path_tlist(root, &best_path->path),
1906  best_path->qual,
1907  (numGroupCols > 0) ? AGG_SORTED : AGG_PLAIN,
1909  numGroupCols,
1910  top_grpColIdx,
1911  extract_grouping_ops(groupClause),
1912  gsets,
1913  chain,
1914  0, /* numGroups not needed */
1915  subplan);
1916 
1917  /* Copy cost data from Path to Plan */
1918  copy_generic_path_info(&plan->plan, &best_path->path);
1919  }
1920 
1921  return (Plan *) plan;
1922 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:154
TargetEntry * get_sortgroupclause_tle(SortGroupClause *sgClause, List *targetList)
Definition: tlist.c:370
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
static AttrNumber * remap_groupColIdx(PlannerInfo *root, List *groupClause)
Definition: createplan.c:1744
#define llast(l)
Definition: pg_list.h:126
Index tleSortGroupRef
Definition: parsenodes.h:1141
List * groupingSets
Definition: parsenodes.h:139
Oid * extract_grouping_ops(List *groupClause)
Definition: tlist.c:466
AttrNumber * grouping_map
Definition: relation.h:283
Agg * make_agg(List *tlist, List *qual, AggStrategy aggstrategy, AggSplit aggsplit, int numGroupCols, AttrNumber *grpColIdx, Oid *grpOperators, List *groupingSets, List *chain, double dNumGroups, Plan *lefttree)
Definition: createplan.c:5888
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define linitial(l)
Definition: pg_list.h:110
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
List * rollup_lists
Definition: relation.h:1412
AttrNumber resno
Definition: primnodes.h:1353
static Sort * make_sort_from_groupcols(List *groupcls, AttrNumber *grpColIdx, Plan *lefttree)
Definition: createplan.c:5792
#define lnext(lc)
Definition: pg_list.h:105
List * lappend(List *list, void *datum)
Definition: list.c:128
Plan plan
Definition: plannodes.h:753
List * rollup_groupclauses
Definition: relation.h:1411
void * palloc0(Size size)
Definition: mcxt.c:878
#define CP_LABEL_TLIST
Definition: createplan.c:68
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
bool hasInheritedTarget
Definition: relation.h:296
static int list_length(const List *l)
Definition: pg_list.h:89
struct Plan * lefttree
Definition: plannodes.h:134
List * targetlist
Definition: plannodes.h:132
List * groupClause
Definition: parsenodes.h:137
Definition: plannodes.h:751
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
static HashJoin * create_hashjoin_plan ( PlannerInfo root,
HashPath best_path 
)
static

Definition at line 3966 of file createplan.c.

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, JoinPath::innerjoinpath, InvalidAttrNumber, InvalidOid, is_opclause, IS_OUTER_JOIN, IsA, HashJoin::join, JoinPath::joinrestrictinfo, JoinPath::jointype, HashPath::jpath, linitial, list_difference(), list_length(), make_hash(), make_hashjoin(), NIL, HashPath::num_batches, order_qual_clauses(), JoinPath::outerjoinpath, Path::param_info, Path::parent, JoinPath::path, HashPath::path_hashclauses, Join::plan, Hash::plan, RangeTblEntry::relid, RelOptInfo::relids, replace_nestloop_params(), RTE_RELATION, RangeTblEntry::rtekind, PlannerInfo::simple_rte_array, Plan::startup_cost, Plan::total_cost, RangeQueryClause::var, Var::varattno, Var::varno, Var::vartype, and Var::vartypmod.

Referenced by create_join_plan().

3968 {
3969  HashJoin *join_plan;
3970  Hash *hash_plan;
3971  Plan *outer_plan;
3972  Plan *inner_plan;
3973  List *tlist = build_path_tlist(root, &best_path->jpath.path);
3974  List *joinclauses;
3975  List *otherclauses;
3976  List *hashclauses;
3977  Oid skewTable = InvalidOid;
3978  AttrNumber skewColumn = InvalidAttrNumber;
3979  bool skewInherit = false;
3980  Oid skewColType = InvalidOid;
3981  int32 skewColTypmod = -1;
3982 
3983  /*
3984  * HashJoin can project, so we don't have to demand exact tlists from the
3985  * inputs. However, it's best to request a small tlist from the inner
3986  * side, so that we aren't storing more data than necessary. Likewise, if
3987  * we anticipate batching, request a small tlist from the outer side so
3988  * that we don't put extra data in the outer batch files.
3989  */
3990  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
3991  (best_path->num_batches > 1) ? CP_SMALL_TLIST : 0);
3992 
3993  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
3994  CP_SMALL_TLIST);
3995 
3996  /* Sort join qual clauses into best execution order */
3997  joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
3998  /* There's no point in sorting the hash clauses ... */
3999 
4000  /* Get the join qual clauses (in plain expression form) */
4001  /* Any pseudoconstant clauses are ignored here */
4002  if (IS_OUTER_JOIN(best_path->jpath.jointype))
4003  {
4004  extract_actual_join_clauses(joinclauses,
4005  &joinclauses, &otherclauses);
4006  }
4007  else
4008  {
4009  /* We can treat all clauses alike for an inner join */
4010  joinclauses = extract_actual_clauses(joinclauses, false);
4011  otherclauses = NIL;
4012  }
4013 
4014  /*
4015  * Remove the hashclauses from the list of join qual clauses, leaving the
4016  * list of quals that must be checked as qpquals.
4017  */
4018  hashclauses = get_actual_clauses(best_path->path_hashclauses);
4019  joinclauses = list_difference(joinclauses, hashclauses);
4020 
4021  /*
4022  * Replace any outer-relation variables with nestloop params. There
4023  * should not be any in the hashclauses.
4024  */
4025  if (best_path->jpath.path.param_info)
4026  {
4027  joinclauses = (List *)
4028  replace_nestloop_params(root, (Node *) joinclauses);
4029  otherclauses = (List *)
4030  replace_nestloop_params(root, (Node *) otherclauses);
4031  }
4032 
4033  /*
4034  * Rearrange hashclauses, if needed, so that the outer variable is always
4035  * on the left.
4036  */
4037  hashclauses = get_switched_clauses(best_path->path_hashclauses,
4038  best_path->jpath.outerjoinpath->parent->relids);
4039 
4040  /*
4041  * If there is a single join clause and we can identify the outer variable
4042  * as a simple column reference, supply its identity for possible use in
4043  * skew optimization. (Note: in principle we could do skew optimization
4044  * with multiple join clauses, but we'd have to be able to determine the
4045  * most common combinations of outer values, which we don't currently have
4046  * enough stats for.)
4047  */
4048  if (list_length(hashclauses) == 1)
4049  {
4050  OpExpr *clause = (OpExpr *) linitial(hashclauses);
4051  Node *node;
4052 
4053  Assert(is_opclause(clause));
4054  node = (Node *) linitial(clause->args);
4055  if (IsA(node, RelabelType))
4056  node = (Node *) ((RelabelType *) node)->arg;
4057  if (IsA(node, Var))
4058  {
4059  Var *var = (Var *) node;
4060  RangeTblEntry *rte;
4061 
4062  rte = root->simple_rte_array[var->varno];
4063  if (rte->rtekind == RTE_RELATION)
4064  {
4065  skewTable = rte->relid;
4066  skewColumn = var->varattno;
4067  skewInherit = rte->inh;
4068  skewColType = var->vartype;
4069  skewColTypmod = var->vartypmod;
4070  }
4071  }
4072  }
4073 
4074  /*
4075  * Build the hash node and hash join node.
4076  */
4077  hash_plan = make_hash(inner_plan,
4078  skewTable,
4079  skewColumn,
4080  skewInherit,
4081  skewColType,
4082  skewColTypmod);
4083 
4084  /*
4085  * Set Hash node's startup & total costs equal to total cost of input
4086  * plan; this only affects EXPLAIN display not decisions.
4087  */
4088  copy_plan_costsize(&hash_plan->plan, inner_plan);
4089  hash_plan->plan.startup_cost = hash_plan->plan.total_cost;
4090 
4091  join_plan = make_hashjoin(tlist,
4092  joinclauses,
4093  otherclauses,
4094  hashclauses,
4095  outer_plan,
4096  (Plan *) hash_plan,
4097  best_path->jpath.jointype);
4098 
4099  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
4100 
4101  return join_plan;
4102 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
JoinPath jpath
Definition: relation.h:1303
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
static List * get_switched_clauses(List *clauses, Relids outerrelids)
Definition: createplan.c:4602
int num_batches
Definition: relation.h:1305
void extract_actual_join_clauses(List *restrictinfo_list, List **joinquals, List **otherquals)
Definition: restrictinfo.c:381
Path * innerjoinpath
Definition: relation.h:1238
static HashJoin * make_hashjoin(List *tlist, List *joinclauses, List *otherclauses, List *hashclauses, Plan *lefttree, Plan *righttree, JoinType jointype)
Definition: createplan.c:5287
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:724
ParamPathInfo * param_info
Definition: relation.h:901
#define CP_SMALL_TLIST
Definition: createplan.c:67
Definition: nodes.h:518
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:331
AttrNumber varattno
Definition: primnodes.h:168
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
unsigned int Oid
Definition: postgres_ext.h:31
Definition: primnodes.h:163
Join join
Definition: plannodes.h:696
signed int int32
Definition: c.h:256
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define linitial(l)
Definition: pg_list.h:110
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
#define is_opclause(clause)
Definition: clauses.h:20
Oid vartype
Definition: primnodes.h:170
List * joinrestrictinfo
Definition: relation.h:1240
RelOptInfo * parent
Definition: relation.h:898
Cost startup_cost
Definition: plannodes.h:114
static void copy_plan_costsize(Plan *dest, Plan *src)
Definition: createplan.c:4787
Relids relids
Definition: relation.h:494
RangeTblEntry ** simple_rte_array
Definition: relation.h:187
Index varno
Definition: primnodes.h:166
Path * outerjoinpath
Definition: relation.h:1237
#define InvalidOid
Definition: postgres_ext.h:36
Path path
Definition: relation.h:1233
#define Assert(condition)
Definition: c.h:675
static int list_length(const List *l)
Definition: pg_list.h:89
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
List * list_difference(const List *list1, const List *list2)
Definition: list.c:858
#define InvalidAttrNumber
Definition: attnum.h:23
RTEKind rtekind
Definition: parsenodes.h:916
Plan plan
Definition: plannodes.h:836
static Hash * make_hash(Plan *lefttree, Oid skewTable, AttrNumber skewColumn, bool skewInherit, Oid skewColType, int32 skewColTypmod)
Definition: createplan.c:5310
JoinType jointype
Definition: relation.h:1235
Cost total_cost
Definition: plannodes.h:115
List * path_hashclauses
Definition: relation.h:1304
List * args
Definition: primnodes.h:501
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
Plan plan
Definition: plannodes.h:639
int32 vartypmod
Definition: primnodes.h:171
static Scan * create_indexscan_plan ( PlannerInfo root,
IndexPath best_path,
List tlist,
List scan_clauses,
bool  indexonly 
)
static

Definition at line 2459 of file createplan.c.

References Assert, castNode, RestrictInfo::clause, contain_mutable_functions(), copy_generic_path_info(), elog, ERROR, exprType(), extract_actual_clauses(), fix_indexorderby_references(), fix_indexqual_references(), forboth, get_actual_clauses(), get_opfamily_member(), IndexPath::indexinfo, IndexOptInfo::indexoid, IndexPath::indexorderbys, IndexPath::indexquals, IndexPath::indexscandir, IndexOptInfo::indextlist, is_redundant_derived_clause(), lappend(), lappend_oid(), lfirst, list_length(), list_make1, list_member_ptr(), make_indexonlyscan(), make_indexscan(), NIL, OidIsValid, order_qual_clauses(), Path::param_info, Path::parent, IndexPath::path, Path::pathkeys, PathKey::pk_opfamily, PathKey::pk_strategy, Scan::plan, predicate_implied_by(), RestrictInfo::pseudoconstant, RelOptInfo::relid, replace_nestloop_params(), RTE_RELATION, and RelOptInfo::rtekind.

Referenced by create_bitmap_subplan(), and create_scan_plan().

2464 {
2465  Scan *scan_plan;
2466  List *indexquals = best_path->indexquals;
2467  List *indexorderbys = best_path->indexorderbys;
2468  Index baserelid = best_path->path.parent->relid;
2469  Oid indexoid = best_path->indexinfo->indexoid;
2470  List *qpqual;
2471  List *stripped_indexquals;
2472  List *fixed_indexquals;
2473  List *fixed_indexorderbys;
2474  List *indexorderbyops = NIL;
2475  ListCell *l;
2476 
2477  /* it should be a base rel... */
2478  Assert(baserelid > 0);
2479  Assert(best_path->path.parent->rtekind == RTE_RELATION);
2480 
2481  /*
2482  * Build "stripped" indexquals structure (no RestrictInfos) to pass to
2483  * executor as indexqualorig
2484  */
2485  stripped_indexquals = get_actual_clauses(indexquals);
2486 
2487  /*
2488  * The executor needs a copy with the indexkey on the left of each clause
2489  * and with index Vars substituted for table ones.
2490  */
2491  fixed_indexquals = fix_indexqual_references(root, best_path);
2492 
2493  /*
2494  * Likewise fix up index attr references in the ORDER BY expressions.
2495  */
2496  fixed_indexorderbys = fix_indexorderby_references(root, best_path);
2497 
2498  /*
2499  * The qpqual list must contain all restrictions not automatically handled
2500  * by the index, other than pseudoconstant clauses which will be handled
2501  * by a separate gating plan node. All the predicates in the indexquals
2502  * will be checked (either by the index itself, or by nodeIndexscan.c),
2503  * but if there are any "special" operators involved then they must be
2504  * included in qpqual. The upshot is that qpqual must contain
2505  * scan_clauses minus whatever appears in indexquals.
2506  *
2507  * In normal cases simple pointer equality checks will be enough to spot
2508  * duplicate RestrictInfos, so we try that first.
2509  *
2510  * Another common case is that a scan_clauses entry is generated from the
2511  * same EquivalenceClass as some indexqual, and is therefore redundant
2512  * with it, though not equal. (This happens when indxpath.c prefers a
2513  * different derived equality than what generate_join_implied_equalities
2514  * picked for a parameterized scan's ppi_clauses.)
2515  *
2516  * In some situations (particularly with OR'd index conditions) we may
2517  * have scan_clauses that are not equal to, but are logically implied by,
2518  * the index quals; so we also try a predicate_implied_by() check to see
2519  * if we can discard quals that way. (predicate_implied_by assumes its
2520  * first input contains only immutable functions, so we have to check
2521  * that.)
2522  *
2523  * Note: if you change this bit of code you should also look at
2524  * extract_nonindex_conditions() in costsize.c.
2525  */
2526  qpqual = NIL;
2527  foreach(l, scan_clauses)
2528  {
2529  RestrictInfo *rinfo = castNode(RestrictInfo, lfirst(l));
2530 
2531  if (rinfo->pseudoconstant)
2532  continue; /* we may drop pseudoconstants here */
2533  if (list_member_ptr(indexquals, rinfo))
2534  continue; /* simple duplicate */
2535  if (is_redundant_derived_clause(rinfo, indexquals))
2536  continue; /* derived from same EquivalenceClass */
2537  if (!contain_mutable_functions((Node *) rinfo->clause) &&
2538  predicate_implied_by(list_make1(rinfo->clause), indexquals))
2539  continue; /* provably implied by indexquals */
2540  qpqual = lappend(qpqual, rinfo);
2541  }
2542 
2543  /* Sort clauses into best execution order */
2544  qpqual = order_qual_clauses(root, qpqual);
2545 
2546  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2547  qpqual = extract_actual_clauses(qpqual, false);
2548 
2549  /*
2550  * We have to replace any outer-relation variables with nestloop params in
2551  * the indexqualorig, qpqual, and indexorderbyorig expressions. A bit
2552  * annoying to have to do this separately from the processing in
2553  * fix_indexqual_references --- rethink this when generalizing the inner
2554  * indexscan support. But note we can't really do this earlier because
2555  * it'd break the comparisons to predicates above ... (or would it? Those
2556  * wouldn't have outer refs)
2557  */
2558  if (best_path->path.param_info)
2559  {
2560  stripped_indexquals = (List *)
2561  replace_nestloop_params(root, (Node *) stripped_indexquals);
2562  qpqual = (List *)
2563  replace_nestloop_params(root, (Node *) qpqual);
2564  indexorderbys = (List *)
2565  replace_nestloop_params(root, (Node *) indexorderbys);
2566  }
2567 
2568  /*
2569  * If there are ORDER BY expressions, look up the sort operators for their
2570  * result datatypes.
2571  */
2572  if (indexorderbys)
2573  {
2574  ListCell *pathkeyCell,
2575  *exprCell;
2576 
2577  /*
2578  * PathKey contains OID of the btree opfamily we're sorting by, but
2579  * that's not quite enough because we need the expression's datatype
2580  * to look up the sort operator in the operator family.
2581  */
2582  Assert(list_length(best_path->path.pathkeys) == list_length(indexorderbys));
2583  forboth(pathkeyCell, best_path->path.pathkeys, exprCell, indexorderbys)
2584  {
2585  PathKey *pathkey = (PathKey *) lfirst(pathkeyCell);
2586  Node *expr = (Node *) lfirst(exprCell);
2587  Oid exprtype = exprType(expr);
2588  Oid sortop;
2589 
2590  /* Get sort operator from opfamily */
2591  sortop = get_opfamily_member(pathkey->pk_opfamily,
2592  exprtype,
2593  exprtype,
2594  pathkey->pk_strategy);
2595  if (!OidIsValid(sortop))
2596  elog(ERROR, "failed to find sort operator for ORDER BY expression");
2597  indexorderbyops = lappend_oid(indexorderbyops, sortop);
2598  }
2599  }
2600 
2601  /* Finally ready to build the plan node */
2602  if (indexonly)
2603  scan_plan = (Scan *) make_indexonlyscan(tlist,
2604  qpqual,
2605  baserelid,
2606  indexoid,
2607  fixed_indexquals,
2608  fixed_indexorderbys,
2609  best_path->indexinfo->indextlist,
2610  best_path->indexscandir);
2611  else
2612  scan_plan = (Scan *) make_indexscan(tlist,
2613  qpqual,
2614  baserelid,
2615  indexoid,
2616  fixed_indexquals,
2617  stripped_indexquals,
2618  fixed_indexorderbys,
2619  indexorderbys,
2620  indexorderbyops,
2621  best_path->indexscandir);
2622 
2623  copy_generic_path_info(&scan_plan->plan, &best_path->path);
2624 
2625  return scan_plan;
2626 }
#define NIL
Definition: pg_list.h:69
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
Path path
Definition: relation.h:975
bool is_redundant_derived_clause(RestrictInfo *rinfo, List *clauselist)
Definition: equivclass.c:2448
IndexOptInfo * indexinfo
Definition: relation.h:976
bool predicate_implied_by(List *predicate_list, List *restrictinfo_list)
Definition: predtest.c:128
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
List * indextlist
Definition: relation.h:617
bool pseudoconstant
Definition: relation.h:1668
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:331
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
unsigned int Oid
Definition: postgres_ext.h:31
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:538
int pk_strategy
Definition: relation.h:797
#define list_make1(x1)
Definition: pg_list.h:133
List * indexquals
Definition: relation.h:978
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define ERROR
Definition: elog.h:43
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:4896
RelOptInfo * parent
Definition: relation.h:898
Oid get_opfamily_member(Oid opfamily, Oid lefttype, Oid righttype, int16 strategy)
Definition: lsyscache.c:163
static List * fix_indexorderby_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:4470
static List * fix_indexqual_references(PlannerInfo *root, IndexPath *index_path)
Definition: createplan.c:4339
Index relid
Definition: relation.h:522
List * lappend(List *list, void *datum)
Definition: list.c:128
Expr * clause
Definition: relation.h:1660
List * indexorderbys
Definition: relation.h:980
unsigned int Index
Definition: c.h:365
RTEKind rtekind
Definition: relation.h:524
bool list_member_ptr(const List *list, const void *datum)
Definition: list.c:465
List * pathkeys
Definition: relation.h:913
static IndexOnlyScan * make_indexonlyscan(List *qptlist, List *qpqual, Index scanrelid, Oid indexid, List *indexqual, List *indexorderby, List *indextlist, ScanDirection indexscandir)
Definition: createplan.c:4927
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
static int list_length(const List *l)
Definition: pg_list.h:89
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
Oid pk_opfamily
Definition: relation.h:796
ScanDirection indexscandir
Definition: relation.h:982
bool contain_mutable_functions(Node *clause)
Definition: clauses.c:877
#define elog
Definition: elog.h:219
Oid indexoid
Definition: relation.h:592
Definition: pg_list.h:45
static Plan * create_join_plan ( PlannerInfo root,
JoinPath best_path 
)
static

Definition at line 919 of file createplan.c.

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, NULL, JoinPath::path, Path::pathtype, T_HashJoin, T_MergeJoin, and T_NestLoop.

Referenced by create_plan_recurse().

920 {
921  Plan *plan;
922  List *gating_clauses;
923 
924  switch (best_path->path.pathtype)
925  {
926  case T_MergeJoin:
927  plan = (Plan *) create_mergejoin_plan(root,
928  (MergePath *) best_path);
929  break;
930  case T_HashJoin:
931  plan = (Plan *) create_hashjoin_plan(root,
932  (HashPath *) best_path);
933  break;
934  case T_NestLoop:
935  plan = (Plan *) create_nestloop_plan(root,
936  (NestPath *) best_path);
937  break;
938  default:
939  elog(ERROR, "unrecognized node type: %d",
940  (int) best_path->path.pathtype);
941  plan = NULL; /* keep compiler quiet */
942  break;
943  }
944 
945  /*
946  * If there are any pseudoconstant clauses attached to this node, insert a
947  * gating Result node that evaluates the pseudoconstants as one-time
948  * quals.
949  */
950  gating_clauses = get_gating_quals(root, best_path->joinrestrictinfo);
951  if (gating_clauses)
952  plan = create_gating_plan(root, (Path *) best_path, plan,
953  gating_clauses);
954 
955 #ifdef NOT_USED
956 
957  /*
958  * * Expensive function pullups may have pulled local predicates * into
959  * this path node. Put them in the qpqual of the plan node. * JMH,
960  * 6/15/92
961  */
962  if (get_loc_restrictinfo(best_path) != NIL)
963  set_qpqual((Plan) plan,
964  list_concat(get_qpqual((Plan) plan),
965  get_actual_clauses(get_loc_restrictinfo(best_path))));
966 #endif
967 
968  return plan;
969 }
#define NIL
Definition: pg_list.h:69
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:331
List * list_concat(List *list1, List *list2)
Definition: list.c:321
static NestLoop * create_nestloop_plan(PlannerInfo *root, NestPath *best_path)
Definition: createplan.c:3558
NodeTag pathtype
Definition: relation.h:896
#define ERROR
Definition: elog.h:43
List * joinrestrictinfo
Definition: relation.h:1240
#define NULL
Definition: c.h:229
Path path
Definition: relation.h:1233
static HashJoin * create_hashjoin_plan(PlannerInfo *root, HashPath *best_path)
Definition: createplan.c:3966
static Plan * create_gating_plan(PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
Definition: createplan.c:880
#define elog
Definition: elog.h:219
static MergeJoin * create_mergejoin_plan(PlannerInfo *root, MergePath *best_path)
Definition: createplan.c:3663
Definition: pg_list.h:45
Definition: relation.h:892
static List * get_gating_quals(PlannerInfo *root, List *quals)
Definition: createplan.c:860
static Limit * create_limit_plan ( PlannerInfo root,
LimitPath best_path,
int  flags 
)
static

Definition at line 2339 of file createplan.c.

References copy_generic_path_info(), create_plan_recurse(), LimitPath::limitCount, LimitPath::limitOffset, make_limit(), Limit::plan, and LimitPath::subpath.

Referenced by create_plan_recurse().

2340 {
2341  Limit *plan;
2342  Plan *subplan;
2343 
2344  /* Limit doesn't project, so tlist requirements pass through */
2345  subplan = create_plan_recurse(root, best_path->subpath, flags);
2346 
2347  plan = make_limit(subplan,
2348  best_path->limitOffset,
2349  best_path->limitCount);
2350 
2351  copy_generic_path_info(&plan->plan, (Path *) best_path);
2352 
2353  return plan;
2354 }
Plan plan
Definition: plannodes.h:888
Node * limitOffset
Definition: relation.h:1512
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Path * subpath
Definition: relation.h:1511
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
Definition: createplan.c:6225
Node * limitCount
Definition: relation.h:1513
Definition: relation.h:892
static LockRows * create_lockrows_plan ( PlannerInfo root,
LockRowsPath best_path,
int  flags 
)
static

Definition at line 2257 of file createplan.c.

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

Referenced by create_plan_recurse().

2259 {
2260  LockRows *plan;
2261  Plan *subplan;
2262 
2263  /* LockRows doesn't project, so tlist requirements pass through */
2264  subplan = create_plan_recurse(root, best_path->subpath, flags);
2265 
2266  plan = make_lockrows(subplan, best_path->rowMarks, best_path->epqParam);
2267 
2268  copy_generic_path_info(&plan->plan, (Path *) best_path);
2269 
2270  return plan;
2271 }
Plan plan
Definition: plannodes.h:874
List * rowMarks
Definition: relation.h:1476
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Path * subpath
Definition: relation.h:1475
static LockRows * make_lockrows(Plan *lefttree, List *rowMarks, int epqParam)
Definition: createplan.c:6204
Definition: relation.h:892
static Material * create_material_plan ( PlannerInfo root,
MaterialPath best_path,
int  flags 
)
static

Definition at line 1203 of file createplan.c.

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

Referenced by create_plan_recurse().

1204 {
1205  Material *plan;
1206  Plan *subplan;
1207 
1208  /*
1209  * We don't want any excess columns in the materialized tuples, so request
1210  * a smaller tlist. Otherwise, since Material doesn't project, tlist
1211  * requirements pass through.
1212  */
1213  subplan = create_plan_recurse(root, best_path->subpath,
1214  flags | CP_SMALL_TLIST);
1215 
1216  plan = make_material(subplan);
1217 
1218  copy_generic_path_info(&plan->plan, (Path *) best_path);
1219 
1220  return plan;
1221 }
#define CP_SMALL_TLIST
Definition: createplan.c:67
Path * subpath
Definition: relation.h:1171
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static Material * make_material(Plan *lefttree)
Definition: createplan.c:5833
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Plan plan
Definition: plannodes.h:706
Definition: relation.h:892
static Plan * create_merge_append_plan ( PlannerInfo root,
MergeAppendPath best_path 
)
static

Definition at line 1044 of file createplan.c.

References Assert, build_path_tlist(), MergeAppend::collations, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), elog, ERROR, label_sort_with_costsize(), lappend(), Plan::lefttree, lfirst, MergeAppendPath::limit_tuples, make_sort(), makeNode, MergeAppend::mergeplans, NIL, NULL, MergeAppend::nullsFirst, MergeAppend::numCols, Path::parent, MergeAppend::partitioned_rels, MergeAppendPath::partitioned_rels, MergeAppendPath::path, Path::pathkeys, pathkeys_contained_in(), MergeAppend::plan, prepare_sort_from_pathkeys(), Plan::qual, RelOptInfo::relids, Plan::righttree, sort(), MergeAppend::sortColIdx, MergeAppend::sortOperators, subpath(), MergeAppendPath::subpaths, and Plan::targetlist.

Referenced by create_plan_recurse().

1045 {
1046  MergeAppend *node = makeNode(MergeAppend);
1047  Plan *plan = &node->plan;
1048  List *tlist = build_path_tlist(root, &best_path->path);
1049  List *pathkeys = best_path->path.pathkeys;
1050  List *subplans = NIL;
1051  ListCell *subpaths;
1052 
1053  /*
1054  * We don't have the actual creation of the MergeAppend node split out
1055  * into a separate make_xxx function. This is because we want to run
1056  * prepare_sort_from_pathkeys on it before we do so on the individual
1057  * child plans, to make cross-checking the sort info easier.
1058  */
1059  copy_generic_path_info(plan, (Path *) best_path);
1060  plan->targetlist = tlist;
1061  plan->qual = NIL;
1062  plan->lefttree = NULL;
1063  plan->righttree = NULL;
1064 
1065  /* Compute sort column info, and adjust MergeAppend's tlist as needed */
1066  (void) prepare_sort_from_pathkeys(plan, pathkeys,
1067  best_path->path.parent->relids,
1068  NULL,
1069  true,
1070  &node->numCols,
1071  &node->sortColIdx,
1072  &node->sortOperators,
1073  &node->collations,
1074  &node->nullsFirst);
1075 
1076  /*
1077  * Now prepare the child plans. We must apply prepare_sort_from_pathkeys
1078  * even to subplans that don't need an explicit sort, to make sure they
1079  * are returning the same sort key columns the MergeAppend expects.
1080  */
1081  foreach(subpaths, best_path->subpaths)
1082  {
1083  Path *subpath = (Path *) lfirst(subpaths);
1084  Plan *subplan;
1085  int numsortkeys;
1086  AttrNumber *sortColIdx;
1087  Oid *sortOperators;
1088  Oid *collations;
1089  bool *nullsFirst;
1090 
1091  /* Build the child plan */
1092  /* Must insist that all children return the same tlist */
1093  subplan = create_plan_recurse(root, subpath, CP_EXACT_TLIST);
1094 
1095  /* Compute sort column info, and adjust subplan's tlist as needed */
1096  subplan = prepare_sort_from_pathkeys(subplan, pathkeys,
1097  subpath->parent->relids,
1098  node->sortColIdx,
1099  false,
1100  &numsortkeys,
1101  &sortColIdx,
1102  &sortOperators,
1103  &collations,
1104  &nullsFirst);
1105 
1106  /*
1107  * Check that we got the same sort key information. We just Assert
1108  * that the sortops match, since those depend only on the pathkeys;
1109  * but it seems like a good idea to check the sort column numbers
1110  * explicitly, to ensure the tlists really do match up.
1111  */
1112  Assert(numsortkeys == node->numCols);
1113  if (memcmp(sortColIdx, node->sortColIdx,
1114  numsortkeys * sizeof(AttrNumber)) != 0)
1115  elog(ERROR, "MergeAppend child's targetlist doesn't match MergeAppend");
1116  Assert(memcmp(sortOperators, node->sortOperators,
1117  numsortkeys * sizeof(Oid)) == 0);
1118  Assert(memcmp(collations, node->collations,
1119  numsortkeys * sizeof(Oid)) == 0);
1120  Assert(memcmp(nullsFirst, node->nullsFirst,
1121  numsortkeys * sizeof(bool)) == 0);
1122 
1123  /* Now, insert a Sort node if subplan isn't sufficiently ordered */
1124  if (!pathkeys_contained_in(pathkeys, subpath->pathkeys))
1125  {
1126  Sort *sort = make_sort(subplan, numsortkeys,
1127  sortColIdx, sortOperators,
1128  collations, nullsFirst);
1129 
1130  label_sort_with_costsize(root, sort, best_path->limit_tuples);
1131  subplan = (Plan *) sort;
1132  }
1133 
1134  subplans = lappend(subplans, subplan);
1135  }
1136 
1137  node->partitioned_rels = best_path->partitioned_rels;
1138  node->mergeplans = subplans;
1139 
1140  return (Plan *) node;
1141 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:133
Oid * collations
Definition: plannodes.h:255
List * partitioned_rels
Definition: relation.h:1144
unsigned int Oid
Definition: postgres_ext.h:31
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
struct Plan * righttree
Definition: plannodes.h:135
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define ERROR
Definition: elog.h:43
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
RelOptInfo * parent
Definition: relation.h:898
List * partitioned_rels
Definition: plannodes.h:249
Datum sort(PG_FUNCTION_ARGS)
Definition: _int_op.c:200
Relids relids
Definition: relation.h:494
List * lappend(List *list, void *datum)
Definition: list.c:128
bool pathkeys_contained_in(List *keys1, List *keys2)
Definition: pathkeys.c:317
List * pathkeys
Definition: relation.h:913
static Sort * make_sort(Plan *lefttree, int numCols, AttrNumber *sortColIdx, Oid *sortOperators, Oid *collations, bool *nullsFirst)
Definition: createplan.c:5372
#define makeNode(_type_)
Definition: nodes.h:566
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
AttrNumber * sortColIdx
Definition: plannodes.h:253
struct Plan * lefttree
Definition: plannodes.h:134
List * targetlist
Definition: plannodes.h:132
bool * nullsFirst
Definition: plannodes.h:256
List * mergeplans
Definition: plannodes.h:250
Oid * sortOperators
Definition: plannodes.h:254
List * subpaths
Definition: relation.h:1145
#define elog
Definition: elog.h:219
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Definition: createplan.c:4807
Definition: relation.h:892
double limit_tuples
Definition: relation.h:1146
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
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:5433
static MergeJoin * create_mergejoin_plan ( PlannerInfo root,
MergePath best_path 
)
static

Definition at line 3663 of file createplan.c.

References Assert, build_path_tlist(), castNode, copy_generic_path_info(), copy_plan_costsize(), CP_SMALL_TLIST, cpu_operator_cost, create_plan_recurse(), EquivalenceClass::ec_collation, elog, ERROR, extract_actual_clauses(), extract_actual_join_clauses(), get_actual_clauses(), get_switched_clauses(), i, JoinPath::innerjoinpath, MergePath::innersortkeys, IS_OUTER_JOIN, MergeJoin::join, JoinPath::joinrestrictinfo, JoinPath::jointype, MergePath::jpath, label_sort_with_costsize(), RestrictInfo::left_ec, lfirst, list_difference(), list_head(), list_length(), lnext, make_material(), make_mergejoin(), make_sort_from_pathkeys(), MergePath::materialize_inner, NIL, NULL, order_qual_clauses(), RestrictInfo::outer_is_left, JoinPath::outerjoinpath, MergePath::outersortkeys, palloc(), Path::param_info, Path::parent, JoinPath::path, MergePath::path_mergeclauses, Path::pathkeys, PathKey::pk_eclass, PathKey::pk_nulls_first, PathKey::pk_opfamily, PathKey::pk_strategy, Join::plan, Plan::plan_rows, RelOptInfo::relids, replace_nestloop_params(), RestrictInfo::right_ec, sort(), and Plan::total_cost.

Referenced by create_join_plan().

3665 {
3666  MergeJoin *join_plan;
3667  Plan *outer_plan;
3668  Plan *inner_plan;
3669  List *tlist = build_path_tlist(root, &best_path->jpath.path);
3670  List *joinclauses;
3671  List *otherclauses;
3672  List *mergeclauses;
3673  List *outerpathkeys;
3674  List *innerpathkeys;
3675  int nClauses;
3676  Oid *mergefamilies;
3677  Oid *mergecollations;
3678  int *mergestrategies;
3679  bool *mergenullsfirst;
3680  int i;
3681  ListCell *lc;
3682  ListCell *lop;
3683  ListCell *lip;
3684 
3685  /*
3686  * MergeJoin can project, so we don't have to demand exact tlists from the
3687  * inputs. However, if we're intending to sort an input's result, it's
3688  * best to request a small tlist so we aren't sorting more data than
3689  * necessary.
3690  */
3691  outer_plan = create_plan_recurse(root, best_path->jpath.outerjoinpath,
3692  (best_path->outersortkeys != NIL) ? CP_SMALL_TLIST : 0);
3693 
3694  inner_plan = create_plan_recurse(root, best_path->jpath.innerjoinpath,
3695  (best_path->innersortkeys != NIL) ? CP_SMALL_TLIST : 0);
3696 
3697  /* Sort join qual clauses into best execution order */
3698  /* NB: do NOT reorder the mergeclauses */
3699  joinclauses = order_qual_clauses(root, best_path->jpath.joinrestrictinfo);
3700 
3701  /* Get the join qual clauses (in plain expression form) */
3702  /* Any pseudoconstant clauses are ignored here */
3703  if (IS_OUTER_JOIN(best_path->jpath.jointype))
3704  {
3705  extract_actual_join_clauses(joinclauses,
3706  &joinclauses, &otherclauses);
3707  }
3708  else
3709  {
3710  /* We can treat all clauses alike for an inner join */
3711  joinclauses = extract_actual_clauses(joinclauses, false);
3712  otherclauses = NIL;
3713  }
3714 
3715  /*
3716  * Remove the mergeclauses from the list of join qual clauses, leaving the
3717  * list of quals that must be checked as qpquals.
3718  */
3719  mergeclauses = get_actual_clauses(best_path->path_mergeclauses);
3720  joinclauses = list_difference(joinclauses, mergeclauses);
3721 
3722  /*
3723  * Replace any outer-relation variables with nestloop params. There
3724  * should not be any in the mergeclauses.
3725  */
3726  if (best_path->jpath.path.param_info)
3727  {
3728  joinclauses = (List *)
3729  replace_nestloop_params(root, (Node *) joinclauses);
3730  otherclauses = (List *)
3731  replace_nestloop_params(root, (Node *) otherclauses);
3732  }
3733 
3734  /*
3735  * Rearrange mergeclauses, if needed, so that the outer variable is always
3736  * on the left; mark the mergeclause restrictinfos with correct
3737  * outer_is_left status.
3738  */
3739  mergeclauses = get_switched_clauses(best_path->path_mergeclauses,
3740  best_path->jpath.outerjoinpath->parent->relids);
3741 
3742  /*
3743  * Create explicit sort nodes for the outer and inner paths if necessary.
3744  */
3745  if (best_path->outersortkeys)
3746  {
3747  Sort *sort = make_sort_from_pathkeys(outer_plan,
3748  best_path->outersortkeys);
3749 
3750  label_sort_with_costsize(root, sort, -1.0);
3751  outer_plan = (Plan *) sort;
3752  outerpathkeys = best_path->outersortkeys;
3753  }
3754  else
3755  outerpathkeys = best_path->jpath.outerjoinpath->pathkeys;
3756 
3757  if (best_path->innersortkeys)
3758  {
3759  Sort *sort = make_sort_from_pathkeys(inner_plan,
3760  best_path->innersortkeys);
3761 
3762  label_sort_with_costsize(root, sort, -1.0);
3763  inner_plan = (Plan *) sort;
3764  innerpathkeys = best_path->innersortkeys;
3765  }
3766  else
3767  innerpathkeys = best_path->jpath.innerjoinpath->pathkeys;
3768 
3769  /*
3770  * If specified, add a materialize node to shield the inner plan from the
3771  * need to handle mark/restore.
3772  */
3773  if (best_path->materialize_inner)
3774  {
3775  Plan *matplan = (Plan *) make_material(inner_plan);
3776 
3777  /*
3778  * We assume the materialize will not spill to disk, and therefore
3779  * charge just cpu_operator_cost per tuple. (Keep this estimate in
3780  * sync with final_cost_mergejoin.)
3781  */
3782  copy_plan_costsize(matplan, inner_plan);
3783  matplan->total_cost += cpu_operator_cost * matplan->plan_rows;
3784 
3785  inner_plan = matplan;
3786  }
3787 
3788  /*
3789  * Compute the opfamily/collation/strategy/nullsfirst arrays needed by the
3790  * executor. The information is in the pathkeys for the two inputs, but
3791  * we need to be careful about the possibility of mergeclauses sharing a
3792  * pathkey (compare find_mergeclauses_for_pathkeys()).
3793  */
3794  nClauses = list_length(mergeclauses);
3795  Assert(nClauses == list_length(best_path->path_mergeclauses));
3796  mergefamilies = (Oid *) palloc(nClauses * sizeof(Oid));
3797  mergecollations = (Oid *) palloc(nClauses * sizeof(Oid));
3798  mergestrategies = (int *) palloc(nClauses * sizeof(int));
3799  mergenullsfirst = (bool *) palloc(nClauses * sizeof(bool));
3800 
3801  lop = list_head(outerpathkeys);
3802  lip = list_head(innerpathkeys);
3803  i = 0;
3804  foreach(lc, best_path->path_mergeclauses)
3805  {
3806  RestrictInfo *rinfo = castNode(RestrictInfo, lfirst(lc));
3807  EquivalenceClass *oeclass;
3808  EquivalenceClass *ieclass;
3809  PathKey *opathkey;
3810  PathKey *ipathkey;
3811  EquivalenceClass *opeclass;
3812  EquivalenceClass *ipeclass;
3813  ListCell *l2;
3814 
3815  /* fetch outer/inner eclass from mergeclause */
3816  if (rinfo->outer_is_left)
3817  {
3818  oeclass = rinfo->left_ec;
3819  ieclass = rinfo->right_ec;
3820  }
3821  else
3822  {
3823  oeclass = rinfo->right_ec;
3824  ieclass = rinfo->left_ec;
3825  }
3826  Assert(oeclass != NULL);
3827  Assert(ieclass != NULL);
3828 
3829  /*
3830  * For debugging purposes, we check that the eclasses match the paths'
3831  * pathkeys. In typical cases the merge clauses are one-to-one with
3832  * the pathkeys, but when dealing with partially redundant query
3833  * conditions, we might have clauses that re-reference earlier path
3834  * keys. The case that we need to reject is where a pathkey is
3835  * entirely skipped over.
3836  *
3837  * lop and lip reference the first as-yet-unused pathkey elements;
3838  * it's okay to match them, or any element before them. If they're
3839  * NULL then we have found all pathkey elements to be used.
3840  */
3841  if (lop)
3842  {
3843  opathkey = (PathKey *) lfirst(lop);
3844  opeclass = opathkey->pk_eclass;
3845  if (oeclass == opeclass)
3846  {
3847  /* fast path for typical case */
3848  lop = lnext(lop);
3849  }
3850  else
3851  {
3852  /* redundant clauses ... must match something before lop */
3853  foreach(l2, outerpathkeys)
3854  {
3855  if (l2 == lop)
3856  break;
3857  opathkey = (PathKey *) lfirst(l2);
3858  opeclass = opathkey->pk_eclass;
3859  if (oeclass == opeclass)
3860  break;
3861  }
3862  if (oeclass != opeclass)
3863  elog(ERROR, "outer pathkeys do not match mergeclauses");
3864  }
3865  }
3866  else
3867  {
3868  /* redundant clauses ... must match some already-used pathkey */
3869  opathkey = NULL;
3870  opeclass = NULL;
3871  foreach(l2, outerpathkeys)
3872  {
3873  opathkey = (PathKey *) lfirst(l2);
3874  opeclass = opathkey->pk_eclass;
3875  if (oeclass == opeclass)
3876  break;
3877  }
3878  if (l2 == NULL)
3879  elog(ERROR, "outer pathkeys do not match mergeclauses");
3880  }
3881 
3882  if (lip)
3883  {
3884  ipathkey = (PathKey *) lfirst(lip);
3885  ipeclass = ipathkey->pk_eclass;
3886  if (ieclass == ipeclass)
3887  {
3888  /* fast path for typical case */
3889  lip = lnext(lip);
3890  }
3891  else
3892  {
3893  /* redundant clauses ... must match something before lip */
3894  foreach(l2, innerpathkeys)
3895  {
3896  if (l2 == lip)
3897  break;
3898  ipathkey = (PathKey *) lfirst(l2);
3899  ipeclass = ipathkey->pk_eclass;
3900  if (ieclass == ipeclass)
3901  break;
3902  }
3903  if (ieclass != ipeclass)
3904  elog(ERROR, "inner pathkeys do not match mergeclauses");
3905  }
3906  }
3907  else
3908  {
3909  /* redundant clauses ... must match some already-used pathkey */
3910  ipathkey = NULL;
3911  ipeclass = NULL;
3912  foreach(l2, innerpathkeys)
3913  {
3914  ipathkey = (PathKey *) lfirst(l2);
3915  ipeclass = ipathkey->pk_eclass;
3916  if (ieclass == ipeclass)
3917  break;
3918  }
3919  if (l2 == NULL)
3920  elog(ERROR, "inner pathkeys do not match mergeclauses");
3921  }
3922 
3923  /* pathkeys should match each other too (more debugging) */
3924  if (opathkey->pk_opfamily != ipathkey->pk_opfamily ||
3925  opathkey->pk_eclass->ec_collation != ipathkey->pk_eclass->ec_collation ||
3926  opathkey->pk_strategy != ipathkey->pk_strategy ||
3927  opathkey->pk_nulls_first != ipathkey->pk_nulls_first)
3928  elog(ERROR, "left and right pathkeys do not match in mergejoin");
3929 
3930  /* OK, save info for executor */
3931  mergefamilies[i] = opathkey->pk_opfamily;
3932  mergecollations[i] = opathkey->pk_eclass->ec_collation;
3933  mergestrategies[i] = opathkey->pk_strategy;
3934  mergenullsfirst[i] = opathkey->pk_nulls_first;
3935  i++;
3936  }
3937 
3938  /*
3939  * Note: it is not an error if we have additional pathkey elements (i.e.,
3940  * lop or lip isn't NULL here). The input paths might be better-sorted
3941  * than we need for the current mergejoin.
3942  */
3943 
3944  /*
3945  * Now we can build the mergejoin node.
3946  */
3947  join_plan = make_mergejoin(tlist,
3948  joinclauses,
3949  otherclauses,
3950  mergeclauses,
3951  mergefamilies,
3952  mergecollations,
3953  mergestrategies,
3954  mergenullsfirst,
3955  outer_plan,
3956  inner_plan,
3957  best_path->jpath.jointype);
3958 
3959  /* Costs of sort and material steps are included in path cost already */
3960  copy_generic_path_info(&join_plan->join.plan, &best_path->jpath.path);
3961 
3962  return join_plan;
3963 }
#define NIL
Definition: pg_list.h:69
List * path_mergeclauses
Definition: relation.h:1286
List * outersortkeys
Definition: relation.h:1287
double plan_rows
Definition: plannodes.h:120
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
static List * get_switched_clauses(List *clauses, Relids outerrelids)
Definition: createplan.c:4602
bool materialize_inner
Definition: relation.h:1289
void extract_actual_join_clauses(List *restrictinfo_list, List **joinquals, List **otherquals)
Definition: restrictinfo.c:381
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
Path * innerjoinpath
Definition: relation.h:1238
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:724
ParamPathInfo * param_info
Definition: relation.h:901
#define CP_SMALL_TLIST
Definition: createplan.c:67
Definition: nodes.h:518
List * get_actual_clauses(List *restrictinfo_list)
Definition: restrictinfo.c:331
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
EquivalenceClass * right_ec
Definition: relation.h:1709
unsigned int Oid
Definition: postgres_ext.h:31
int pk_strategy
Definition: relation.h:797
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static Material * make_material(Plan *lefttree)
Definition: createplan.c:5833
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
bool pk_nulls_first
Definition: relation.h:798
#define ERROR
Definition: elog.h:43
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
List * joinrestrictinfo
Definition: relation.h:1240
RelOptInfo * parent
Definition: relation.h:898
bool outer_is_left
Definition: relation.h:1715
Datum sort(PG_FUNCTION_ARGS)
Definition: _int_op.c:200
static void copy_plan_costsize(Plan *dest, Plan *src)
Definition: createplan.c:4787
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Relids relids
Definition: relation.h:494
double cpu_operator_cost
Definition: costsize.c:108
#define lnext(lc)
Definition: pg_list.h:105
Path * outerjoinpath
Definition: relation.h:1237
List * pathkeys
Definition: relation.h:913
#define NULL
Definition: c.h:229
Path path
Definition: relation.h:1233
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
EquivalenceClass * pk_eclass
Definition: relation.h:795
static int list_length(const List *l)
Definition: pg_list.h:89
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
List * list_difference(const List *list1, const List *list2)
Definition: list.c:858
List * innersortkeys
Definition: relation.h:1288
Oid pk_opfamily
Definition: relation.h:796
static Sort * make_sort_from_pathkeys(Plan *lefttree, List *pathkeys)
Definition: createplan.c:5710
static MergeJoin * make_mergejoin(List *tlist, List *joinclauses, List *otherclauses, List *mergeclauses, Oid *mergefamilies, Oid *mergecollations, int *mergestrategies, bool *mergenullsfirst, Plan *lefttree, Plan *righttree, JoinType jointype)
Definition: createplan.c:5335
void * palloc(Size size)
Definition: mcxt.c:849
EquivalenceClass * left_ec
Definition: relation.h:1708
Join join
Definition: plannodes.h:681
JoinType jointype
Definition: relation.h:1235
int i
Cost total_cost
Definition: plannodes.h:115
JoinPath jpath
Definition: relation.h:1285
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static void label_sort_with_costsize(PlannerInfo *root, Sort *plan, double limit_tuples)
Definition: createplan.c:4807
Plan plan
Definition: plannodes.h:639
static Result * create_minmaxagg_plan ( PlannerInfo root,
MinMaxAggPath best_path 
)
static

Definition at line 1931 of file createplan.c.

References Assert, build_path_tlist(), copy_generic_path_info(), create_plan(), PlannerInfo::hasInheritedTarget, lfirst, Query::limitCount, Query::limitOffset, make_limit(), make_result(), PlannerInfo::minmax_aggs, MinMaxAggPath::mmaggregates, NIL, NULL, Plan::parallel_aware, MinMaxAggInfo::param, PlannerInfo::parse, MinMaxAggPath::path, MinMaxAggInfo::path, MinMaxAggInfo::pathcost, Path::pathtarget, Result::plan, Plan::plan_rows, Plan::plan_width, MinMaxAggPath::quals, SS_make_initplan_from_plan(), Plan::startup_cost, Path::startup_cost, MinMaxAggInfo::subroot, Plan::total_cost, and PathTarget::width.

Referenced by create_plan_recurse().

1932 {
1933  Result *plan;
1934  List *tlist;
1935  ListCell *lc;
1936 
1937  /* Prepare an InitPlan for each aggregate's subquery. */
1938  foreach(lc, best_path->mmaggregates)
1939  {
1940  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1941  PlannerInfo *subroot = mminfo->subroot;
1942  Query *subparse = subroot->parse;
1943  Plan *plan;
1944 
1945  /*
1946  * Generate the plan for the subquery. We already have a Path, but we
1947  * have to convert it to a Plan and attach a LIMIT node above it.
1948  * Since we are entering a different planner context (subroot),
1949  * recurse to create_plan not create_plan_recurse.
1950  */
1951  plan = create_plan(subroot, mminfo->path);
1952 
1953  plan = (Plan *) make_limit(plan,
1954  subparse->limitOffset,
1955  subparse->limitCount);
1956 
1957  /* Must apply correct cost/width data to Limit node */
1958  plan->startup_cost = mminfo->path->startup_cost;
1959  plan->total_cost = mminfo->pathcost;
1960  plan->plan_rows = 1;
1961  plan->plan_width = mminfo->path->pathtarget->width;
1962  plan->parallel_aware = false;
1963 
1964  /* Convert the plan into an InitPlan in the outer query. */
1965  SS_make_initplan_from_plan(root, subroot, plan, mminfo->param);
1966  }
1967 
1968  /* Generate the output plan --- basically just a Result */
1969  tlist = build_path_tlist(root, &best_path->path);
1970 
1971  plan = make_result(tlist, (Node *) best_path->quals, NULL);
1972 
1973  copy_generic_path_info(&plan->plan, (Path *) best_path);
1974 
1975  /*
1976  * During setrefs.c, we'll need to replace references to the Agg nodes
1977  * with InitPlan output params. (We can't just do that locally in the
1978  * MinMaxAgg node, because path nodes above here may have Agg references
1979  * as well.) Save the mmaggregates list to tell setrefs.c to do that.
1980  *
1981  * This doesn't work if we're in an inheritance subtree (see notes in
1982  * create_modifytable_plan). Fortunately we can't be because there would
1983  * never be aggregates in an UPDATE/DELETE; but let's Assert that.
1984  */
1985  Assert(!root->hasInheritedTarget);
1986  Assert(root->minmax_aggs == NIL);
1987  root->minmax_aggs = best_path->mmaggregates;
1988 
1989  return plan;
1990 }
Node * limitOffset
Definition: parsenodes.h:149
#define NIL
Definition: pg_list.h:69
double plan_rows
Definition: plannodes.h:120
PathTarget * pathtarget
Definition: relation.h:899
Query * parse
Definition: relation.h:154
Param * param
Definition: relation.h:1998
Definition: nodes.h:518
List * minmax_aggs
Definition: relation.h:284
List * quals
Definition: relation.h:1423
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:300
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Path * path
Definition: relation.h:1996
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Cost startup_cost
Definition: relation.h:910
Node * limitCount
Definition: parsenodes.h:150
Cost startup_cost
Definition: plannodes.h:114
bool parallel_aware
Definition: plannodes.h:126
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6246
List * mmaggregates
Definition: relation.h:1422
int plan_width
Definition: plannodes.h:121
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
#define lfirst(lc)
Definition: pg_list.h:106
bool hasInheritedTarget
Definition: relation.h:296
void SS_make_initplan_from_plan(PlannerInfo *root, PlannerInfo *subroot, Plan *plan, Param *prm)
Definition: subselect.c:2899
Limit * make_limit(Plan *lefttree, Node *limitOffset, Node *limitCount)
Definition: createplan.c:6225
int width
Definition: relation.h:831
Cost total_cost
Definition: plannodes.h:115
Definition: pg_list.h:45
Definition: relation.h:892
PlannerInfo * subroot
Definition: relation.h:1995
static ModifyTable * create_modifytable_plan ( PlannerInfo root,
ModifyTablePath best_path 
)
static

Definition at line 2280 of file createplan.c.

References apply_tlist_labeling(), ModifyTablePath::canSetTag, copy_generic_path_info(), CP_EXACT_TLIST, create_plan_recurse(), ModifyTablePath::epqParam, forboth, lappend(), lfirst, make_modifytable(), NIL, ModifyTablePath::nominalRelation, ModifyTablePath::onconflict, ModifyTablePath::operation, ModifyTablePath::partitioned_rels, ModifyTablePath::path, ModifyTable::plan, PlannerInfo::processed_tlist, ModifyTablePath::resultRelations, ModifyTablePath::returningLists, ModifyTablePath::rowMarks, subpath(), ModifyTablePath::subpaths, ModifyTablePath::subroots, Plan::targetlist, and ModifyTablePath::withCheckOptionLists.

Referenced by create_plan_recurse().

2281 {
2282  ModifyTable *plan;
2283  List *subplans = NIL;
2284  ListCell *subpaths,
2285  *subroots;
2286 
2287  /* Build the plan for each input path */
2288  forboth(subpaths, best_path->subpaths,
2289  subroots, best_path->subroots)
2290  {
2291  Path *subpath = (Path *) lfirst(subpaths);
2292  PlannerInfo *subroot = (PlannerInfo *) lfirst(subroots);
2293  Plan *subplan;
2294 
2295  /*
2296  * In an inherited UPDATE/DELETE, reference the per-child modified
2297  * subroot while creating Plans from Paths for the child rel. This is
2298  * a kluge, but otherwise it's too hard to ensure that Plan creation
2299  * functions (particularly in FDWs) don't depend on the contents of
2300  * "root" matching what they saw at Path creation time. The main
2301  * downside is that creation functions for Plans that might appear
2302  * below a ModifyTable cannot expect to modify the contents of "root"
2303  * and have it "stick" for subsequent processing such as setrefs.c.
2304  * That's not great, but it seems better than the alternative.
2305  */
2306  subplan = create_plan_recurse(subroot, subpath, CP_EXACT_TLIST);
2307 
2308  /* Transfer resname/resjunk labeling, too, to keep executor happy */
2309  apply_tlist_labeling(subplan->targetlist, subroot->processed_tlist);
2310 
2311  subplans = lappend(subplans, subplan);
2312  }
2313 
2314  plan = make_modifytable(root,
2315  best_path->operation,
2316  best_path->canSetTag,
2317  best_path->nominalRelation,
2318  best_path->partitioned_rels,
2319  best_path->resultRelations,
2320  subplans,
2321  best_path->withCheckOptionLists,
2322  best_path->returningLists,
2323  best_path->rowMarks,
2324  best_path->onconflict,
2325  best_path->epqParam);
2326 
2327  copy_generic_path_info(&plan->plan, &best_path->path);
2328 
2329  return plan;
2330 }
#define NIL
Definition: pg_list.h:69
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:321
List * returningLists
Definition: relation.h:1499
OnConflictExpr * onconflict
Definition: relation.h:1501
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
Index nominalRelation
Definition: relation.h:1492
List * rowMarks
Definition: relation.h:1500
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
List * subroots
Definition: relation.h:1497
List * subpaths
Definition: relation.h:1496
List * lappend(List *list, void *datum)
Definition: list.c:128
List * partitioned_rels
Definition: relation.h:1494
static ModifyTable * make_modifytable(PlannerInfo *root, CmdType operation, bool canSetTag, Index nominalRelation, List *partitioned_rels, List *resultRelations, List *subplans, List *withCheckOptionLists, List *returningLists, List *rowMarks, OnConflictExpr *onconflict, int epqParam)
Definition: createplan.c:6286
#define lfirst(lc)
Definition: pg_list.h:106
List * targetlist
Definition: plannodes.h:132
List * withCheckOptionLists
Definition: relation.h:1498
CmdType operation
Definition: relation.h:1490
List * resultRelations
Definition: relation.h:1495
List * processed_tlist
Definition: relation.h:280
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
Definition: relation.h:892
Datum subpath(PG_FUNCTION_ARGS)
Definition: ltree_op.c:234
static NestLoop * create_nestloop_plan ( PlannerInfo root,
NestPath best_path 
)
static

Definition at line 3558 of file createplan.c.

References bms_free(), bms_is_member(), bms_is_subset(), bms_overlap(), bms_union(), build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), PlannerInfo::curOuterParams, PlannerInfo::curOuterRels, extract_actual_clauses(), extract_actual_join_clauses(), find_placeholder_info(), JoinPath::innerjoinpath, IS_OUTER_JOIN, IsA, NestLoop::join, JoinPath::joinrestrictinfo, JoinPath::jointype, lappend(), lfirst, list_delete_cell(), list_head(), lnext, make_nestloop(), next, NIL, NULL, order_qual_clauses(), JoinPath::outerjoinpath, Path::param_info, NestLoopParam::paramval, Path::parent, JoinPath::path, PlaceHolderInfo::ph_eval_at, Join::plan, RelOptInfo::relids, replace_nestloop_params(), and Var::varno.

Referenced by create_join_plan().

3560 {
3561  NestLoop *join_plan;
3562  Plan *outer_plan;
3563  Plan *inner_plan;
3564  List *tlist = build_path_tlist(root, &best_path->path);
3565  List *joinrestrictclauses = best_path->joinrestrictinfo;
3566  List *joinclauses;
3567  List *otherclauses;
3568  Relids outerrelids;
3569  List *nestParams;
3570  Relids saveOuterRels = root->curOuterRels;
3571  ListCell *cell;
3572  ListCell *prev;
3573  ListCell *next;
3574 
3575  /* NestLoop can project, so no need to be picky about child tlists */
3576  outer_plan = create_plan_recurse(root, best_path->outerjoinpath, 0);
3577 
3578  /* For a nestloop, include outer relids in curOuterRels for inner side */
3579  root->curOuterRels = bms_union(root->curOuterRels,
3580  best_path->outerjoinpath->parent->relids);
3581 
3582  inner_plan = create_plan_recurse(root, best_path->innerjoinpath, 0);
3583 
3584  /* Restore curOuterRels */
3585  bms_free(root->curOuterRels);
3586  root->curOuterRels = saveOuterRels;
3587 
3588  /* Sort join qual clauses into best execution order */
3589  joinrestrictclauses = order_qual_clauses(root, joinrestrictclauses);
3590 
3591  /* Get the join qual clauses (in plain expression form) */
3592  /* Any pseudoconstant clauses are ignored here */
3593  if (IS_OUTER_JOIN(best_path->jointype))
3594  {
3595  extract_actual_join_clauses(joinrestrictclauses,
3596  &joinclauses, &otherclauses);
3597  }
3598  else
3599  {
3600  /* We can treat all clauses alike for an inner join */
3601  joinclauses = extract_actual_clauses(joinrestrictclauses, false);
3602  otherclauses = NIL;
3603  }
3604 
3605  /* Replace any outer-relation variables with nestloop params */
3606  if (best_path->path.param_info)
3607  {
3608  joinclauses = (List *)
3609  replace_nestloop_params(root, (Node *) joinclauses);
3610  otherclauses = (List *)
3611  replace_nestloop_params(root, (Node *) otherclauses);
3612  }
3613 
3614  /*
3615  * Identify any nestloop parameters that should be supplied by this join
3616  * node, and move them from root->curOuterParams to the nestParams list.
3617  */
3618  outerrelids = best_path->outerjoinpath->parent->relids;
3619  nestParams = NIL;
3620  prev = NULL;
3621  for (cell = list_head(root->curOuterParams); cell; cell = next)
3622  {
3623  NestLoopParam *nlp = (NestLoopParam *) lfirst(cell);
3624 
3625  next = lnext(cell);
3626  if (IsA(nlp->paramval, Var) &&
3627  bms_is_member(nlp->paramval->varno, outerrelids))
3628  {
3630  cell, prev);
3631  nestParams = lappend(nestParams, nlp);
3632  }
3633  else if (IsA(nlp->paramval, PlaceHolderVar) &&
3634  bms_overlap(((PlaceHolderVar *) nlp->paramval)->phrels,
3635  outerrelids) &&
3637  (PlaceHolderVar *) nlp->paramval,
3638  false)->ph_eval_at,
3639  outerrelids))
3640  {
3642  cell, prev);
3643  nestParams = lappend(nestParams, nlp);
3644  }
3645  else
3646  prev = cell;
3647  }
3648 
3649  join_plan = make_nestloop(tlist,
3650  joinclauses,
3651  otherclauses,
3652  nestParams,
3653  outer_plan,
3654  inner_plan,
3655  best_path->jointype);
3656 
3657  copy_generic_path_info(&join_plan->join.plan, &best_path->path);
3658 
3659  return join_plan;
3660 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
Relids ph_eval_at
Definition: relation.h:1977
static int32 next
Definition: blutils.c:210
void extract_actual_join_clauses(List *restrictinfo_list, List **joinquals, List **otherquals)
Definition: restrictinfo.c:381
Relids curOuterRels
Definition: relation.h:311
Path * innerjoinpath
Definition: relation.h:1238
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:724
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
Definition: primnodes.h:163
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Var * paramval
Definition: plannodes.h:665
Join join
Definition: plannodes.h:657
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
List * joinrestrictinfo
Definition: relation.h:1240
RelOptInfo * parent
Definition: relation.h:898
bool bms_is_subset(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:307
List * curOuterParams
Definition: relation.h:312
PlaceHolderInfo * find_placeholder_info(PlannerInfo *root, PlaceHolderVar *phv, bool create_new_ph)
Definition: placeholder.c:69
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
Relids relids
Definition: relation.h:494
#define lnext(lc)
Definition: pg_list.h:105
List * lappend(List *list, void *datum)
Definition: list.c:128
static NestLoop * make_nestloop(List *tlist, List *joinclauses, List *otherclauses, List *nestParams, Plan *lefttree, Plan *righttree, JoinType jointype)
Definition: createplan.c:5264
Index varno
Definition: primnodes.h:166
List * list_delete_cell(List *list, ListCell *cell, ListCell *prev)
Definition: list.c:528
Path * outerjoinpath
Definition: relation.h:1237
void bms_free(Bitmapset *a)
Definition: bitmapset.c:200
#define NULL
Definition: c.h:229
Path path
Definition: relation.h:1233
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_union(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:217
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:442
JoinType jointype
Definition: relation.h:1235
Definition: pg_list.h:45
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:419
Plan plan
Definition: plannodes.h:639
Plan* create_plan ( PlannerInfo root,
Path best_path 
)

Definition at line 300 of file createplan.c.

References apply_tlist_labeling(), Assert, CP_EXACT_TLIST, create_plan_recurse(), PlannerInfo::curOuterParams, PlannerInfo::curOuterRels, elog, ERROR, IsA, NIL, NULL, PlannerInfo::plan_params, PlannerInfo::processed_tlist, SS_attach_initplans(), and Plan::targetlist.

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

301 {
302  Plan *plan;
303 
304  /* plan_params should not be in use in current query level */
305  Assert(root->plan_params == NIL);
306 
307  /* Initialize this module's private workspace in PlannerInfo */
308  root->curOuterRels = NULL;
309  root->curOuterParams = NIL;
310 
311  /* Recursively process the path tree, demanding the correct tlist result */
312  plan = create_plan_recurse(root, best_path, CP_EXACT_TLIST);
313 
314  /*
315  * Make sure the topmost plan node's targetlist exposes the original
316  * column names and other decorative info. Targetlists generated within
317  * the planner don't bother with that stuff, but we must have it on the
318  * top-level tlist seen at execution time. However, ModifyTable plan
319  * nodes don't have a tlist matching the querytree targetlist.
320  */
321  if (!IsA(plan, ModifyTable))
323 
324  /*
325  * Attach any initPlans created in this query level to the topmost plan
326  * node. (In principle the initplans could go in any plan node at or
327  * above where they're referenced, but there seems no reason to put them
328  * any lower than the topmost node for the query level. Also, see
329  * comments for SS_finalize_plan before you try to change this.)
330  */
331  SS_attach_initplans(root, plan);
332 
333  /* Check we successfully assigned all NestLoopParams to plan nodes */
334  if (root->curOuterParams != NIL)
335  elog(ERROR, "failed to assign all NestLoopParams to plan nodes");
336 
337  /*
338  * Reset plan_params to ensure param IDs used for nestloop params are not
339  * re-used later
340  */
341  root->plan_params = NIL;
342 
343  return plan;
344 }
#define NIL
Definition: pg_list.h:69
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:321
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
List * plan_params
Definition: relation.h:168
Relids curOuterRels
Definition: relation.h:311
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
#define ERROR
Definition: elog.h:43
List * curOuterParams
Definition: relation.h:312
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void SS_attach_initplans(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2203
List * targetlist
Definition: plannodes.h:132
#define elog
Definition: elog.h:219
List * processed_tlist
Definition: relation.h:280
#define CP_EXACT_TLIST
Definition: createplan.c:66
static Plan * create_plan_recurse ( PlannerInfo root,
Path best_path,
int  flags 
)
static

Definition at line 351 of file createplan.c.

References Assert, create_agg_plan(), create_append_plan(), create_gather_merge_plan(), create_gather_plan(), create_group_plan(), create_groupingsets_plan(), create_join_plan(), create_limit_plan(), create_lockrows_plan(), create_material_plan(), create_merge_append_plan(), create_minmaxagg_plan(), create_modifytable_plan(), create_project_set_plan(), create_projection_plan(), create_recursiveunion_plan(), create_result_plan(), create_scan_plan(), create_setop_plan(), create_sort_plan(), create_unique_plan(), create_upper_unique_plan(), create_windowagg_plan(), elog, ERROR, IsA, NULL, Path::pathtype, T_Agg, T_Append, T_BitmapHeapScan, T_CteScan, T_CustomScan, T_ForeignScan, T_FunctionScan, T_Gather, T_GatherMerge, T_Group, T_HashJoin, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_MergeJoin, T_ModifyTable, T_NestLoop, T_ProjectSet, T_RecursiveUnion, T_Result, T_SampleScan, T_SeqScan, T_SetOp, T_Sort, T_SubqueryScan, T_TableFuncScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, and T_WorkTableScan.

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_limit_plan(), create_lockrows_plan(), create_material_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().

352 {
353  Plan *plan;
354 
355  switch (best_path->pathtype)
356  {
357  case T_SeqScan:
358  case T_SampleScan:
359  case T_IndexScan:
360  case T_IndexOnlyScan:
361  case T_BitmapHeapScan:
362  case T_TidScan:
363  case T_SubqueryScan:
364  case T_FunctionScan:
365  case T_TableFuncScan:
366  case T_ValuesScan:
367  case T_CteScan:
368  case T_WorkTableScan:
369  case T_ForeignScan:
370  case T_CustomScan:
371  plan = create_scan_plan(root, best_path, flags);
372  break;
373  case T_HashJoin:
374  case T_MergeJoin:
375  case T_NestLoop:
376  plan = create_join_plan(root,
377  (JoinPath *) best_path);
378  break;
379  case T_Append:
380  plan = create_append_plan(root,
381  (AppendPath *) best_path);
382  break;
383  case T_MergeAppend:
384  plan = create_merge_append_plan(root,
385  (MergeAppendPath *) best_path);
386  break;
387  case T_Result:
388  if (IsA(best_path, ProjectionPath))
389  {
390  plan = create_projection_plan(root,
391  (ProjectionPath *) best_path);
392  }
393  else if (IsA(best_path, MinMaxAggPath))
394  {
395  plan = (Plan *) create_minmaxagg_plan(root,
396  (MinMaxAggPath *) best_path);
397  }
398  else
399  {
400  Assert(IsA(best_path, ResultPath));
401  plan = (Plan *) create_result_plan(root,
402  (ResultPath *) best_path);
403  }
404  break;
405  case T_ProjectSet:
406  plan = (Plan *) create_project_set_plan(root,
407  (ProjectSetPath *) best_path);
408  break;
409  case T_Material:
410  plan = (Plan *) create_material_plan(root,
411  (MaterialPath *) best_path,
412  flags);
413  break;
414  case T_Unique:
415  if (IsA(best_path, UpperUniquePath))
416  {
417  plan = (Plan *) create_upper_unique_plan(root,
418  (UpperUniquePath *) best_path,
419  flags);
420  }
421  else
422  {
423  Assert(IsA(best_path, UniquePath));
424  plan = create_unique_plan(root,
425  (UniquePath *) best_path,
426  flags);
427  }
428  break;
429  case T_Gather:
430  plan = (Plan *) create_gather_plan(root,
431  (GatherPath *) best_path);
432  break;
433  case T_Sort:
434  plan = (Plan *) create_sort_plan(root,
435  (SortPath *) best_path,
436  flags);
437  break;
438  case T_Group:
439  plan = (Plan *) create_group_plan(root,
440  (GroupPath *) best_path);
441  break;
442  case T_Agg:
443  if (IsA(best_path, GroupingSetsPath))
444  plan = create_groupingsets_plan(root,
445  (GroupingSetsPath *) best_path);
446  else
447  {
448  Assert(IsA(best_path, AggPath));
449  plan = (Plan *) create_agg_plan(root,
450  (AggPath *) best_path);
451  }
452  break;
453  case T_WindowAgg:
454  plan = (Plan *) create_windowagg_plan(root,
455  (WindowAggPath *) best_path);
456  break;
457  case T_SetOp:
458  plan = (Plan *) create_setop_plan(root,
459  (SetOpPath *) best_path,
460  flags);
461  break;
462  case T_RecursiveUnion:
463  plan = (Plan *) create_recursiveunion_plan(root,
464  (RecursiveUnionPath *) best_path);
465  break;
466  case T_LockRows:
467  plan = (Plan *) create_lockrows_plan(root,
468  (LockRowsPath *) best_path,
469  flags);
470  break;
471  case T_ModifyTable:
472  plan = (Plan *) create_modifytable_plan(root,
473  (ModifyTablePath *) best_path);
474  break;
475  case T_Limit:
476  plan = (Plan *) create_limit_plan(root,
477  (LimitPath *) best_path,
478  flags);
479  break;
480  case T_GatherMerge:
481  plan = (Plan *) create_gather_merge_plan(root,
482  (GatherMergePath *) best_path);
483  break;
484  default:
485  elog(ERROR, "unrecognized node type: %d",
486  (int) best_path->pathtype);
487  plan = NULL; /* keep compiler quiet */
488  break;
489  }
490 
491  return plan;
492 }
static Plan * create_unique_plan(PlannerInfo *root, UniquePath *best_path, int flags)
Definition: createplan.c:1231
static Result * create_minmaxagg_plan(PlannerInfo *root, MinMaxAggPath *best_path)
Definition: createplan.c:1931
static Result * create_result_plan(PlannerInfo *root, ResultPath *best_path)
Definition: createplan.c:1152
Definition: nodes.h:76
static Group * create_group_plan(PlannerInfo *root, GroupPath *best_path)
Definition: createplan.c:1636
#define IsA(nodeptr, _type_)
Definition: nodes.h:569
Definition: nodes.h:78
static Sort * create_sort_plan(PlannerInfo *root, SortPath *best_path, int flags)
Definition: createplan.c:1609
static Plan * create_scan_plan(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:499
static LockRows * create_lockrows_plan(PlannerInfo *root, LockRowsPath *best_path, int flags)
Definition: createplan.c:2257
static ProjectSet * create_project_set_plan(PlannerInfo *root, ProjectSetPath *best_path)
Definition: createplan.c:1177
static RecursiveUnion * create_recursiveunion_plan(PlannerInfo *root, RecursiveUnionPath *best_path)
Definition: createplan.c:2221
static Agg * create_agg_plan(PlannerInfo *root, AggPath *best_path)
Definition: createplan.c:1701
static Unique * create_upper_unique_plan(PlannerInfo *root, UpperUniquePath *best_path, int flags)
Definition: createplan.c:1673
Definition: nodes.h:48
Definition: nodes.h:74
static ModifyTable * create_modifytable_plan(PlannerInfo *root, ModifyTablePath *best_path)
Definition: createplan.c:2280
NodeTag pathtype
Definition: relation.h:896
Definition: nodes.h:45
#define ERROR
Definition: elog.h:43
static Plan * create_projection_plan(PlannerInfo *root, ProjectionPath *best_path)
Definition: createplan.c:1524
Definition: nodes.h:75
static Plan * create_join_plan(PlannerInfo *root, JoinPath *best_path)
Definition: createplan.c:919
static GatherMerge * create_gather_merge_plan(PlannerInfo *root, GatherMergePath *best_path)
Definition: createplan.c:1468
static SetOp * create_setop_plan(PlannerInfo *root, SetOpPath *best_path, int flags)
Definition: createplan.c:2185
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static Gather * create_gather_plan(PlannerInfo *root, GatherPath *best_path)
Definition: createplan.c:1433
static Plan * create_append_plan(PlannerInfo *root, AppendPath *best_path)
Definition: createplan.c:979
static WindowAgg * create_windowagg_plan(PlannerInfo *root, WindowAggPath *best_path)
Definition: createplan.c:1999
static Material * create_material_plan(PlannerInfo *root, MaterialPath *best_path, int flags)
Definition: createplan.c:1203
Definition: nodes.h:82
Definition: nodes.h:79
static Plan * create_groupingsets_plan(PlannerInfo *root, GroupingSetsPath *best_path)
Definition: createplan.c:1782
static Limit * create_limit_plan(PlannerInfo *root, LimitPath *best_path, int flags)
Definition: createplan.c:2339
#define elog
Definition: elog.h:219
static Plan * create_merge_append_plan(PlannerInfo *root, MergeAppendPath *best_path)
Definition: createplan.c:1044
Definition: nodes.h:84
static ProjectSet * create_project_set_plan ( PlannerInfo root,
ProjectSetPath best_path 
)
static

Definition at line 1177 of file createplan.c.

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

Referenced by create_plan_recurse().

1178 {
1179  ProjectSet *plan;
1180  Plan *subplan;
1181  List *tlist;
1182 
1183  /* Since we intend to project, we don't need to constrain child tlist */
1184  subplan = create_plan_recurse(root, best_path->subpath, 0);
1185 
1186  tlist = build_path_tlist(root, &best_path->path);
1187 
1188  plan = make_project_set(tlist, subplan);
1189 
1190  copy_generic_path_info(&plan->plan, (Path *) best_path);
1191 
1192  return plan;
1193 }
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static ProjectSet * make_project_set(List *tlist, Plan *subplan)
Definition: createplan.c:6267
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Path * subpath
Definition: relation.h:1337
Definition: pg_list.h:45
Definition: relation.h:892
Plan plan
Definition: plannodes.h:190
static Plan * create_projection_plan ( PlannerInfo root,
ProjectionPath best_path 
)
static

Definition at line 1524 of file createplan.c.

References build_path_tlist(), copy_generic_path_info(), create_plan_recurse(), is_projection_capable_path(), make_result(), NULL, ProjectionPath::path, Path::pathtarget, Plan::plan_rows, Plan::plan_width, Path::rows, Plan::startup_cost, Path::startup_cost, ProjectionPath::subpath, Plan::targetlist, tlist_same_exprs(), Plan::total_cost, Path::total_cost, and PathTarget::width.

Referenced by create_plan_recurse().

1525 {
1526  Plan *plan;
1527  Plan *subplan;
1528  List *tlist;
1529 
1530  /* Since we intend to project, we don't need to constrain child tlist */
1531  subplan = create_plan_recurse(root, best_path->subpath, 0);
1532 
1533  tlist = build_path_tlist(root, &best_path->path);
1534 
1535  /*
1536  * We might not really need a Result node here, either because the subplan
1537  * can project or because it's returning the right list of expressions
1538  * anyway. Usually create_projection_path will have detected that and set
1539  * dummypp if we don't need a Result; but its decision can't be final,
1540  * because some createplan.c routines change the tlists of their nodes.
1541  * (An example is that create_merge_append_plan might add resjunk sort
1542  * columns to a MergeAppend.) So we have to recheck here. If we do
1543  * arrive at a different answer than create_projection_path did, we'll
1544  * have made slightly wrong cost estimates; but label the plan with the
1545  * cost estimates we actually used, not "corrected" ones. (XXX this could
1546  * be cleaned up if we moved more of the sortcolumn setup logic into Path
1547  * creation, but that would add expense to creating Paths we might end up
1548  * not using.)
1549  */
1550  if (is_projection_capable_path(best_path->subpath) ||
1551  tlist_same_exprs(tlist, subplan->targetlist))
1552  {
1553  /* Don't need a separate Result, just assign tlist to subplan */
1554  plan = subplan;
1555  plan->targetlist = tlist;
1556 
1557  /* Label plan with the estimated costs we actually used */
1558  plan->startup_cost = best_path->path.startup_cost;
1559  plan->total_cost = best_path->path.total_cost;
1560  plan->plan_rows = best_path->path.rows;
1561  plan->plan_width = best_path->path.pathtarget->width;
1562  /* ... but be careful not to munge subplan's parallel-aware flag */
1563  }
1564  else
1565  {
1566  /* We need a Result node */
1567  plan = (Plan *) make_result(tlist, NULL, subplan);
1568 
1569  copy_generic_path_info(plan, (Path *) best_path);
1570  }
1571 
1572  return plan;
1573 }
double plan_rows
Definition: plannodes.h:120
PathTarget * pathtarget
Definition: relation.h:899
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
Cost startup_cost
Definition: relation.h:910
Cost startup_cost
Definition: plannodes.h:114
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6246
Cost total_cost
Definition: relation.h:911
int plan_width
Definition: plannodes.h:121
#define NULL
Definition: c.h:229
double rows
Definition: relation.h:909
bool tlist_same_exprs(List *tlist1, List *tlist2)
Definition: tlist.c:221
List * targetlist
Definition: plannodes.h:132
int width
Definition: relation.h:831
bool is_projection_capable_path(Path *path)
Definition: createplan.c:6423
Cost total_cost
Definition: plannodes.h:115
Path * subpath
Definition: relation.h:1325
Definition: pg_list.h:45
Definition: relation.h:892
static RecursiveUnion * create_recursiveunion_plan ( PlannerInfo root,
RecursiveUnionPath best_path 
)
static

Definition at line 2221 of file createplan.c.

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

Referenced by create_plan_recurse().

2222 {
2223  RecursiveUnion *plan;
2224  Plan *leftplan;
2225  Plan *rightplan;
2226  List *tlist;
2227  long numGroups;
2228 
2229  /* Need both children to produce same tlist, so force it */
2230  leftplan = create_plan_recurse(root, best_path->leftpath, CP_EXACT_TLIST);
2231  rightplan = create_plan_recurse(root, best_path->rightpath, CP_EXACT_TLIST);
2232 
2233  tlist = build_path_tlist(root, &best_path->path);
2234 
2235  /* Convert numGroups to long int --- but 'ware overflow! */
2236  numGroups = (long) Min(best_path->numGroups, (double) LONG_MAX);
2237 
2238  plan = make_recursive_union(tlist,
2239  leftplan,
2240  rightplan,
2241  best_path->wtParam,
2242  best_path->distinctList,
2243  numGroups);
2244 
2245  copy_generic_path_info(&plan->plan, (Path *) best_path);
2246 
2247  return plan;
2248 }
static RecursiveUnion * make_recursive_union(List *tlist, Plan *lefttree, Plan *righttree, int wtParam, List *distinctList, long numGroups)
Definition: createplan.c:5182
#define Min(x, y)
Definition: c.h:806
static Plan * create_plan_recurse(PlannerInfo *root, Path *best_path, int flags)
Definition: createplan.c:351
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
#define CP_EXACT_TLIST
Definition: createplan.c:66
Definition: pg_list.h:45
Definition: relation.h:892
static Result * create_result_plan ( PlannerInfo root,
ResultPath best_path 
)
static

Definition at line 1152 of file createplan.c.

References build_path_tlist(), copy_generic_path_info(), make_result(), NULL, order_qual_clauses(), ResultPath::path, Result::plan, and ResultPath::quals.

Referenced by create_plan_recurse().

1153 {
1154  Result *plan;
1155  List *tlist;
1156  List *quals;
1157 
1158  tlist = build_path_tlist(root, &best_path->path);
1159 
1160  /* best_path->quals is just bare clauses */
1161  quals = order_qual_clauses(root, best_path->quals);
1162 
1163  plan = make_result(tlist, (Node *) quals, NULL);
1164 
1165  copy_generic_path_info(&plan->plan, (Path *) best_path);
1166 
1167  return plan;
1168 }
Plan plan
Definition: plannodes.h:178
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
Path path
Definition: relation.h:1158
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
static Result * make_result(List *tlist, Node *resconstantqual, Plan *subplan)
Definition: createplan.c:6246
#define NULL
Definition: c.h:229
List * quals
Definition: relation.h:1159
Definition: pg_list.h:45
Definition: relation.h:892
static SampleScan * create_samplescan_plan ( PlannerInfo root,
Path best_path,
List tlist,
List scan_clauses 
)
static

Definition at line 2408 of file createplan.c.

References Assert, copy_generic_path_info(), extract_actual_clauses(), make_samplescan(), NULL, order_qual_clauses(), Path::param_info, Path::parent, Scan::plan, planner_rt_fetch, RelOptInfo::relid, replace_nestloop_params(), RTE_RELATION, RangeTblEntry::rtekind, SampleScan::scan, and RangeTblEntry::tablesample.

Referenced by create_scan_plan().

2410 {
2411  SampleScan *scan_plan;
2412  Index scan_relid = best_path->parent->relid;
2413  RangeTblEntry *rte;
2414  TableSampleClause *tsc;
2415 
2416  /* it should be a base rel with a tablesample clause... */
2417  Assert(scan_relid > 0);
2418  rte = planner_rt_fetch(scan_relid, root);
2419  Assert(rte->rtekind == RTE_RELATION);
2420  tsc = rte->tablesample;
2421  Assert(tsc != NULL);
2422 
2423  /* Sort clauses into best execution order */
2424  scan_clauses = order_qual_clauses(root, scan_clauses);
2425 
2426  /* Reduce RestrictInfo list to bare expressions; ignore pseudoconstants */
2427  scan_clauses = extract_actual_clauses(scan_clauses, false);
2428 
2429  /* Replace any outer-relation variables with nestloop params */
2430  if (best_path->param_info)
2431  {
2432  scan_clauses = (List *)
2433  replace_nestloop_params(root, (Node *) scan_clauses);
2434  tsc = (TableSampleClause *)
2435  replace_nestloop_params(root, (Node *) tsc);
2436  }
2437 
2438  scan_plan = make_samplescan(tlist,
2439  scan_clauses,
2440  scan_relid,
2441  tsc);
2442 
2443  copy_generic_path_info(&scan_plan->scan.plan, best_path);
2444 
2445  return scan_plan;
2446 }
Plan plan
Definition: plannodes.h:315
static Node * replace_nestloop_params(PlannerInfo *root, Node *expr)
Definition: createplan.c:4121
ParamPathInfo * param_info
Definition: relation.h:901
Definition: nodes.h:518
static List * order_qual_clauses(PlannerInfo *root, List *clauses)
Definition: createplan.c:4679
static void copy_generic_path_info(Plan *dest, Path *src)
Definition: createplan.c:4773
#define planner_rt_fetch(rti, root)
Definition: relation.h:324
Scan scan
Definition: plannodes.h:331
RelOptInfo * parent
Definition: relation.h:898
Index relid
Definition: relation.h:522
static SampleScan * make_samplescan(List *qptlist, List *qpqual, Index scanrelid, TableSampleClause *tsc)
Definition: createplan.c:4877
unsigned int Index
Definition: c.h:365
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
List * extract_actual_clauses(List *restrictinfo_list, bool pseudoconstant)
Definition: restrictinfo.c:354
RTEKind rtekind
Definition: parsenodes.h:916
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:929
static Plan * create_scan_plan ( PlannerInfo root,
Path best_path,
int  flags 
)
static

Definition at line 499 of file createplan.c.

References apply_pathtarget_labeling_to_tlist(), RelOptInfo::baserestrictinfo, build_path_tlist(), build_physical_tlist(), castNode, copyObject(), create_bitmap_scan_plan(), create_ctescan_plan(), create_customscan_plan(), create_foreignscan_plan(), create_functionscan_plan(), create_gating_plan(), create_indexscan_plan(), create_samplescan_plan(), create_seqscan_plan(), create_subqueryscan_plan(), create_tablefuncscan_plan(), create_tidscan_plan(), create_valuesscan_plan(), create_worktablescan_plan(), elog, ERROR, get_gating_quals(), list_concat(), list_copy(), NIL, NULL, Path::param_info, Path::parent, Path::pathtarget, Path::pathtype, ParamPathInfo::ppi_clauses, T_BitmapHeapScan, T_CteScan, T_CustomScan, T_ForeignScan, T_FunctionScan, T_IndexOnlyScan, T_IndexScan, T_SampleScan, T_SeqScan, T_SubqueryScan, T_TableFuncScan, T_TidScan, T_ValuesScan, T_WorkTableScan, and use_physical_tlist().

Referenced by create_plan_recurse().

500 {
501  RelOptInfo *rel = best_path->parent;
502  List *scan_clauses;
503  List *gating_clauses;
504  List *tlist;
505  Plan *plan;
506 
507  /*
508  * Extract the relevant restriction clauses from the parent relation. The
509  * executor must apply all these restrictions during the scan, except for
510  * pseudoconstants which we'll take care of below.
511  *
512  * If this is a plain indexscan or index-only scan, we need not consider
513  * restriction clauses that are implied by the index's predicate, so use
514  * indrestrictinfo not baserestrictinfo. Note that we can't do that for
515  * bitmap indexscans, since there's not necessarily a single index
516  * involved; but it doesn't matter since create_bitmap_scan_plan() will be
517  * able to get rid of such clauses anyway via predicate proof.
518  */
519  switch (best_path->pathtype)
520  {
521  case T_IndexScan:
522  case T_IndexOnlyScan:
523  scan_clauses = castNode(IndexPath, best_path)->indexinfo->indrestrictinfo;
524  break;
525  default:
526  scan_clauses = rel->baserestrictinfo;
527  break;
528  }
529 
530  /*
531  * If this is a parameterized scan, we also need to enforce all the join
532  * clauses available from the outer relation(s).
533  *
534  * For paranoia's sake, don't modify the stored baserestrictinfo list.
535  */
536  if (best_path->param_info)
537  scan_clauses = list_concat(list_copy(scan_clauses),
538  best_path->param_info->ppi_clauses);
539 
540  /*
541  * Detect whether we have any pseudoconstant quals to deal with. Then, if
542  * we'll need a gating Result node, it will be able to project, so there
543  * are no requirements on the child's tlist.
544  */
545  gating_clauses = get_gating_quals(root, scan_clauses);
546  if (gating_clauses)
547  flags = 0;
548 
549  /*
550  * For table scans, rather than using the relation targetlist (which is
551  * only those Vars actually needed by the query), we prefer to generate a
552  * tlist containing all Vars in order. This will allow the executor to
553  * optimize away projection of the table tuples, if possible.
554  */
555  if (use_physical_tlist(root, best_path, flags))
556  {
557  if (best_path->pathtype == T_IndexOnlyScan)
558  {
559  /* For index-only scan, the preferred tlist is the index's */
560  tlist = copyObject(((IndexPath *) best_path)->indexinfo->indextlist);
561 
562  /*
563  * Transfer any sortgroupref data to the replacement tlist, unless
564  * we don't care because the gating Result will handle it.
565  */
566  if (!gating_clauses)
568  }
569  else
570  {
571  tlist = build_physical_tlist(root, rel);
572  if (tlist == NIL)
573  {
574  /* Failed because of dropped cols, so use regular method */
575  tlist = build_path_tlist(root, best_path);
576  }
577  else
578  {
579  /* As above, transfer sortgroupref data to replacement tlist */
580  if (!gating_clauses)
582  }
583  }
584  }
585  else
586  {
587  tlist = build_path_tlist(root, best_path);
588  }
589 
590  switch (best_path->pathtype)
591  {
592  case T_SeqScan:
593  plan = (Plan *) create_seqscan_plan(root,
594  best_path,
595  tlist,
596  scan_clauses);
597  break;
598 
599  case T_SampleScan:
600  plan = (Plan *) create_samplescan_plan(root,
601  best_path,
602  tlist,
603  scan_clauses);
604  break;
605 
606  case T_IndexScan:
607  plan = (Plan *) create_indexscan_plan(root,
608  (IndexPath *) best_path,
609  tlist,
610  scan_clauses,
611  false);
612  break;
613 
614  case T_IndexOnlyScan:
615  plan = (Plan *) create_indexscan_plan(root,
616  (IndexPath *) best_path,
617  tlist,
618  scan_clauses,
619  true);
620  break;
621 
622  case T_BitmapHeapScan:
623  plan = (Plan *) create_bitmap_scan_plan(root,
624  (BitmapHeapPath *) best_path,
625  tlist,
626  scan_clauses);
627  break;
628 
629  case T_TidScan:
630  plan = (Plan *) create_tidscan_plan(root,
631  (TidPath *) best_path,
632  tlist,
633  scan_clauses);
634  break;
635 
636  case T_SubqueryScan:
637  plan = (Plan *) create_subqueryscan_plan(root,
638  (SubqueryScanPath *) best_path,
639  tlist,
640  scan_clauses);
641  break;
642 
643  case T_FunctionScan:
644  plan = (Plan *) create_functionscan_plan(root,
645  best_path,
646  tlist,
647  scan_clauses);
648  break;
649 
650  case T_TableFuncScan:
651  plan = (Plan *) create_tablefuncscan_plan(root,
652  best_path,
653  tlist,
654  scan_clauses);
655  break;
656 
657  case T_ValuesScan:
658  plan = (Plan *) create_valuesscan_plan(root,
659  best_path,
660  tlist,
661  scan_clauses);
662  break;
663 
664  case T_CteScan:
665  plan = (Plan *) create_ctescan_plan(root,
666  best_path,
667  tlist,
668  scan_clauses);
669  break;
670 
671  case T_WorkTableScan:
672  plan = (Plan *) create_worktablescan_plan(root,
673  best_path,
674  tlist,
675  scan_clauses);
676  break;
677 
678  case T_ForeignScan:
679  plan = (Plan *) create_foreignscan_plan(root,
680  (ForeignPath *) best_path,
681  tlist,
682  scan_clauses);
683  break;
684 
685  case T_CustomScan:
686  plan = (Plan *) create_customscan_plan(root,
687  (CustomPath *) best_path,
688  tlist,
689  scan_clauses);
690  break;
691 
692  default:
693  elog(ERROR, "unrecognized node type: %d",
694  (int) best_path->pathtype);
695  plan = NULL; /* keep compiler quiet */
696  break;
697  }
698 
699  /*
700  * If there are any pseudoconstant clauses attached to this node, insert a
701  * gating Result node that evaluates the pseudoconstants as one-time
702  * quals.
703  */
704  if (gating_clauses)
705  plan = create_gating_plan(root, best_path, plan, gating_clauses);
706 
707  return plan;
708 }
#define NIL
Definition: pg_list.h:69
static BitmapHeapScan * create_bitmap_scan_plan(PlannerInfo *root, BitmapHeapPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2634
static ForeignScan * create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3343
PathTarget * pathtarget
Definition: relation.h:899
static CustomScan * create_customscan_plan(PlannerInfo *root, CustomPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3487
#define castNode(_type_, nodeptr)
Definition: nodes.h:587
List * baserestrictinfo
Definition: relation.h:548
ParamPathInfo * param_info
Definition: relation.h:901
static TableFuncScan * create_tablefuncscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3103
List * list_copy(const List *oldlist)
Definition: list.c:1160
List * list_concat(List *list1, List *list2)
Definition: list.c:321
void * copyObject(const void *from)
Definition: copyfuncs.c:4592
NodeTag pathtype
Definition: relation.h:896
#define ERROR
Definition: elog.h:43
static List * build_path_tlist(PlannerInfo *root, Path *path)
Definition: createplan.c:717
RelOptInfo * parent
Definition: relation.h:898
static SeqScan * create_seqscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2370
static SubqueryScan * create_subqueryscan_plan(PlannerInfo *root, SubqueryScanPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3010
static CteScan * create_ctescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3190
List * build_physical_tlist(PlannerInfo *root, RelOptInfo *rel)
Definition: plancat.c:1389
void apply_pathtarget_labeling_to_tlist(List *tlist, PathTarget *target)
Definition: tlist.c:736
static TidScan * create_tidscan_plan(PlannerInfo *root, TidPath *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2958
#define NULL
Definition: c.h:229
List * ppi_clauses
Definition: relation.h:859
static SampleScan * create_samplescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:2408
static FunctionScan * create_functionscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3060
static Plan * create_gating_plan(PlannerInfo *root, Path *path, Plan *plan, List *gating_quals)
Definition: createplan.c:880
static bool use_physical_tlist(PlannerInfo *root, Path *path, int flags)
Definition: createplan.c:757
#define elog
Definition: elog.h:219
static WorkTableScan * create_worktablescan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: createplan.c:3283
Definition: pg_list.h:45
static ValuesScan * create_valuesscan_plan(PlannerInfo *root, Path *best_path, List *tlist, List *scan_clauses)
Definition: