PostgreSQL Source Code  git master
planner.h File Reference
#include "nodes/plannodes.h"
#include "nodes/relation.h"
Include dependency graph for planner.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Typedefs

typedef PlannedStmt *(* planner_hook_type) (Query *parse, int cursorOptions, ParamListInfo boundParams)
 
typedef void(* create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)
 

Functions

PlannedStmtplanner (Query *parse, int cursorOptions, ParamListInfo boundParams)
 
PlannedStmtstandard_planner (Query *parse, int cursorOptions, ParamListInfo boundParams)
 
PlannerInfosubquery_planner (PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
 
bool is_dummy_plan (Plan *plan)
 
RowMarkType select_rowmark_type (RangeTblEntry *rte, LockClauseStrength strength)
 
void mark_partial_aggref (Aggref *agg, AggSplit aggsplit)
 
Pathget_cheapest_fractional_path (RelOptInfo *rel, double tuple_fraction)
 
Exprexpression_planner (Expr *expr)
 
Exprpreprocess_phv_expression (PlannerInfo *root, Expr *expr)
 
bool plan_cluster_use_sort (Oid tableOid, Oid indexOid)
 
int plan_create_index_workers (Oid tableOid, Oid indexOid)
 

Variables

PGDLLIMPORT planner_hook_type planner_hook
 
PGDLLIMPORT create_upper_paths_hook_type create_upper_paths_hook
 

Typedef Documentation

◆ create_upper_paths_hook_type

typedef void(* create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)

Definition at line 28 of file planner.h.

◆ planner_hook_type

typedef PlannedStmt*(* planner_hook_type) (Query *parse, int cursorOptions, ParamListInfo boundParams)

Definition at line 22 of file planner.h.

Function Documentation

◆ expression_planner()

Expr* expression_planner ( Expr expr)

Definition at line 5888 of file planner.c.

References eval_const_expressions(), and fix_opfuncids().

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), BeginCopyFrom(), CheckMutability(), ComputePartitionAttrs(), ExecPrepareCheck(), ExecPrepareExpr(), ExecPrepareQual(), gen_partprune_steps(), gen_partprune_steps_internal(), get_cast_hashentry(), load_domaintype_info(), slot_fill_defaults(), StoreAttrDefault(), and transformPartitionBoundValue().

5889 {
5890  Node *result;
5891 
5892  /*
5893  * Convert named-argument function calls, insert default arguments and
5894  * simplify constant subexprs
5895  */
5896  result = eval_const_expressions(NULL, (Node *) expr);
5897 
5898  /* Fill in opfuncid values if missing */
5899  fix_opfuncids(result);
5900 
5901  return (Expr *) result;
5902 }
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1582
Definition: nodes.h:517
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2460

◆ get_cheapest_fractional_path()

Path* get_cheapest_fractional_path ( RelOptInfo rel,
double  tuple_fraction 
)

Definition at line 5735 of file planner.c.

References RelOptInfo::cheapest_total_path, compare_fractional_path_costs(), lfirst, RelOptInfo::pathlist, and Path::rows.

Referenced by make_subplan(), recurse_set_operations(), and standard_planner().

5736 {
5737  Path *best_path = rel->cheapest_total_path;
5738  ListCell *l;
5739 
5740  /* If all tuples will be retrieved, just return the cheapest-total path */
5741  if (tuple_fraction <= 0.0)
5742  return best_path;
5743 
5744  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
5745  if (tuple_fraction >= 1.0 && best_path->rows > 0)
5746  tuple_fraction /= best_path->rows;
5747 
5748  foreach(l, rel->pathlist)
5749  {
5750  Path *path = (Path *) lfirst(l);
5751 
5752  if (path == rel->cheapest_total_path ||
5753  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
5754  continue;
5755 
5756  best_path = path;
5757  }
5758 
5759  return best_path;
5760 }
struct Path * cheapest_total_path
Definition: relation.h:630
#define lfirst(lc)
Definition: pg_list.h:106
double rows
Definition: relation.h:1088
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:117
List * pathlist
Definition: relation.h:626

◆ is_dummy_plan()

bool is_dummy_plan ( Plan plan)

Definition at line 2477 of file planner.c.

References Const::constisnull, Const::constvalue, DatumGetBool, IsA, linitial, and list_length().

2478 {
2479  if (IsA(plan, Result))
2480  {
2481  List *rcqual = (List *) ((Result *) plan)->resconstantqual;
2482 
2483  if (list_length(rcqual) == 1)
2484  {
2485  Const *constqual = (Const *) linitial(rcqual);
2486 
2487  if (constqual && IsA(constqual, Const))
2488  {
2489  if (!constqual->constisnull &&
2490  !DatumGetBool(constqual->constvalue))
2491  return true;
2492  }
2493  }
2494  }
2495  return false;
2496 }
Datum constvalue
Definition: primnodes.h:197
#define IsA(nodeptr, _type_)
Definition: nodes.h:568
#define linitial(l)
Definition: pg_list.h:111
#define DatumGetBool(X)
Definition: postgres.h:378
static int list_length(const List *l)
Definition: pg_list.h:89
Definition: pg_list.h:45
bool constisnull
Definition: primnodes.h:198

◆ mark_partial_aggref()

void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)

Definition at line 5184 of file planner.c.

References Aggref::aggsplit, AGGSPLIT_SIMPLE, Aggref::aggtranstype, Aggref::aggtype, Assert, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, and OidIsValid.

Referenced by convert_combining_aggrefs(), and make_partial_grouping_target().

5185 {
5186  /* aggtranstype should be computed by this point */
5188  /* ... but aggsplit should still be as the parser left it */
5189  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
5190 
5191  /* Mark the Aggref with the intended partial-aggregation mode */
5192  agg->aggsplit = aggsplit;
5193 
5194  /*
5195  * Adjust result type if needed. Normally, a partial aggregate returns
5196  * the aggregate's transition type; but if that's INTERNAL and we're
5197  * serializing, it returns BYTEA instead.
5198  */
5199  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
5200  {
5201  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
5202  agg->aggtype = BYTEAOID;
5203  else
5204  agg->aggtype = agg->aggtranstype;
5205  }
5206 }
#define OidIsValid(objectId)
Definition: c.h:605
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:778
#define Assert(condition)
Definition: c.h:699
AggSplit aggsplit
Definition: primnodes.h:311
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:777
Oid aggtranstype
Definition: primnodes.h:299
Oid aggtype
Definition: primnodes.h:296

◆ plan_cluster_use_sort()

bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 5917 of file planner.c.

References build_simple_rel(), CMD_SELECT, Query::commandType, cost_qual_eval(), cost_sort(), create_index_path(), create_seqscan_path(), CurrentMemoryContext, enable_indexscan, ForwardScanDirection, get_relation_data_width(), PlannerInfo::glob, RelOptInfo::indexlist, IndexOptInfo::indexoid, IndexOptInfo::indexprs, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::lateral, lfirst_node, list_make1, maintenance_work_mem, makeNode, NIL, RelOptInfo::pages, PlannerInfo::parse, IndexPath::path, QualCost::per_tuple, PlannerInfo::planner_cxt, PlannerInfo::query_level, RangeTblEntry::relid, RangeTblEntry::relkind, RelOptInfo::reltarget, RelOptInfo::rows, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), QualCost::startup, Path::total_cost, PlannerInfo::total_table_pages, RelOptInfo::tuples, PathTarget::width, and PlannerInfo::wt_param_id.

Referenced by copy_heap_data().

5918 {
5919  PlannerInfo *root;
5920  Query *query;
5921  PlannerGlobal *glob;
5922  RangeTblEntry *rte;
5923  RelOptInfo *rel;
5924  IndexOptInfo *indexInfo;
5925  QualCost indexExprCost;
5926  Cost comparisonCost;
5927  Path *seqScanPath;
5928  Path seqScanAndSortPath;
5929  IndexPath *indexScanPath;
5930  ListCell *lc;
5931 
5932  /* We can short-circuit the cost comparison if indexscans are disabled */
5933  if (!enable_indexscan)
5934  return true; /* use sort */
5935 
5936  /* Set up mostly-dummy planner state */
5937  query = makeNode(Query);
5938  query->commandType = CMD_SELECT;
5939 
5940  glob = makeNode(PlannerGlobal);
5941 
5942  root = makeNode(PlannerInfo);
5943  root->parse = query;
5944  root->glob = glob;
5945  root->query_level = 1;
5947  root->wt_param_id = -1;
5948 
5949  /* Build a minimal RTE for the rel */
5950  rte = makeNode(RangeTblEntry);
5951  rte->rtekind = RTE_RELATION;
5952  rte->relid = tableOid;
5953  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
5954  rte->lateral = false;
5955  rte->inh = false;
5956  rte->inFromCl = true;
5957  query->rtable = list_make1(rte);
5958 
5959  /* Set up RTE/RelOptInfo arrays */
5961 
5962  /* Build RelOptInfo */
5963  rel = build_simple_rel(root, 1, NULL);
5964 
5965  /* Locate IndexOptInfo for the target index */
5966  indexInfo = NULL;
5967  foreach(lc, rel->indexlist)
5968  {
5969  indexInfo = lfirst_node(IndexOptInfo, lc);
5970  if (indexInfo->indexoid == indexOid)
5971  break;
5972  }
5973 
5974  /*
5975  * It's possible that get_relation_info did not generate an IndexOptInfo
5976  * for the desired index; this could happen if it's not yet reached its
5977  * indcheckxmin usability horizon, or if it's a system index and we're
5978  * ignoring system indexes. In such cases we should tell CLUSTER to not
5979  * trust the index contents but use seqscan-and-sort.
5980  */
5981  if (lc == NULL) /* not in the list? */
5982  return true; /* use sort */
5983 
5984  /*
5985  * Rather than doing all the pushups that would be needed to use
5986  * set_baserel_size_estimates, just do a quick hack for rows and width.
5987  */
5988  rel->rows = rel->tuples;
5989  rel->reltarget->width = get_relation_data_width(tableOid, NULL);
5990 
5991  root->total_table_pages = rel->pages;
5992 
5993  /*
5994  * Determine eval cost of the index expressions, if any. We need to
5995  * charge twice that amount for each tuple comparison that happens during
5996  * the sort, since tuplesort.c will have to re-evaluate the index
5997  * expressions each time. (XXX that's pretty inefficient...)
5998  */
5999  cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
6000  comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
6001 
6002  /* Estimate the cost of seq scan + sort */
6003  seqScanPath = create_seqscan_path(root, rel, NULL, 0);
6004  cost_sort(&seqScanAndSortPath, root, NIL,
6005  seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
6006  comparisonCost, maintenance_work_mem, -1.0);
6007 
6008  /* Estimate the cost of index scan */
6009  indexScanPath = create_index_path(root, indexInfo,
6010  NIL, NIL, NIL, NIL, NIL,
6011  ForwardScanDirection, false,
6012  NULL, 1.0, false);
6013 
6014  return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
6015 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:169
Path path
Definition: relation.h:1154
double tuples
Definition: relation.h:652
IndexPath * create_index_path(PlannerInfo *root, IndexOptInfo *index, List *indexclauses, List *indexclausecols, List *indexorderbys, List *indexorderbycols, List *pathkeys, ScanDirection indexscandir, bool indexonly, Relids required_outer, double loop_count, bool partial_path)
Definition: pathnode.c:1024
Cost startup
Definition: relation.h:46
#define list_make1(x1)
Definition: pg_list.h:139
Cost per_tuple
Definition: relation.h:47
int wt_param_id
Definition: relation.h:324
List * rtable
Definition: parsenodes.h:137
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3716
#define lfirst_node(type, lc)
Definition: pg_list.h:109
PlannerGlobal * glob
Definition: relation.h:171
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:96
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
double total_table_pages
Definition: relation.h:304
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition: plancat.c:1141
void cost_sort(Path *path, PlannerInfo *root, List *pathkeys, Cost input_cost, double tuples, int width, Cost comparison_cost, int sort_mem, double limit_tuples)
Definition: costsize.c:1661
List * indexlist
Definition: relation.h:649
double rows
Definition: relation.h:615
int maintenance_work_mem
Definition: globals.c:123
Cost total_cost
Definition: relation.h:1090
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:565
BlockNumber pages
Definition: relation.h:651
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
Index query_level
Definition: relation.h:173
RTEKind rtekind
Definition: parsenodes.h:962
MemoryContext planner_cxt
Definition: relation.h:302
Oid indexoid
Definition: relation.h:753
struct PathTarget * reltarget
Definition: relation.h:623
bool enable_indexscan
Definition: costsize.c:126
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:954
double Cost
Definition: nodes.h:648
List * indexprs
Definition: relation.h:777

◆ plan_create_index_workers()

int plan_create_index_workers ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 6034 of file planner.c.

References build_simple_rel(), CMD_SELECT, Query::commandType, compute_parallel_worker(), CurrentMemoryContext, DSM_IMPL_NONE, dynamic_shared_memory_type, estimate_rel_size(), PlannerInfo::glob, heap_close, heap_open(), index_close(), index_open(), RangeTblEntry::inFromCl, RangeTblEntry::inh, is_parallel_safe(), RangeTblEntry::lateral, list_make1, maintenance_work_mem, makeNode, max_parallel_maintenance_workers, Min, NoLock, PlannerInfo::parse, PlannerInfo::planner_cxt, PlannerInfo::query_level, RelationData::rd_rel, RelOptInfo::rel_parallel_workers, RelationGetIndexExpressions(), RelationGetIndexPredicate(), RangeTblEntry::relid, RangeTblEntry::relkind, reltuples, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, setup_simple_rel_arrays(), and PlannerInfo::wt_param_id.

Referenced by index_build().

6035 {
6036  PlannerInfo *root;
6037  Query *query;
6038  PlannerGlobal *glob;
6039  RangeTblEntry *rte;
6040  Relation heap;
6041  Relation index;
6042  RelOptInfo *rel;
6043  int parallel_workers;
6044  BlockNumber heap_blocks;
6045  double reltuples;
6046  double allvisfrac;
6047 
6048  /* Return immediately when parallelism disabled */
6051  return 0;
6052 
6053  /* Set up largely-dummy planner state */
6054  query = makeNode(Query);
6055  query->commandType = CMD_SELECT;
6056 
6057  glob = makeNode(PlannerGlobal);
6058 
6059  root = makeNode(PlannerInfo);
6060  root->parse = query;
6061  root->glob = glob;
6062  root->query_level = 1;
6064  root->wt_param_id = -1;
6065 
6066  /*
6067  * Build a minimal RTE.
6068  *
6069  * Set the target's table to be an inheritance parent. This is a kludge
6070  * that prevents problems within get_relation_info(), which does not
6071  * expect that any IndexOptInfo is currently undergoing REINDEX.
6072  */
6073  rte = makeNode(RangeTblEntry);
6074  rte->rtekind = RTE_RELATION;
6075  rte->relid = tableOid;
6076  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
6077  rte->lateral = false;
6078  rte->inh = true;
6079  rte->inFromCl = true;
6080  query->rtable = list_make1(rte);
6081 
6082  /* Set up RTE/RelOptInfo arrays */
6084 
6085  /* Build RelOptInfo */
6086  rel = build_simple_rel(root, 1, NULL);
6087 
6088  heap = heap_open(tableOid, NoLock);
6089  index = index_open(indexOid, NoLock);
6090 
6091  /*
6092  * Determine if it's safe to proceed.
6093  *
6094  * Currently, parallel workers can't access the leader's temporary tables.
6095  * Furthermore, any index predicate or index expressions must be parallel
6096  * safe.
6097  */
6098  if (heap->rd_rel->relpersistence == RELPERSISTENCE_TEMP ||
6099  !is_parallel_safe(root, (Node *) RelationGetIndexExpressions(index)) ||
6100  !is_parallel_safe(root, (Node *) RelationGetIndexPredicate(index)))
6101  {
6102  parallel_workers = 0;
6103  goto done;
6104  }
6105 
6106  /*
6107  * If parallel_workers storage parameter is set for the table, accept that
6108  * as the number of parallel worker processes to launch (though still cap
6109  * at max_parallel_maintenance_workers). Note that we deliberately do not
6110  * consider any other factor when parallel_workers is set. (e.g., memory
6111  * use by workers.)
6112  */
6113  if (rel->rel_parallel_workers != -1)
6114  {
6115  parallel_workers = Min(rel->rel_parallel_workers,
6117  goto done;
6118  }
6119 
6120  /*
6121  * Estimate heap relation size ourselves, since rel->pages cannot be
6122  * trusted (heap RTE was marked as inheritance parent)
6123  */
6124  estimate_rel_size(heap, NULL, &heap_blocks, &reltuples, &allvisfrac);
6125 
6126  /*
6127  * Determine number of workers to scan the heap relation using generic
6128  * model
6129  */
6130  parallel_workers = compute_parallel_worker(rel, heap_blocks, -1,
6132 
6133  /*
6134  * Cap workers based on available maintenance_work_mem as needed.
6135  *
6136  * Note that each tuplesort participant receives an even share of the
6137  * total maintenance_work_mem budget. Aim to leave participants
6138  * (including the leader as a participant) with no less than 32MB of
6139  * memory. This leaves cases where maintenance_work_mem is set to 64MB
6140  * immediately past the threshold of being capable of launching a single
6141  * parallel worker to sort.
6142  */
6143  while (parallel_workers > 0 &&
6144  maintenance_work_mem / (parallel_workers + 1) < 32768L)
6145  parallel_workers--;
6146 
6147 done:
6148  index_close(index, NoLock);
6149  heap_close(heap, NoLock);
6150 
6151  return parallel_workers;
6152 }
Query * parse
Definition: relation.h:169
int compute_parallel_worker(RelOptInfo *rel, double heap_pages, double index_pages, int max_workers)
Definition: allpaths.c:3439
#define Min(x, y)
Definition: c.h:857
Definition: nodes.h:517
uint32 BlockNumber
Definition: block.h:31
#define heap_close(r, l)
Definition: heapam.h:97
Form_pg_class rd_rel
Definition: rel.h:84
List * RelationGetIndexPredicate(Relation relation)
Definition: relcache.c:4608
Definition: type.h:89
#define list_make1(x1)
Definition: pg_list.h:139
bool is_parallel_safe(PlannerInfo *root, Node *node)
Definition: clauses.c:1088
int wt_param_id
Definition: relation.h:324
List * rtable
Definition: parsenodes.h:137
#define NoLock
Definition: lockdefs.h:34
List * RelationGetIndexExpressions(Relation relation)
Definition: relcache.c:4546
PlannerGlobal * glob
Definition: relation.h:171
int dynamic_shared_memory_type
Definition: dsm_impl.c:114
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptInfo *parent)
Definition: relnode.c:96
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void estimate_rel_size(Relation rel, int32 *attr_widths, BlockNumber *pages, double *tuples, double *allvisfrac)
Definition: plancat.c:939
int rel_parallel_workers
Definition: relation.h:656
int max_parallel_maintenance_workers
Definition: globals.c:124
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Definition: heapam.c:1294
int maintenance_work_mem
Definition: globals.c:123
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:565
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
Index query_level
Definition: relation.h:173
void index_close(Relation relation, LOCKMODE lockmode)
Definition: indexam.c:176
RTEKind rtekind
Definition: parsenodes.h:962
MemoryContext planner_cxt
Definition: relation.h:302
Relation index_open(Oid relationId, LOCKMODE lockmode)
Definition: indexam.c:150
float4 reltuples
Definition: pg_class.h:44

◆ planner()

PlannedStmt* planner ( Query parse,
int  cursorOptions,
ParamListInfo  boundParams 
)

Definition at line 256 of file planner.c.

References parse(), planner_hook, and standard_planner().

Referenced by pg_plan_query().

257 {
258  PlannedStmt *result;
259 
260  if (planner_hook)
261  result = (*planner_hook) (parse, cursorOptions, boundParams);
262  else
263  result = standard_planner(parse, cursorOptions, boundParams);
264  return result;
265 }
PlannedStmt * standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Definition: planner.c:268
planner_hook_type planner_hook
Definition: planner.c:68
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ preprocess_phv_expression()

Expr* preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)

Definition at line 1131 of file planner.c.

References EXPRKIND_PHV, and preprocess_expression().

Referenced by extract_lateral_references().

1132 {
1133  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1134 }
Definition: nodes.h:517
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1000
#define EXPRKIND_PHV
Definition: planner.c:83

◆ select_rowmark_type()

RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)

Definition at line 2613 of file planner.c.

References elog, ERROR, GetFdwRoutineByRelId(), FdwRoutine::GetForeignRowMarkType, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, LCS_NONE, RangeTblEntry::relid, RangeTblEntry::relkind, ROW_MARK_COPY, ROW_MARK_EXCLUSIVE, ROW_MARK_KEYSHARE, ROW_MARK_NOKEYEXCLUSIVE, ROW_MARK_REFERENCE, ROW_MARK_SHARE, RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by expand_single_inheritance_child(), and preprocess_rowmarks().

2614 {
2615  if (rte->rtekind != RTE_RELATION)
2616  {
2617  /* If it's not a table at all, use ROW_MARK_COPY */
2618  return ROW_MARK_COPY;
2619  }
2620  else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2621  {
2622  /* Let the FDW select the rowmark type, if it wants to */
2623  FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2624 
2625  if (fdwroutine->GetForeignRowMarkType != NULL)
2626  return fdwroutine->GetForeignRowMarkType(rte, strength);
2627  /* Otherwise, use ROW_MARK_COPY by default */
2628  return ROW_MARK_COPY;
2629  }
2630  else
2631  {
2632  /* Regular table, apply the appropriate lock type */
2633  switch (strength)
2634  {
2635  case LCS_NONE:
2636 
2637  /*
2638  * We don't need a tuple lock, only the ability to re-fetch
2639  * the row.
2640  */
2641  return ROW_MARK_REFERENCE;
2642  break;
2643  case LCS_FORKEYSHARE:
2644  return ROW_MARK_KEYSHARE;
2645  break;
2646  case LCS_FORSHARE:
2647  return ROW_MARK_SHARE;
2648  break;
2649  case LCS_FORNOKEYUPDATE:
2650  return ROW_MARK_NOKEYEXCLUSIVE;
2651  break;
2652  case LCS_FORUPDATE:
2653  return ROW_MARK_EXCLUSIVE;
2654  break;
2655  }
2656  elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2657  return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2658  }
2659 }
#define ERROR
Definition: elog.h:43
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:372
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:223
RTEKind rtekind
Definition: parsenodes.h:962
#define elog
Definition: elog.h:219

◆ standard_planner()

PlannedStmt* standard_planner ( Query parse,
int  cursorOptions,
ParamListInfo  boundParams 
)

Definition at line 268 of file planner.c.

References Assert, PlannerGlobal::boundParams, PlannedStmt::canSetTag, Query::canSetTag, CMD_SELECT, PlannedStmt::commandType, Query::commandType, create_plan(), CURSOR_OPT_FAST_PLAN, CURSOR_OPT_PARALLEL_OK, CURSOR_OPT_SCROLL, cursor_tuple_fraction, PlannedStmt::dependsOnRole, PlannerGlobal::dependsOnRole, DSM_IMPL_NONE, dynamic_shared_memory_type, ExecSupportsBackwardScan(), fetch_upper_rel(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, forboth, force_parallel_mode, FORCE_PARALLEL_OFF, FORCE_PARALLEL_REGRESS, get_cheapest_fractional_path(), PlannerInfo::glob, PlannedStmt::hasModifyingCTE, Query::hasModifyingCTE, PlannedStmt::hasReturning, Plan::initPlan, PlannedStmt::invalItems, PlannerGlobal::invalItems, Gather::invisible, IsolationIsSerializable, IsParallelWorker, IsUnderPostmaster, jit_above_cost, jit_enabled, jit_expressions, jit_inline_above_cost, jit_optimize_above_cost, jit_tuple_deforming, PlannedStmt::jitFlags, PlannerGlobal::lastPHId, PlannerGlobal::lastPlanNodeId, PlannerGlobal::lastRowMarkId, Plan::lefttree, lfirst, lfirst_node, list_length(), makeNode, materialize_finished_plan(), max_parallel_hazard(), max_parallel_workers_per_gather, PlannerGlobal::maxParallelHazard, NIL, PlannedStmt::nonleafResultRelations, PlannerGlobal::nonleafResultRelations, Gather::num_workers, Plan::parallel_aware, Plan::parallel_safe, parallel_setup_cost, parallel_tuple_cost, PlannedStmt::parallelModeNeeded, PlannerGlobal::parallelModeNeeded, PlannerGlobal::parallelModeOK, PlannedStmt::paramExecTypes, PlannerGlobal::paramExecTypes, PGJIT_DEFORM, PGJIT_EXPR, PGJIT_INLINE, PGJIT_NONE, PGJIT_OPT3, PGJIT_PERFORM, Gather::plan, Plan::plan_rows, Plan::plan_width, PlannedStmt::planTree, Plan::qual, PlannedStmt::queryId, Query::queryId, PlannedStmt::relationOids, PlannerGlobal::relationOids, Gather::rescan_param, PlannedStmt::resultRelations, PlannerGlobal::resultRelations, Query::returningList, PlannedStmt::rewindPlanIDs, PlannerGlobal::rewindPlanIDs, Plan::righttree, PlannedStmt::rootResultRelations, PlannerGlobal::rootResultRelations, PlannedStmt::rowMarks, PlannedStmt::rtable, set_plan_references(), Gather::single_copy, SS_finalize_plan(), Plan::startup_cost, PlannedStmt::stmt_len, Query::stmt_len, PlannedStmt::stmt_location, Query::stmt_location, PlannedStmt::subplans, PlannerGlobal::subplans, subquery_planner(), PlannerGlobal::subroots, Plan::targetlist, Plan::total_cost, PlannedStmt::transientPlan, PlannerGlobal::transientPlan, UPPERREL_FINAL, PlannedStmt::utilityStmt, and Query::utilityStmt.

Referenced by planner().

269 {
270  PlannedStmt *result;
271  PlannerGlobal *glob;
272  double tuple_fraction;
273  PlannerInfo *root;
274  RelOptInfo *final_rel;
275  Path *best_path;
276  Plan *top_plan;
277  ListCell *lp,
278  *lr;
279 
280  /*
281  * Set up global state for this planner invocation. This data is needed
282  * across all levels of sub-Query that might exist in the given command,
283  * so we keep it in a separate struct that's linked to by each per-Query
284  * PlannerInfo.
285  */
286  glob = makeNode(PlannerGlobal);
287 
288  glob->boundParams = boundParams;
289  glob->subplans = NIL;
290  glob->subroots = NIL;
291  glob->rewindPlanIDs = NULL;
292  glob->finalrtable = NIL;
293  glob->finalrowmarks = NIL;
294  glob->resultRelations = NIL;
295  glob->nonleafResultRelations = NIL;
296  glob->rootResultRelations = NIL;
297  glob->relationOids = NIL;
298  glob->invalItems = NIL;
299  glob->paramExecTypes = NIL;
300  glob->lastPHId = 0;
301  glob->lastRowMarkId = 0;
302  glob->lastPlanNodeId = 0;
303  glob->transientPlan = false;
304  glob->dependsOnRole = false;
305 
306  /*
307  * Assess whether it's feasible to use parallel mode for this query. We
308  * can't do this in a standalone backend, or if the command will try to
309  * modify any data, or if this is a cursor operation, or if GUCs are set
310  * to values that don't permit parallelism, or if parallel-unsafe
311  * functions are present in the query tree.
312  *
313  * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
314  * MATERIALIZED VIEW to use parallel plans, but this is safe only because
315  * the command is writing into a completely new table which workers won't
316  * be able to see. If the workers could see the table, the fact that
317  * group locking would cause them to ignore the leader's heavyweight
318  * relation extension lock and GIN page locks would make this unsafe.
319  * We'll have to fix that somehow if we want to allow parallel inserts in
320  * general; updates and deletes have additional problems especially around
321  * combo CIDs.)
322  *
323  * For now, we don't try to use parallel mode if we're running inside a
324  * parallel worker. We might eventually be able to relax this
325  * restriction, but for now it seems best not to have parallel workers
326  * trying to create their own parallel workers.
327  *
328  * We can't use parallelism in serializable mode because the predicate
329  * locking code is not parallel-aware. It's not catastrophic if someone
330  * tries to run a parallel plan in serializable mode; it just won't get
331  * any workers and will run serially. But it seems like a good heuristic
332  * to assume that the same serialization level will be in effect at plan
333  * time and execution time, so don't generate a parallel plan if we're in
334  * serializable mode.
335  */
336  if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
339  parse->commandType == CMD_SELECT &&
340  !parse->hasModifyingCTE &&
342  !IsParallelWorker() &&
344  {
345  /* all the cheap tests pass, so scan the query tree */
346  glob->maxParallelHazard = max_parallel_hazard(parse);
347  glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
348  }
349  else
350  {
351  /* skip the query tree scan, just assume it's unsafe */
352  glob->maxParallelHazard = PROPARALLEL_UNSAFE;
353  glob->parallelModeOK = false;
354  }
355 
356  /*
357  * glob->parallelModeNeeded is normally set to false here and changed to
358  * true during plan creation if a Gather or Gather Merge plan is actually
359  * created (cf. create_gather_plan, create_gather_merge_plan).
360  *
361  * However, if force_parallel_mode = on or force_parallel_mode = regress,
362  * then we impose parallel mode whenever it's safe to do so, even if the
363  * final plan doesn't use parallelism. It's not safe to do so if the
364  * query contains anything parallel-unsafe; parallelModeOK will be false
365  * in that case. Note that parallelModeOK can't change after this point.
366  * Otherwise, everything in the query is either parallel-safe or
367  * parallel-restricted, and in either case it should be OK to impose
368  * parallel-mode restrictions. If that ends up breaking something, then
369  * either some function the user included in the query is incorrectly
370  * labelled as parallel-safe or parallel-restricted when in reality it's
371  * parallel-unsafe, or else the query planner itself has a bug.
372  */
373  glob->parallelModeNeeded = glob->parallelModeOK &&
375 
376  /* Determine what fraction of the plan is likely to be scanned */
377  if (cursorOptions & CURSOR_OPT_FAST_PLAN)
378  {
379  /*
380  * We have no real idea how many tuples the user will ultimately FETCH
381  * from a cursor, but it is often the case that he doesn't want 'em
382  * all, or would prefer a fast-start plan anyway so that he can
383  * process some of the tuples sooner. Use a GUC parameter to decide
384  * what fraction to optimize for.
385  */
386  tuple_fraction = cursor_tuple_fraction;
387 
388  /*
389  * We document cursor_tuple_fraction as simply being a fraction, which
390  * means the edge cases 0 and 1 have to be treated specially here. We
391  * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
392  */
393  if (tuple_fraction >= 1.0)
394  tuple_fraction = 0.0;
395  else if (tuple_fraction <= 0.0)
396  tuple_fraction = 1e-10;
397  }
398  else
399  {
400  /* Default assumption is we need all the tuples */
401  tuple_fraction = 0.0;
402  }
403 
404  /* primary planning entry point (may recurse for subqueries) */
405  root = subquery_planner(glob, parse, NULL,
406  false, tuple_fraction);
407 
408  /* Select best Path and turn it into a Plan */
409  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
410  best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
411 
412  top_plan = create_plan(root, best_path);
413 
414  /*
415  * If creating a plan for a scrollable cursor, make sure it can run
416  * backwards on demand. Add a Material node at the top at need.
417  */
418  if (cursorOptions & CURSOR_OPT_SCROLL)
419  {
420  if (!ExecSupportsBackwardScan(top_plan))
421  top_plan = materialize_finished_plan(top_plan);
422  }
423 
424  /*
425  * Optionally add a Gather node for testing purposes, provided this is
426  * actually a safe thing to do.
427  */
429  {
430  Gather *gather = makeNode(Gather);
431 
432  /*
433  * If there are any initPlans attached to the formerly-top plan node,
434  * move them up to the Gather node; same as we do for Material node in
435  * materialize_finished_plan.
436  */
437  gather->plan.initPlan = top_plan->initPlan;
438  top_plan->initPlan = NIL;
439 
440  gather->plan.targetlist = top_plan->targetlist;
441  gather->plan.qual = NIL;
442  gather->plan.lefttree = top_plan;
443  gather->plan.righttree = NULL;
444  gather->num_workers = 1;
445  gather->single_copy = true;
447 
448  /*
449  * Since this Gather has no parallel-aware descendants to signal to,
450  * we don't need a rescan Param.
451  */
452  gather->rescan_param = -1;
453 
454  /*
455  * Ideally we'd use cost_gather here, but setting up dummy path data
456  * to satisfy it doesn't seem much cleaner than knowing what it does.
457  */
458  gather->plan.startup_cost = top_plan->startup_cost +
460  gather->plan.total_cost = top_plan->total_cost +
462  gather->plan.plan_rows = top_plan->plan_rows;
463  gather->plan.plan_width = top_plan->plan_width;
464  gather->plan.parallel_aware = false;
465  gather->plan.parallel_safe = false;
466 
467  /* use parallel mode for parallel plans. */
468  root->glob->parallelModeNeeded = true;
469 
470  top_plan = &gather->plan;
471  }
472 
473  /*
474  * If any Params were generated, run through the plan tree and compute
475  * each plan node's extParam/allParam sets. Ideally we'd merge this into
476  * set_plan_references' tree traversal, but for now it has to be separate
477  * because we need to visit subplans before not after main plan.
478  */
479  if (glob->paramExecTypes != NIL)
480  {
481  Assert(list_length(glob->subplans) == list_length(glob->subroots));
482  forboth(lp, glob->subplans, lr, glob->subroots)
483  {
484  Plan *subplan = (Plan *) lfirst(lp);
485  PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
486 
487  SS_finalize_plan(subroot, subplan);
488  }
489  SS_finalize_plan(root, top_plan);
490  }
491 
492  /* final cleanup of the plan */
493  Assert(glob->finalrtable == NIL);
494  Assert(glob->finalrowmarks == NIL);
495  Assert(glob->resultRelations == NIL);
497  Assert(glob->rootResultRelations == NIL);
498  top_plan = set_plan_references(root, top_plan);
499  /* ... and the subplans (both regular subplans and initplans) */
500  Assert(list_length(glob->subplans) == list_length(glob->subroots));
501  forboth(lp, glob->subplans, lr, glob->subroots)
502  {
503  Plan *subplan = (Plan *) lfirst(lp);
504  PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
505 
506  lfirst(lp) = set_plan_references(subroot, subplan);
507  }
508 
509  /* build the PlannedStmt result */
510  result = makeNode(PlannedStmt);
511 
512  result->commandType = parse->commandType;
513  result->queryId = parse->queryId;
514  result->hasReturning = (parse->returningList != NIL);
515  result->hasModifyingCTE = parse->hasModifyingCTE;
516  result->canSetTag = parse->canSetTag;
517  result->transientPlan = glob->transientPlan;
518  result->dependsOnRole = glob->dependsOnRole;
519  result->parallelModeNeeded = glob->parallelModeNeeded;
520  result->planTree = top_plan;
521  result->rtable = glob->finalrtable;
522  result->resultRelations = glob->resultRelations;
525  result->subplans = glob->subplans;
526  result->rewindPlanIDs = glob->rewindPlanIDs;
527  result->rowMarks = glob->finalrowmarks;
528  result->relationOids = glob->relationOids;
529  result->invalItems = glob->invalItems;
530  result->paramExecTypes = glob->paramExecTypes;
531  /* utilityStmt should be null, but we might as well copy it */
532  result->utilityStmt = parse->utilityStmt;
533  result->stmt_location = parse->stmt_location;
534  result->stmt_len = parse->stmt_len;
535 
536  result->jitFlags = PGJIT_NONE;
537  if (jit_enabled && jit_above_cost >= 0 &&
538  top_plan->total_cost > jit_above_cost)
539  {
540  result->jitFlags |= PGJIT_PERFORM;
541 
542  /*
543  * Decide how much effort should be put into generating better code.
544  */
545  if (jit_optimize_above_cost >= 0 &&
547  result->jitFlags |= PGJIT_OPT3;
548  if (jit_inline_above_cost >= 0 &&
549  top_plan->total_cost > jit_inline_above_cost)
550  result->jitFlags |= PGJIT_INLINE;
551 
552  /*
553  * Decide which operations should be JITed.
554  */
555  if (jit_expressions)
556  result->jitFlags |= PGJIT_EXPR;
558  result->jitFlags |= PGJIT_DEFORM;
559  }
560 
561  return result;
562 }
char maxParallelHazard
Definition: relation.h:147
bool dependsOnRole
Definition: plannodes.h:57
List * paramExecTypes
Definition: plannodes.h:94
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:147
double plan_rows
Definition: plannodes.h:133
#define PGJIT_EXPR
Definition: jit.h:23
#define PGJIT_NONE
Definition: jit.h:19
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
int stmt_location
Definition: parsenodes.h:181
List * nonleafResultRelations
Definition: plannodes.h:74
List * relationOids
Definition: plannodes.h:90
int lastPlanNodeId
Definition: relation.h:137
List * resultRelations
Definition: relation.h:122
double parallel_setup_cost
Definition: costsize.c:117
Node * utilityStmt
Definition: parsenodes.h:120
bool transientPlan
Definition: plannodes.h:55
int stmt_len
Definition: plannodes.h:100
char max_parallel_hazard(Query *parse)
Definition: clauses.c:1069
struct Plan * planTree
Definition: plannodes.h:63
List * invalItems
Definition: plannodes.h:92
List * rootResultRelations
Definition: relation.h:125
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:315
bool dependsOnRole
Definition: relation.h:141
struct Plan * righttree
Definition: plannodes.h:149
#define PGJIT_OPT3
Definition: jit.h:21
bool parallelModeNeeded
Definition: relation.h:145
bool jit_enabled
Definition: jit.c:35
List * paramExecTypes
Definition: relation.h:131
Plan plan
Definition: plannodes.h:859
bool single_copy
Definition: plannodes.h:862
bool parallelModeOK
Definition: relation.h:143
Bitmapset * rewindPlanIDs
Definition: relation.h:116
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1145
#define lfirst_node(type, lc)
Definition: pg_list.h:109
int stmt_location
Definition: plannodes.h:99
List * subplans
Definition: relation.h:112
Cost startup_cost
Definition: plannodes.h:127
PlannerGlobal * glob
Definition: relation.h:171
bool IsUnderPostmaster
Definition: globals.c:110
bool hasReturning
Definition: plannodes.h:49
Plan * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:6117
List * rootResultRelations
Definition: plannodes.h:81
Node * utilityStmt
Definition: plannodes.h:96
int dynamic_shared_memory_type
Definition: dsm_impl.c:114
bool parallel_aware
Definition: plannodes.h:139
int jitFlags
Definition: plannodes.h:61
double cursor_tuple_fraction
Definition: planner.c:63
bool jit_expressions
Definition: jit.c:39
List * returningList
Definition: parsenodes.h:146
#define IsParallelWorker()
Definition: parallel.h:60
uint64 queryId
Definition: parsenodes.h:116
List * invalItems
Definition: relation.h:129
bool canSetTag
Definition: plannodes.h:53
CmdType commandType
Definition: plannodes.h:45
#define CURSOR_OPT_FAST_PLAN
Definition: parsenodes.h:2650
double jit_above_cost
Definition: jit.c:42
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:462
Index lastPHId
Definition: relation.h:133
#define PGJIT_INLINE
Definition: jit.h:22
bool jit_tuple_deforming
Definition: jit.c:41
List * rowMarks
Definition: plannodes.h:88
int num_workers
Definition: plannodes.h:860
double jit_inline_above_cost
Definition: jit.c:43
CmdType commandType
Definition: parsenodes.h:112
#define makeNode(_type_)
Definition: nodes.h:565
List * subplans
Definition: plannodes.h:83
List * nonleafResultRelations
Definition: relation.h:124
int plan_width
Definition: plannodes.h:134
int force_parallel_mode
Definition: planner.c:64
ParamListInfo boundParams
Definition: relation.h:110
#define Assert(condition)
Definition: c.h:699
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * rewindPlanIDs
Definition: plannodes.h:86
bool hasModifyingCTE
Definition: plannodes.h:51
bool canSetTag
Definition: parsenodes.h:118
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
int rescan_param
Definition: plannodes.h:861
#define PGJIT_PERFORM
Definition: jit.h:20
static int list_length(const List *l)
Definition: pg_list.h:89
List * relationOids
Definition: relation.h:127
List * subroots
Definition: relation.h:114
List * rtable
Definition: plannodes.h:65
struct Plan * lefttree
Definition: plannodes.h:148
double jit_optimize_above_cost
Definition: jit.c:44
List * targetlist
Definition: plannodes.h:146
bool invisible
Definition: plannodes.h:863
e
Definition: preproc-init.c:82
List * finalrtable
Definition: relation.h:118
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2653
Index lastRowMarkId
Definition: relation.h:135
uint64 queryId
Definition: plannodes.h:47
#define IsolationIsSerializable()
Definition: xact.h:51
List * resultRelations
Definition: plannodes.h:68
bool parallelModeNeeded
Definition: plannodes.h:59
List * initPlan
Definition: plannodes.h:150
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2645
Cost total_cost
Definition: plannodes.h:128
bool hasModifyingCTE
Definition: parsenodes.h:131
bool parallel_safe
Definition: plannodes.h:140
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:214
#define PGJIT_DEFORM
Definition: jit.h:24
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2242
int max_parallel_workers_per_gather
Definition: costsize.c:123
List * finalrowmarks
Definition: relation.h:120
int stmt_len
Definition: parsenodes.h:182
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
Definition: planner.c:594
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition: planner.c:5735
bool transientPlan
Definition: relation.h:139
double parallel_tuple_cost
Definition: costsize.c:116

◆ subquery_planner()

PlannerInfo* subquery_planner ( PlannerGlobal glob,
Query parse,
PlannerInfo parent_root,
bool  hasRecursion,
double  tuple_fraction 
)

Definition at line 594 of file planner.c.

References PlannerInfo::append_rel_list, OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, contain_agg_clause(), contain_subplans(), contain_volatile_functions(), copyObject, PlannerInfo::cte_plan_ids, Query::cteList, CurrentMemoryContext, WindowClause::endOffset, PlannerInfo::eq_classes, expand_inherited_tables(), expression_returns_set(), EXPRKIND_APPINFO, EXPRKIND_ARBITER_ELEM, EXPRKIND_LIMIT, EXPRKIND_QUAL, EXPRKIND_RTFUNC, EXPRKIND_RTFUNC_LATERAL, EXPRKIND_TABLEFUNC, EXPRKIND_TABLEFUNC_LATERAL, EXPRKIND_TABLESAMPLE, EXPRKIND_TARGET, EXPRKIND_VALUES, EXPRKIND_VALUES_LATERAL, fetch_upper_rel(), flatten_join_alias_vars(), flatten_simple_union_all(), RangeTblEntry::functions, PlannerInfo::glob, Query::groupClause, PlannerInfo::grouping_map, grouping_planner(), Query::groupingSets, PlannerInfo::hasHavingQual, PlannerInfo::hasJoinRTEs, PlannerInfo::hasLateralRTEs, PlannerInfo::hasPseudoConstantQuals, PlannerInfo::hasRecursion, Query::hasSubLinks, Query::hasTargetSRFs, Query::havingQual, inheritance_planner(), INHKIND_NONE, PlannerInfo::inhTargetKind, PlannerInfo::init_plans, inline_set_returning_functions(), IS_OUTER_JOIN, RangeTblEntry::joinaliasvars, Query::jointree, RangeTblEntry::jointype, lappend(), RangeTblEntry::lateral, lfirst, lfirst_node, Query::limitCount, Query::limitOffset, makeNode, PlannerInfo::minmax_aggs, PlannerInfo::multiexpr_params, NIL, PlannerInfo::non_recursive_path, Query::onConflict, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, PlannerInfo::outer_params, PlannerInfo::parent_root, parse(), PlannerInfo::parse, PlannerInfo::partColsUpdated, PlannerInfo::plan_params, PlannerInfo::planner_cxt, preprocess_expression(), preprocess_qual_conditions(), preprocess_rowmarks(), PlannerInfo::processed_tlist, pull_up_sublinks(), pull_up_subqueries(), WithCheckOption::qual, PlannerInfo::qual_security_level, FromExpr::quals, PlannerInfo::query_level, reduce_outer_joins(), remove_useless_groupby_columns(), Query::resultRelation, Query::returningList, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, set_cheapest(), Query::setOperations, SS_assign_special_param(), SS_charge_for_initplans(), SS_identify_outer_params(), SS_process_ctes(), WindowClause::startOffset, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, Query::targetList, PlannerInfo::upper_rels, PlannerInfo::upper_targets, UPPERREL_FINAL, RangeTblEntry::values_lists, Query::windowClause, Query::withCheckOptions, and PlannerInfo::wt_param_id.

Referenced by make_subplan(), recurse_set_operations(), set_subquery_pathlist(), SS_process_ctes(), and standard_planner().

597 {
598  PlannerInfo *root;
599  List *newWithCheckOptions;
600  List *newHaving;
601  bool hasOuterJoins;
602  RelOptInfo *final_rel;
603  ListCell *l;
604 
605  /* Create a PlannerInfo data structure for this subquery */
606  root = makeNode(PlannerInfo);
607  root->parse = parse;
608  root->glob = glob;
609  root->query_level = parent_root ? parent_root->query_level + 1 : 1;
610  root->parent_root = parent_root;
611  root->plan_params = NIL;
612  root->outer_params = NULL;
614  root->init_plans = NIL;
615  root->cte_plan_ids = NIL;
616  root->multiexpr_params = NIL;
617  root->eq_classes = NIL;
618  root->append_rel_list = NIL;
619  root->rowMarks = NIL;
620  memset(root->upper_rels, 0, sizeof(root->upper_rels));
621  memset(root->upper_targets, 0, sizeof(root->upper_targets));
622  root->processed_tlist = NIL;
623  root->grouping_map = NULL;
624  root->minmax_aggs = NIL;
625  root->qual_security_level = 0;
626  root->inhTargetKind = INHKIND_NONE;
627  root->hasRecursion = hasRecursion;
628  if (hasRecursion)
629  root->wt_param_id = SS_assign_special_param(root);
630  else
631  root->wt_param_id = -1;
632  root->non_recursive_path = NULL;
633  root->partColsUpdated = false;
634 
635  /*
636  * If there is a WITH list, process each WITH query and build an initplan
637  * SubPlan structure for it.
638  */
639  if (parse->cteList)
640  SS_process_ctes(root);
641 
642  /*
643  * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
644  * to transform them into joins. Note that this step does not descend
645  * into subqueries; if we pull up any subqueries below, their SubLinks are
646  * processed just before pulling them up.
647  */
648  if (parse->hasSubLinks)
649  pull_up_sublinks(root);
650 
651  /*
652  * Scan the rangetable for set-returning functions, and inline them if
653  * possible (producing subqueries that might get pulled up next).
654  * Recursion issues here are handled in the same way as for SubLinks.
655  */
657 
658  /*
659  * Check to see if any subqueries in the jointree can be merged into this
660  * query.
661  */
662  pull_up_subqueries(root);
663 
664  /*
665  * If this is a simple UNION ALL query, flatten it into an appendrel. We
666  * do this now because it requires applying pull_up_subqueries to the leaf
667  * queries of the UNION ALL, which weren't touched above because they
668  * weren't referenced by the jointree (they will be after we do this).
669  */
670  if (parse->setOperations)
672 
673  /*
674  * Detect whether any rangetable entries are RTE_JOIN kind; if not, we can
675  * avoid the expense of doing flatten_join_alias_vars(). Also check for
676  * outer joins --- if none, we can skip reduce_outer_joins(). And check
677  * for LATERAL RTEs, too. This must be done after we have done
678  * pull_up_subqueries(), of course.
679  */
680  root->hasJoinRTEs = false;
681  root->hasLateralRTEs = false;
682  hasOuterJoins = false;
683  foreach(l, parse->rtable)
684  {
686 
687  if (rte->rtekind == RTE_JOIN)
688  {
689  root->hasJoinRTEs = true;
690  if (IS_OUTER_JOIN(rte->jointype))
691  hasOuterJoins = true;
692  }
693  if (rte->lateral)
694  root->hasLateralRTEs = true;
695  }
696 
697  /*
698  * Preprocess RowMark information. We need to do this after subquery
699  * pullup (so that all non-inherited RTEs are present) and before
700  * inheritance expansion (so that the info is available for
701  * expand_inherited_tables to examine and modify).
702  */
703  preprocess_rowmarks(root);
704 
705  /*
706  * Expand any rangetable entries that are inheritance sets into "append
707  * relations". This can add entries to the rangetable, but they must be
708  * plain base relations not joins, so it's OK (and marginally more
709  * efficient) to do it after checking for join RTEs. We must do it after
710  * pulling up subqueries, else we'd fail to handle inherited tables in
711  * subqueries.
712  */
714 
715  /*
716  * Set hasHavingQual to remember if HAVING clause is present. Needed
717  * because preprocess_expression will reduce a constant-true condition to
718  * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
719  */
720  root->hasHavingQual = (parse->havingQual != NULL);
721 
722  /* Clear this flag; might get set in distribute_qual_to_rels */
723  root->hasPseudoConstantQuals = false;
724 
725  /*
726  * Do expression preprocessing on targetlist and quals, as well as other
727  * random expressions in the querytree. Note that we do not need to
728  * handle sort/group expressions explicitly, because they are actually
729  * part of the targetlist.
730  */
731  parse->targetList = (List *)
732  preprocess_expression(root, (Node *) parse->targetList,
734 
735  /* Constant-folding might have removed all set-returning functions */
736  if (parse->hasTargetSRFs)
738 
739  newWithCheckOptions = NIL;
740  foreach(l, parse->withCheckOptions)
741  {
743 
744  wco->qual = preprocess_expression(root, wco->qual,
745  EXPRKIND_QUAL);
746  if (wco->qual != NULL)
747  newWithCheckOptions = lappend(newWithCheckOptions, wco);
748  }
749  parse->withCheckOptions = newWithCheckOptions;
750 
751  parse->returningList = (List *)
752  preprocess_expression(root, (Node *) parse->returningList,
754 
755  preprocess_qual_conditions(root, (Node *) parse->jointree);
756 
757  parse->havingQual = preprocess_expression(root, parse->havingQual,
758  EXPRKIND_QUAL);
759 
760  foreach(l, parse->windowClause)
761  {
763 
764  /* partitionClause/orderClause are sort/group expressions */
767  wc->endOffset = preprocess_expression(root, wc->endOffset,
769  }
770 
771  parse->limitOffset = preprocess_expression(root, parse->limitOffset,
773  parse->limitCount = preprocess_expression(root, parse->limitCount,
775 
776  if (parse->onConflict)
777  {
778  parse->onConflict->arbiterElems = (List *)
780  (Node *) parse->onConflict->arbiterElems,
782  parse->onConflict->arbiterWhere =
784  parse->onConflict->arbiterWhere,
785  EXPRKIND_QUAL);
786  parse->onConflict->onConflictSet = (List *)
788  (Node *) parse->onConflict->onConflictSet,
790  parse->onConflict->onConflictWhere =
792  parse->onConflict->onConflictWhere,
793  EXPRKIND_QUAL);
794  /* exclRelTlist contains only Vars, so no preprocessing needed */
795  }
796 
797  root->append_rel_list = (List *)
800 
801  /* Also need to preprocess expressions within RTEs */
802  foreach(l, parse->rtable)
803  {
805  int kind;
806  ListCell *lcsq;
807 
808  if (rte->rtekind == RTE_RELATION)
809  {
810  if (rte->tablesample)
811  rte->tablesample = (TableSampleClause *)
813  (Node *) rte->tablesample,
815  }
816  else if (rte->rtekind == RTE_SUBQUERY)
817  {
818  /*
819  * We don't want to do all preprocessing yet on the subquery's
820  * expressions, since that will happen when we plan it. But if it
821  * contains any join aliases of our level, those have to get
822  * expanded now, because planning of the subquery won't do it.
823  * That's only possible if the subquery is LATERAL.
824  */
825  if (rte->lateral && root->hasJoinRTEs)
826  rte->subquery = (Query *)
827  flatten_join_alias_vars(root, (Node *) rte->subquery);
828  }
829  else if (rte->rtekind == RTE_FUNCTION)
830  {
831  /* Preprocess the function expression(s) fully */
833  rte->functions = (List *)
834  preprocess_expression(root, (Node *) rte->functions, kind);
835  }
836  else if (rte->rtekind == RTE_TABLEFUNC)
837  {
838  /* Preprocess the function expression(s) fully */
840  rte->tablefunc = (TableFunc *)
841  preprocess_expression(root, (Node *) rte->tablefunc, kind);
842  }
843  else if (rte->rtekind == RTE_VALUES)
844  {
845  /* Preprocess the values lists fully */
847  rte->values_lists = (List *)
848  preprocess_expression(root, (Node *) rte->values_lists, kind);
849  }
850 
851  /*
852  * Process each element of the securityQuals list as if it were a
853  * separate qual expression (as indeed it is). We need to do it this
854  * way to get proper canonicalization of AND/OR structure. Note that
855  * this converts each element into an implicit-AND sublist.
856  */
857  foreach(lcsq, rte->securityQuals)
858  {
859  lfirst(lcsq) = preprocess_expression(root,
860  (Node *) lfirst(lcsq),
861  EXPRKIND_QUAL);
862  }
863  }
864 
865  /*
866  * Now that we are done preprocessing expressions, and in particular done
867  * flattening join alias variables, get rid of the joinaliasvars lists.
868  * They no longer match what expressions in the rest of the tree look
869  * like, because we have not preprocessed expressions in those lists (and
870  * do not want to; for example, expanding a SubLink there would result in
871  * a useless unreferenced subplan). Leaving them in place simply creates
872  * a hazard for later scans of the tree. We could try to prevent that by
873  * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
874  * but that doesn't sound very reliable.
875  */
876  if (root->hasJoinRTEs)
877  {
878  foreach(l, parse->rtable)
879  {
881 
882  rte->joinaliasvars = NIL;
883  }
884  }
885 
886  /*
887  * In some cases we may want to transfer a HAVING clause into WHERE. We
888  * cannot do so if the HAVING clause contains aggregates (obviously) or
889  * volatile functions (since a HAVING clause is supposed to be executed
890  * only once per group). We also can't do this if there are any nonempty
891  * grouping sets; moving such a clause into WHERE would potentially change
892  * the results, if any referenced column isn't present in all the grouping
893  * sets. (If there are only empty grouping sets, then the HAVING clause
894  * must be degenerate as discussed below.)
895  *
896  * Also, it may be that the clause is so expensive to execute that we're
897  * better off doing it only once per group, despite the loss of
898  * selectivity. This is hard to estimate short of doing the entire
899  * planning process twice, so we use a heuristic: clauses containing
900  * subplans are left in HAVING. Otherwise, we move or copy the HAVING
901  * clause into WHERE, in hopes of eliminating tuples before aggregation
902  * instead of after.
903  *
904  * If the query has explicit grouping then we can simply move such a
905  * clause into WHERE; any group that fails the clause will not be in the
906  * output because none of its tuples will reach the grouping or
907  * aggregation stage. Otherwise we must have a degenerate (variable-free)
908  * HAVING clause, which we put in WHERE so that query_planner() can use it
909  * in a gating Result node, but also keep in HAVING to ensure that we
910  * don't emit a bogus aggregated row. (This could be done better, but it
911  * seems not worth optimizing.)
912  *
913  * Note that both havingQual and parse->jointree->quals are in
914  * implicitly-ANDed-list form at this point, even though they are declared
915  * as Node *.
916  */
917  newHaving = NIL;
918  foreach(l, (List *) parse->havingQual)
919  {
920  Node *havingclause = (Node *) lfirst(l);
921 
922  if ((parse->groupClause && parse->groupingSets) ||
923  contain_agg_clause(havingclause) ||
924  contain_volatile_functions(havingclause) ||
925  contain_subplans(havingclause))
926  {
927  /* keep it in HAVING */
928  newHaving = lappend(newHaving, havingclause);
929  }
930  else if (parse->groupClause && !parse->groupingSets)
931  {
932  /* move it to WHERE */
933  parse->jointree->quals = (Node *)
934  lappend((List *) parse->jointree->quals, havingclause);
935  }
936  else
937  {
938  /* put a copy in WHERE, keep it in HAVING */
939  parse->jointree->quals = (Node *)
940  lappend((List *) parse->jointree->quals,
941  copyObject(havingclause));
942  newHaving = lappend(newHaving, havingclause);
943  }
944  }
945  parse->havingQual = (Node *) newHaving;
946 
947  /* Remove any redundant GROUP BY columns */
949 
950  /*
951  * If we have any outer joins, try to reduce them to plain inner joins.
952  * This step is most easily done after we've done expression
953  * preprocessing.
954  */
955  if (hasOuterJoins)
956  reduce_outer_joins(root);
957 
958  /*
959  * Do the main planning. If we have an inherited target relation, that
960  * needs special processing, else go straight to grouping_planner.
961  */
962  if (parse->resultRelation &&
963  rt_fetch(parse->resultRelation, parse->rtable)->inh)
964  inheritance_planner(root);
965  else
966  grouping_planner(root, false, tuple_fraction);
967 
968  /*
969  * Capture the set of outer-level param IDs we have access to, for use in
970  * extParam/allParam calculations later.
971  */
973 
974  /*
975  * If any initPlans were created in this query level, adjust the surviving
976  * Paths' costs and parallel-safety flags to account for them. The
977  * initPlans won't actually get attached to the plan tree till
978  * create_plan() runs, but we must include their effects now.
979  */
980  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
981  SS_charge_for_initplans(root, final_rel);
982 
983  /*
984  * Make sure we've identified the cheapest Path for the final rel. (By
985  * doing this here not in grouping_planner, we include initPlan costs in
986  * the decision, though it's unlikely that will change anything.)
987  */
988  set_cheapest(final_rel);
989 
990  return root;
991 }
Node * limitOffset
Definition: parsenodes.h:160
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:268
Query * parse
Definition: relation.h:169
List * joinaliasvars
Definition: parsenodes.h:1006
List * plan_params
Definition: relation.h:183
bool hasJoinRTEs
Definition: relation.h:315
#define EXPRKIND_ARBITER_ELEM
Definition: planner.c:85
void reduce_outer_joins(PlannerInfo *root)
FromExpr * jointree
Definition: parsenodes.h:138
int SS_assign_special_param(PlannerInfo *root)
Definition: subselect.c:429
OnConflictExpr * onConflict
Definition: parsenodes.h:144
static void preprocess_rowmarks(PlannerInfo *root)
Definition: planner.c:2502
List * securityQuals
Definition: parsenodes.h:1075
List * withCheckOptions
Definition: parsenodes.h:171
#define EXPRKIND_APPINFO
Definition: planner.c:82
#define EXPRKIND_QUAL
Definition: planner.c:75
#define EXPRKIND_TABLEFUNC_LATERAL
Definition: planner.c:87
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:670
int resultRelation
Definition: parsenodes.h:122
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
Definition: subselect.c:2170
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:730
#define EXPRKIND_RTFUNC
Definition: planner.c:77
List * groupingSets
Definition: parsenodes.h:150
Definition: nodes.h:517
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1000
List * minmax_aggs
Definition: relation.h:300
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:958
#define EXPRKIND_VALUES_LATERAL
Definition: planner.c:80
void expand_inherited_tables(PlannerInfo *root)
Definition: prepunion.c:1466
AttrNumber * grouping_map
Definition: relation.h:299
bool hasRecursion
Definition: relation.h:321
void pull_up_subqueries(PlannerInfo *root)
Definition: prepjointree.c:607
#define EXPRKIND_TARGET
Definition: planner.c:76
List * values_lists
Definition: parsenodes.h:1027
Node * quals
Definition: primnodes.h:1480
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * arbiterElems
Definition: primnodes.h:1498
List * multiexpr_params
Definition: relation.h:246
bool contain_subplans(Node *clause)
Definition: clauses.c:844
#define EXPRKIND_LIMIT
Definition: planner.c:81
int wt_param_id
Definition: relation.h:324
List * rtable
Definition: parsenodes.h:137
TableFunc * tablefunc
Definition: parsenodes.h:1022
bool hasLateralRTEs
Definition: relation.h:316
void inline_set_returning_functions(PlannerInfo *root)
Definition: prepjointree.c:573
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1145
#define lfirst_node(type, lc)
Definition: pg_list.h:109
static void remove_useless_groupby_columns(PlannerInfo *root)
Definition: planner.c:2921
Node * limitCount
Definition: parsenodes.h:161
PlannerGlobal * glob
Definition: relation.h:171
bool partColsUpdated
Definition: relation.h:335
JoinType jointype
Definition: parsenodes.h:1005
MemoryContext CurrentMemoryContext
Definition: mcxt.c:38
void SS_process_ctes(PlannerInfo *root)
Definition: subselect.c:1158
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:128
struct PlannerInfo * parent_root
Definition: relation.h:175
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:244
Node * startOffset
Definition: parsenodes.h:1306
Node * flatten_join_alias_vars(PlannerInfo *root, Node *node)
Definition: var.c:670
List * append_rel_list
Definition: relation.h:266
List * cte_plan_ids
Definition: relation.h:244
List * init_plans
Definition: relation.h:242
bool hasPseudoConstantQuals
Definition: relation.h:319
static void inheritance_planner(PlannerInfo *root)
Definition: planner.c:1156
bool hasTargetSRFs
Definition: parsenodes.h:127
#define makeNode(_type_)
Definition: nodes.h:565
#define lfirst(lc)
Definition: pg_list.h:106
void SS_identify_outer_params(PlannerInfo *root)
Definition: subselect.c:2108
List * eq_classes
Definition: relation.h:249
List * functions
Definition: parsenodes.h:1016
InheritanceKind inhTargetKind
Definition: relation.h:312
void flatten_simple_union_all(PlannerInfo *root)
Bitmapset * outer_params
Definition: relation.h:184
struct Path * non_recursive_path
Definition: relation.h:325
Node * endOffset
Definition: parsenodes.h:1307
#define EXPRKIND_RTFUNC_LATERAL
Definition: planner.c:78
Index qual_security_level
Definition: relation.h:309
Index query_level
Definition: relation.h:173
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:150
RTEKind rtekind
Definition: parsenodes.h:962
Node * arbiterWhere
Definition: primnodes.h:1500
List * cteList
Definition: parsenodes.h:135
Node * setOperations
Definition: parsenodes.h:165
bool contain_agg_clause(Node *clause)
Definition: clauses.c:418
Query * subquery
Definition: parsenodes.h:985
List * groupClause
Definition: parsenodes.h:148
bool hasSubLinks
Definition: parsenodes.h:128
static void grouping_planner(PlannerInfo *root, bool inheritance_update, double tuple_fraction)
Definition: planner.c:1665
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition: planner.c:1087
List * onConflictSet
Definition: primnodes.h:1504
bool hasHavingQual
Definition: relation.h:318
#define EXPRKIND_TABLESAMPLE
Definition: planner.c:84
MemoryContext planner_cxt
Definition: relation.h:302
#define copyObject(obj)
Definition: nodes.h:630
#define EXPRKIND_VALUES
Definition: planner.c:79
Node * havingQual
Definition: parsenodes.h:152
List * processed_tlist
Definition: relation.h:296
Node * onConflictWhere
Definition: primnodes.h:1505
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:980
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649
struct PathTarget * upper_targets[UPPERREL_FINAL+1]
Definition: relation.h:290
#define EXPRKIND_TABLEFUNC
Definition: planner.c:86
List * upper_rels[UPPERREL_FINAL+1]
Definition: relation.h:287

Variable Documentation

◆ create_upper_paths_hook

◆ planner_hook

Definition at line 68 of file planner.c.

Referenced by planner().