PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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)
 

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)
 

Variables

PGDLLIMPORT planner_hook_type planner_hook
 
PGDLLIMPORT
create_upper_paths_hook_type 
create_upper_paths_hook
 

Typedef Documentation

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

Definition at line 28 of file planner.h.

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

Definition at line 22 of file planner.h.

Function Documentation

Expr* expression_planner ( Expr expr)

Definition at line 5212 of file planner.c.

References eval_const_expressions(), fix_opfuncids(), and NULL.

Referenced by ATExecAddColumn(), ATPrepAlterColumnType(), BeginCopyFrom(), CheckMutability(), ComputePartitionAttrs(), ExecPrepareExpr(), get_cast_hashentry(), load_domaintype_info(), slot_fill_defaults(), and transformPartitionBound().

5213 {
5214  Node *result;
5215 
5216  /*
5217  * Convert named-argument function calls, insert default arguments and
5218  * simplify constant subexprs
5219  */
5220  result = eval_const_expressions(NULL, (Node *) expr);
5221 
5222  /* Fill in opfuncid values if missing */
5223  fix_opfuncids(result);
5224 
5225  return (Expr *) result;
5226 }
void fix_opfuncids(Node *node)
Definition: nodeFuncs.c:1596
Definition: nodes.h:508
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2366
#define NULL
Definition: c.h:226
Path* get_cheapest_fractional_path ( RelOptInfo rel,
double  tuple_fraction 
)

Definition at line 5059 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().

5060 {
5061  Path *best_path = rel->cheapest_total_path;
5062  ListCell *l;
5063 
5064  /* If all tuples will be retrieved, just return the cheapest-total path */
5065  if (tuple_fraction <= 0.0)
5066  return best_path;
5067 
5068  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
5069  if (tuple_fraction >= 1.0 && best_path->rows > 0)
5070  tuple_fraction /= best_path->rows;
5071 
5072  foreach(l, rel->pathlist)
5073  {
5074  Path *path = (Path *) lfirst(l);
5075 
5076  if (path == rel->cheapest_total_path ||
5077  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
5078  continue;
5079 
5080  best_path = path;
5081  }
5082 
5083  return best_path;
5084 }
struct Path * cheapest_total_path
Definition: relation.h:508
#define lfirst(lc)
Definition: pg_list.h:106
double rows
Definition: relation.h:905
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:107
List * pathlist
Definition: relation.h:504
Definition: relation.h:888
bool is_dummy_plan ( Plan plan)

Definition at line 2080 of file planner.c.

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

2081 {
2082  if (IsA(plan, Result))
2083  {
2084  List *rcqual = (List *) ((Result *) plan)->resconstantqual;
2085 
2086  if (list_length(rcqual) == 1)
2087  {
2088  Const *constqual = (Const *) linitial(rcqual);
2089 
2090  if (constqual && IsA(constqual, Const))
2091  {
2092  if (!constqual->constisnull &&
2093  !DatumGetBool(constqual->constvalue))
2094  return true;
2095  }
2096  }
2097  }
2098  return false;
2099 }
Datum constvalue
Definition: primnodes.h:174
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
#define linitial(l)
Definition: pg_list.h:110
#define DatumGetBool(X)
Definition: postgres.h:401
static int list_length(const List *l)
Definition: pg_list.h:89
Definition: pg_list.h:45
bool constisnull
Definition: primnodes.h:175
void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)

Definition at line 4508 of file planner.c.

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

Referenced by convert_combining_aggrefs(), and make_partial_grouping_target().

4509 {
4510  /* aggtranstype should be computed by this point */
4512  /* ... but aggsplit should still be as the parser left it */
4513  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
4514 
4515  /* Mark the Aggref with the intended partial-aggregation mode */
4516  agg->aggsplit = aggsplit;
4517 
4518  /*
4519  * Adjust result type if needed. Normally, a partial aggregate returns
4520  * the aggregate's transition type; but if that's INTERNAL and we're
4521  * serializing, it returns BYTEA instead.
4522  */
4523  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
4524  {
4525  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
4526  agg->aggtype = BYTEAOID;
4527  else
4528  agg->aggtype = agg->aggtranstype;
4529  }
4530 }
#define OidIsValid(objectId)
Definition: c.h:533
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:761
#define INTERNALOID
Definition: pg_type.h:686
#define Assert(condition)
Definition: c.h:670
AggSplit aggsplit
Definition: primnodes.h:288
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:760
#define BYTEAOID
Definition: pg_type.h:292
Oid aggtranstype
Definition: primnodes.h:276
Oid aggtype
Definition: primnodes.h:273
bool plan_cluster_use_sort ( Oid  tableOid,
Oid  indexOid 
)

Definition at line 5241 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, list_make1, maintenance_work_mem, makeNode, NIL, NULL, RelOptInfo::pages, PlannerInfo::parse, IndexPath::path, QualCost::per_tuple, PlannerInfo::planner_cxt, PlannerInfo::query_level, RangeTblEntry::relid, RangeTblEntry::relkind, RELKIND_RELATION, RELOPT_BASEREL, 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().

5242 {
5243  PlannerInfo *root;
5244  Query *query;
5245  PlannerGlobal *glob;
5246  RangeTblEntry *rte;
5247  RelOptInfo *rel;
5248  IndexOptInfo *indexInfo;
5249  QualCost indexExprCost;
5250  Cost comparisonCost;
5251  Path *seqScanPath;
5252  Path seqScanAndSortPath;
5253  IndexPath *indexScanPath;
5254  ListCell *lc;
5255 
5256  /* We can short-circuit the cost comparison if indexscans are disabled */
5257  if (!enable_indexscan)
5258  return true; /* use sort */
5259 
5260  /* Set up mostly-dummy planner state */
5261  query = makeNode(Query);
5262  query->commandType = CMD_SELECT;
5263 
5264  glob = makeNode(PlannerGlobal);
5265 
5266  root = makeNode(PlannerInfo);
5267  root->parse = query;
5268  root->glob = glob;
5269  root->query_level = 1;
5271  root->wt_param_id = -1;
5272 
5273  /* Build a minimal RTE for the rel */
5274  rte = makeNode(RangeTblEntry);
5275  rte->rtekind = RTE_RELATION;
5276  rte->relid = tableOid;
5277  rte->relkind = RELKIND_RELATION; /* Don't be too picky. */
5278  rte->lateral = false;
5279  rte->inh = false;
5280  rte->inFromCl = true;
5281  query->rtable = list_make1(rte);
5282 
5283  /* Set up RTE/RelOptInfo arrays */
5285 
5286  /* Build RelOptInfo */
5287  rel = build_simple_rel(root, 1, RELOPT_BASEREL);
5288 
5289  /* Locate IndexOptInfo for the target index */
5290  indexInfo = NULL;
5291  foreach(lc, rel->indexlist)
5292  {
5293  indexInfo = (IndexOptInfo *) lfirst(lc);
5294  if (indexInfo->indexoid == indexOid)
5295  break;
5296  }
5297 
5298  /*
5299  * It's possible that get_relation_info did not generate an IndexOptInfo
5300  * for the desired index; this could happen if it's not yet reached its
5301  * indcheckxmin usability horizon, or if it's a system index and we're
5302  * ignoring system indexes. In such cases we should tell CLUSTER to not
5303  * trust the index contents but use seqscan-and-sort.
5304  */
5305  if (lc == NULL) /* not in the list? */
5306  return true; /* use sort */
5307 
5308  /*
5309  * Rather than doing all the pushups that would be needed to use
5310  * set_baserel_size_estimates, just do a quick hack for rows and width.
5311  */
5312  rel->rows = rel->tuples;
5313  rel->reltarget->width = get_relation_data_width(tableOid, NULL);
5314 
5315  root->total_table_pages = rel->pages;
5316 
5317  /*
5318  * Determine eval cost of the index expressions, if any. We need to
5319  * charge twice that amount for each tuple comparison that happens during
5320  * the sort, since tuplesort.c will have to re-evaluate the index
5321  * expressions each time. (XXX that's pretty inefficient...)
5322  */
5323  cost_qual_eval(&indexExprCost, indexInfo->indexprs, root);
5324  comparisonCost = 2.0 * (indexExprCost.startup + indexExprCost.per_tuple);
5325 
5326  /* Estimate the cost of seq scan + sort */
5327  seqScanPath = create_seqscan_path(root, rel, NULL, 0);
5328  cost_sort(&seqScanAndSortPath, root, NIL,
5329  seqScanPath->total_cost, rel->tuples, rel->reltarget->width,
5330  comparisonCost, maintenance_work_mem, -1.0);
5331 
5332  /* Estimate the cost of index scan */
5333  indexScanPath = create_index_path(root, indexInfo,
5334  NIL, NIL, NIL, NIL, NIL,
5335  ForwardScanDirection, false,
5336  NULL, 1.0, false);
5337 
5338  return (seqScanAndSortPath.total_cost < indexScanPath->path.total_cost);
5339 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
Path path
Definition: relation.h:971
double tuples
Definition: relation.h:529
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:1008
Cost startup
Definition: relation.h:45
#define list_make1(x1)
Definition: pg_list.h:133
Cost per_tuple
Definition: relation.h:46
int wt_param_id
Definition: relation.h:303
List * rtable
Definition: parsenodes.h:128
void cost_qual_eval(QualCost *cost, List *quals, PlannerInfo *root)
Definition: costsize.c:3204
PlannerGlobal * glob
Definition: relation.h:154
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
double total_table_pages
Definition: relation.h:284
int32 get_relation_data_width(Oid relid, int32 *attr_widths)
Definition: plancat.c:1103
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:1463
List * indexlist
Definition: relation.h:527
double rows
Definition: relation.h:493
RelOptInfo * build_simple_rel(PlannerInfo *root, int relid, RelOptKind reloptkind)
Definition: relnode.c:88
int maintenance_work_mem
Definition: globals.c:113
Cost total_cost
Definition: relation.h:907
CmdType commandType
Definition: parsenodes.h:103
#define makeNode(_type_)
Definition: nodes.h:556
BlockNumber pages
Definition: relation.h:528
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:59
Index query_level
Definition: relation.h:156
RTEKind rtekind
Definition: parsenodes.h:882
int width
Definition: relation.h:827
MemoryContext planner_cxt
Definition: relation.h:282
Oid indexoid
Definition: relation.h:588
#define RELKIND_RELATION
Definition: pg_class.h:160
struct PathTarget * reltarget
Definition: relation.h:501
bool enable_indexscan
Definition: costsize.c:119
Path * create_seqscan_path(PlannerInfo *root, RelOptInfo *rel, Relids required_outer, int parallel_workers)
Definition: pathnode.c:938
Definition: relation.h:888
double Cost
Definition: nodes.h:632
List * indexprs
Definition: relation.h:610
PlannedStmt* planner ( Query parse,
int  cursorOptions,
ParamListInfo  boundParams 
)

Definition at line 174 of file planner.c.

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

Referenced by pg_plan_query().

175 {
176  PlannedStmt *result;
177 
178  if (planner_hook)
179  result = (*planner_hook) (parse, cursorOptions, boundParams);
180  else
181  result = standard_planner(parse, cursorOptions, boundParams);
182  return result;
183 }
PlannedStmt * standard_planner(Query *parse, int cursorOptions, ParamListInfo boundParams)
Definition: planner.c:186
planner_hook_type planner_hook
Definition: planner.c:65
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
Expr* preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)

Definition at line 955 of file planner.c.

References EXPRKIND_PHV, and preprocess_expression().

Referenced by extract_lateral_references().

956 {
957  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
958 }
Definition: nodes.h:508
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:826
#define EXPRKIND_PHV
Definition: planner.c:80
RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)

Definition at line 2216 of file planner.c.

References elog, ERROR, GetFdwRoutineByRelId(), FdwRoutine::GetForeignRowMarkType, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, LCS_NONE, NULL, RangeTblEntry::relid, RangeTblEntry::relkind, RELKIND_FOREIGN_TABLE, 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_inherited_rtentry(), and preprocess_rowmarks().

2217 {
2218  if (rte->rtekind != RTE_RELATION)
2219  {
2220  /* If it's not a table at all, use ROW_MARK_COPY */
2221  return ROW_MARK_COPY;
2222  }
2223  else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2224  {
2225  /* Let the FDW select the rowmark type, if it wants to */
2226  FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2227 
2228  if (fdwroutine->GetForeignRowMarkType != NULL)
2229  return fdwroutine->GetForeignRowMarkType(rte, strength);
2230  /* Otherwise, use ROW_MARK_COPY by default */
2231  return ROW_MARK_COPY;
2232  }
2233  else
2234  {
2235  /* Regular table, apply the appropriate lock type */
2236  switch (strength)
2237  {
2238  case LCS_NONE:
2239 
2240  /*
2241  * We don't need a tuple lock, only the ability to re-fetch
2242  * the row.
2243  */
2244  return ROW_MARK_REFERENCE;
2245  break;
2246  case LCS_FORKEYSHARE:
2247  return ROW_MARK_KEYSHARE;
2248  break;
2249  case LCS_FORSHARE:
2250  return ROW_MARK_SHARE;
2251  break;
2252  case LCS_FORNOKEYUPDATE:
2253  return ROW_MARK_NOKEYEXCLUSIVE;
2254  break;
2255  case LCS_FORUPDATE:
2256  return ROW_MARK_EXCLUSIVE;
2257  break;
2258  }
2259  elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2260  return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2261  }
2262 }
#define ERROR
Definition: elog.h:43
#define RELKIND_FOREIGN_TABLE
Definition: pg_class.h:166
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:372
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:207
#define NULL
Definition: c.h:226
RTEKind rtekind
Definition: parsenodes.h:882
#define elog
Definition: elog.h:219
PlannedStmt* standard_planner ( Query parse,
int  cursorOptions,
ParamListInfo  boundParams 
)

Definition at line 186 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, PlannedStmt::invalItems, PlannerGlobal::invalItems, Gather::invisible, IsolationIsSerializable, IsParallelWorker, IsUnderPostmaster, PlannerGlobal::lastPHId, PlannerGlobal::lastPlanNodeId, PlannerGlobal::lastRowMarkId, Plan::lefttree, lfirst, list_length(), makeNode, materialize_finished_plan(), max_parallel_hazard(), max_parallel_workers_per_gather, PlannerGlobal::maxParallelHazard, NIL, PlannedStmt::nParamExec, PlannerGlobal::nParamExec, NULL, Gather::num_workers, Plan::parallel_aware, Path::parallel_safe, parallel_setup_cost, parallel_tuple_cost, PlannedStmt::parallelModeNeeded, PlannerGlobal::parallelModeNeeded, PlannerGlobal::parallelModeOK, Gather::plan, Plan::plan_rows, Plan::plan_width, PlannedStmt::planTree, PROPARALLEL_UNSAFE, Plan::qual, PlannedStmt::queryId, Query::queryId, PlannedStmt::relationOids, PlannerGlobal::relationOids, PlannedStmt::resultRelations, PlannerGlobal::resultRelations, Query::returningList, PlannedStmt::rewindPlanIDs, PlannerGlobal::rewindPlanIDs, Plan::righttree, 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().

187 {
188  PlannedStmt *result;
189  PlannerGlobal *glob;
190  double tuple_fraction;
191  PlannerInfo *root;
192  RelOptInfo *final_rel;
193  Path *best_path;
194  Plan *top_plan;
195  ListCell *lp,
196  *lr;
197 
198  /*
199  * Set up global state for this planner invocation. This data is needed
200  * across all levels of sub-Query that might exist in the given command,
201  * so we keep it in a separate struct that's linked to by each per-Query
202  * PlannerInfo.
203  */
204  glob = makeNode(PlannerGlobal);
205 
206  glob->boundParams = boundParams;
207  glob->subplans = NIL;
208  glob->subroots = NIL;
209  glob->rewindPlanIDs = NULL;
210  glob->finalrtable = NIL;
211  glob->finalrowmarks = NIL;
212  glob->resultRelations = NIL;
213  glob->relationOids = NIL;
214  glob->invalItems = NIL;
215  glob->nParamExec = 0;
216  glob->lastPHId = 0;
217  glob->lastRowMarkId = 0;
218  glob->lastPlanNodeId = 0;
219  glob->transientPlan = false;
220  glob->dependsOnRole = false;
221 
222  /*
223  * Assess whether it's feasible to use parallel mode for this query. We
224  * can't do this in a standalone backend, or if the command will try to
225  * modify any data, or if this is a cursor operation, or if GUCs are set
226  * to values that don't permit parallelism, or if parallel-unsafe
227  * functions are present in the query tree.
228  *
229  * For now, we don't try to use parallel mode if we're running inside a
230  * parallel worker. We might eventually be able to relax this
231  * restriction, but for now it seems best not to have parallel workers
232  * trying to create their own parallel workers.
233  *
234  * We can't use parallelism in serializable mode because the predicate
235  * locking code is not parallel-aware. It's not catastrophic if someone
236  * tries to run a parallel plan in serializable mode; it just won't get
237  * any workers and will run serially. But it seems like a good heuristic
238  * to assume that the same serialization level will be in effect at plan
239  * time and execution time, so don't generate a parallel plan if we're in
240  * serializable mode.
241  */
242  if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
245  parse->commandType == CMD_SELECT &&
246  !parse->hasModifyingCTE &&
248  !IsParallelWorker() &&
250  {
251  /* all the cheap tests pass, so scan the query tree */
252  glob->maxParallelHazard = max_parallel_hazard(parse);
254  }
255  else
256  {
257  /* skip the query tree scan, just assume it's unsafe */
259  glob->parallelModeOK = false;
260  }
261 
262  /*
263  * glob->parallelModeNeeded should tell us whether it's necessary to
264  * impose the parallel mode restrictions, but we don't actually want to
265  * impose them unless we choose a parallel plan, so it is normally set
266  * only if a parallel plan is chosen (see create_gather_plan). That way,
267  * people who mislabel their functions but don't use parallelism anyway
268  * aren't harmed. But when force_parallel_mode is set, we enable the
269  * restrictions whenever possible for testing purposes.
270  */
271  glob->parallelModeNeeded = glob->parallelModeOK &&
273 
274  /* Determine what fraction of the plan is likely to be scanned */
275  if (cursorOptions & CURSOR_OPT_FAST_PLAN)
276  {
277  /*
278  * We have no real idea how many tuples the user will ultimately FETCH
279  * from a cursor, but it is often the case that he doesn't want 'em
280  * all, or would prefer a fast-start plan anyway so that he can
281  * process some of the tuples sooner. Use a GUC parameter to decide
282  * what fraction to optimize for.
283  */
284  tuple_fraction = cursor_tuple_fraction;
285 
286  /*
287  * We document cursor_tuple_fraction as simply being a fraction, which
288  * means the edge cases 0 and 1 have to be treated specially here. We
289  * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
290  */
291  if (tuple_fraction >= 1.0)
292  tuple_fraction = 0.0;
293  else if (tuple_fraction <= 0.0)
294  tuple_fraction = 1e-10;
295  }
296  else
297  {
298  /* Default assumption is we need all the tuples */
299  tuple_fraction = 0.0;
300  }
301 
302  /* primary planning entry point (may recurse for subqueries) */
303  root = subquery_planner(glob, parse, NULL,
304  false, tuple_fraction);
305 
306  /* Select best Path and turn it into a Plan */
307  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
308  best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
309 
310  top_plan = create_plan(root, best_path);
311 
312  /*
313  * If creating a plan for a scrollable cursor, make sure it can run
314  * backwards on demand. Add a Material node at the top at need.
315  */
316  if (cursorOptions & CURSOR_OPT_SCROLL)
317  {
318  if (!ExecSupportsBackwardScan(top_plan))
319  top_plan = materialize_finished_plan(top_plan);
320  }
321 
322  /*
323  * Optionally add a Gather node for testing purposes, provided this is
324  * actually a safe thing to do. (Note: we assume adding a Material node
325  * above did not change the parallel safety of the plan, so we can still
326  * rely on best_path->parallel_safe.)
327  */
329  {
330  Gather *gather = makeNode(Gather);
331 
332  gather->plan.targetlist = top_plan->targetlist;
333  gather->plan.qual = NIL;
334  gather->plan.lefttree = top_plan;
335  gather->plan.righttree = NULL;
336  gather->num_workers = 1;
337  gather->single_copy = true;
339 
340  /*
341  * Ideally we'd use cost_gather here, but setting up dummy path data
342  * to satisfy it doesn't seem much cleaner than knowing what it does.
343  */
344  gather->plan.startup_cost = top_plan->startup_cost +
346  gather->plan.total_cost = top_plan->total_cost +
348  gather->plan.plan_rows = top_plan->plan_rows;
349  gather->plan.plan_width = top_plan->plan_width;
350  gather->plan.parallel_aware = false;
351 
352  /* use parallel mode for parallel plans. */
353  root->glob->parallelModeNeeded = true;
354 
355  top_plan = &gather->plan;
356  }
357 
358  /*
359  * If any Params were generated, run through the plan tree and compute
360  * each plan node's extParam/allParam sets. Ideally we'd merge this into
361  * set_plan_references' tree traversal, but for now it has to be separate
362  * because we need to visit subplans before not after main plan.
363  */
364  if (glob->nParamExec > 0)
365  {
366  Assert(list_length(glob->subplans) == list_length(glob->subroots));
367  forboth(lp, glob->subplans, lr, glob->subroots)
368  {
369  Plan *subplan = (Plan *) lfirst(lp);
370  PlannerInfo *subroot = (PlannerInfo *) lfirst(lr);
371 
372  SS_finalize_plan(subroot, subplan);
373  }
374  SS_finalize_plan(root, top_plan);
375  }
376 
377  /* final cleanup of the plan */
378  Assert(glob->finalrtable == NIL);
379  Assert(glob->finalrowmarks == NIL);
380  Assert(glob->resultRelations == NIL);
381  top_plan = set_plan_references(root, top_plan);
382  /* ... and the subplans (both regular subplans and initplans) */
383  Assert(list_length(glob->subplans) == list_length(glob->subroots));
384  forboth(lp, glob->subplans, lr, glob->subroots)
385  {
386  Plan *subplan = (Plan *) lfirst(lp);
387  PlannerInfo *subroot = (PlannerInfo *) lfirst(lr);
388 
389  lfirst(lp) = set_plan_references(subroot, subplan);
390  }
391 
392  /* build the PlannedStmt result */
393  result = makeNode(PlannedStmt);
394 
395  result->commandType = parse->commandType;
396  result->queryId = parse->queryId;
397  result->hasReturning = (parse->returningList != NIL);
398  result->hasModifyingCTE = parse->hasModifyingCTE;
399  result->canSetTag = parse->canSetTag;
400  result->transientPlan = glob->transientPlan;
401  result->dependsOnRole = glob->dependsOnRole;
402  result->parallelModeNeeded = glob->parallelModeNeeded;
403  result->planTree = top_plan;
404  result->rtable = glob->finalrtable;
405  result->resultRelations = glob->resultRelations;
406  result->subplans = glob->subplans;
407  result->rewindPlanIDs = glob->rewindPlanIDs;
408  result->rowMarks = glob->finalrowmarks;
409  result->relationOids = glob->relationOids;
410  result->invalItems = glob->invalItems;
411  result->nParamExec = glob->nParamExec;
412  /* utilityStmt should be null, but we might as well copy it */
413  result->utilityStmt = parse->utilityStmt;
414  result->stmt_location = parse->stmt_location;
415  result->stmt_len = parse->stmt_len;
416 
417  return result;
418 }
char maxParallelHazard
Definition: relation.h:130
bool dependsOnRole
Definition: plannodes.h:57
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:130
uint32 queryId
Definition: parsenodes.h:107
double plan_rows
Definition: plannodes.h:117
uint32 queryId
Definition: plannodes.h:47
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
int stmt_location
Definition: parsenodes.h:171
List * relationOids
Definition: plannodes.h:74
int lastPlanNodeId
Definition: relation.h:120
List * resultRelations
Definition: relation.h:108
double parallel_setup_cost
Definition: costsize.c:110
Node * utilityStmt
Definition: parsenodes.h:111
bool transientPlan
Definition: plannodes.h:55
int stmt_len
Definition: plannodes.h:84
char max_parallel_hazard(Query *parse)
Definition: clauses.c:1053
struct Plan * planTree
Definition: plannodes.h:61
List * invalItems
Definition: plannodes.h:76
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:293
bool dependsOnRole
Definition: relation.h:124
int nParamExec
Definition: plannodes.h:78
struct Plan * righttree
Definition: plannodes.h:132
bool parallelModeNeeded
Definition: relation.h:128
Plan plan
Definition: plannodes.h:782
bool single_copy
Definition: plannodes.h:784
bool parallelModeOK
Definition: relation.h:126
Bitmapset * rewindPlanIDs
Definition: relation.h:102
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
int stmt_location
Definition: plannodes.h:83
List * subplans
Definition: relation.h:98
Cost startup_cost
Definition: plannodes.h:111
PlannerGlobal * glob
Definition: relation.h:154
bool IsUnderPostmaster
Definition: globals.c:100
bool hasReturning
Definition: plannodes.h:49
Plan * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:5700
Node * utilityStmt
Definition: plannodes.h:80
int dynamic_shared_memory_type
Definition: dsm_impl.c:112
bool parallel_aware
Definition: plannodes.h:123
double cursor_tuple_fraction
Definition: planner.c:61
List * returningList
Definition: parsenodes.h:135
#define IsParallelWorker()
Definition: parallel.h:53
#define PROPARALLEL_UNSAFE
Definition: pg_proc.h:5383
List * invalItems
Definition: relation.h:112
bool canSetTag
Definition: plannodes.h:53
CmdType commandType
Definition: plannodes.h:45
#define CURSOR_OPT_FAST_PLAN
Definition: parsenodes.h:2525
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:446
Index lastPHId
Definition: relation.h:116
List * rowMarks
Definition: plannodes.h:72
int num_workers
Definition: plannodes.h:783
CmdType commandType
Definition: parsenodes.h:103
#define makeNode(_type_)
Definition: nodes.h:556
List * subplans
Definition: plannodes.h:68
int plan_width
Definition: plannodes.h:118
#define NULL
Definition: c.h:226
int force_parallel_mode
Definition: planner.c:62
ParamListInfo boundParams
Definition: relation.h:96
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * rewindPlanIDs
Definition: plannodes.h:70
bool hasModifyingCTE
Definition: plannodes.h:51
bool parallel_safe
Definition: relation.h:900
bool canSetTag
Definition: parsenodes.h:109
#define DSM_IMPL_NONE
Definition: dsm_impl.h:17
static int list_length(const List *l)
Definition: pg_list.h:89
List * relationOids
Definition: relation.h:110
List * subroots
Definition: relation.h:100
List * rtable
Definition: plannodes.h:63
struct Plan * lefttree
Definition: plannodes.h:131
List * targetlist
Definition: plannodes.h:129
bool invisible
Definition: plannodes.h:785
e
Definition: preproc-init.c:82
List * finalrtable
Definition: relation.h:104
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2528
Index lastRowMarkId
Definition: relation.h:118
#define IsolationIsSerializable()
Definition: xact.h:44
List * resultRelations
Definition: plannodes.h:66
bool parallelModeNeeded
Definition: plannodes.h:59
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2520
Cost total_cost
Definition: plannodes.h:112
int nParamExec
Definition: relation.h:114
bool hasModifyingCTE
Definition: parsenodes.h:122
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:209
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2219
int max_parallel_workers_per_gather
Definition: costsize.c:116
List * finalrowmarks
Definition: relation.h:106
int stmt_len
Definition: parsenodes.h:172
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
Definition: planner.c:450
Definition: relation.h:888
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition: planner.c:5059
bool transientPlan
Definition: relation.h:122
double parallel_tuple_cost
Definition: costsize.c:109
PlannerInfo* subquery_planner ( PlannerGlobal glob,
Query parse,
PlannerInfo parent_root,
bool  hasRecursion,
double  tuple_fraction 
)

Definition at line 450 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_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::hasInheritedTarget, PlannerInfo::hasJoinRTEs, PlannerInfo::hasLateralRTEs, PlannerInfo::hasPseudoConstantQuals, PlannerInfo::hasRecursion, Query::hasSubLinks, Query::hasTargetSRFs, Query::havingQual, inheritance_planner(), PlannerInfo::init_plans, inline_set_returning_functions(), IS_OUTER_JOIN, Query::jointree, RangeTblEntry::jointype, lappend(), RangeTblEntry::lateral, lfirst, Query::limitCount, Query::limitOffset, makeNode, PlannerInfo::minmax_aggs, PlannerInfo::multiexpr_params, NIL, PlannerInfo::non_recursive_path, NULL, Query::onConflict, OnConflictExpr::onConflictSet, OnConflictExpr::onConflictWhere, PlannerInfo::outer_params, PlannerInfo::parent_root, parse(), PlannerInfo::parse, 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_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::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().

453 {
454  PlannerInfo *root;
455  List *newWithCheckOptions;
456  List *newHaving;
457  bool hasOuterJoins;
458  RelOptInfo *final_rel;
459  ListCell *l;
460 
461  /* Create a PlannerInfo data structure for this subquery */
462  root = makeNode(PlannerInfo);
463  root->parse = parse;
464  root->glob = glob;
465  root->query_level = parent_root ? parent_root->query_level + 1 : 1;
466  root->parent_root = parent_root;
467  root->plan_params = NIL;
468  root->outer_params = NULL;
470  root->init_plans = NIL;
471  root->cte_plan_ids = NIL;
472  root->multiexpr_params = NIL;
473  root->eq_classes = NIL;
474  root->append_rel_list = NIL;
475  root->rowMarks = NIL;
476  memset(root->upper_rels, 0, sizeof(root->upper_rels));
477  memset(root->upper_targets, 0, sizeof(root->upper_targets));
478  root->processed_tlist = NIL;
479  root->grouping_map = NULL;
480  root->minmax_aggs = NIL;
481  root->qual_security_level = 0;
482  root->hasInheritedTarget = false;
483  root->hasRecursion = hasRecursion;
484  if (hasRecursion)
485  root->wt_param_id = SS_assign_special_param(root);
486  else
487  root->wt_param_id = -1;
488  root->non_recursive_path = NULL;
489 
490  /*
491  * If there is a WITH list, process each WITH query and build an initplan
492  * SubPlan structure for it.
493  */
494  if (parse->cteList)
495  SS_process_ctes(root);
496 
497  /*
498  * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
499  * to transform them into joins. Note that this step does not descend
500  * into subqueries; if we pull up any subqueries below, their SubLinks are
501  * processed just before pulling them up.
502  */
503  if (parse->hasSubLinks)
504  pull_up_sublinks(root);
505 
506  /*
507  * Scan the rangetable for set-returning functions, and inline them if
508  * possible (producing subqueries that might get pulled up next).
509  * Recursion issues here are handled in the same way as for SubLinks.
510  */
512 
513  /*
514  * Check to see if any subqueries in the jointree can be merged into this
515  * query.
516  */
517  pull_up_subqueries(root);
518 
519  /*
520  * If this is a simple UNION ALL query, flatten it into an appendrel. We
521  * do this now because it requires applying pull_up_subqueries to the leaf
522  * queries of the UNION ALL, which weren't touched above because they
523  * weren't referenced by the jointree (they will be after we do this).
524  */
525  if (parse->setOperations)
527 
528  /*
529  * Detect whether any rangetable entries are RTE_JOIN kind; if not, we can
530  * avoid the expense of doing flatten_join_alias_vars(). Also check for
531  * outer joins --- if none, we can skip reduce_outer_joins(). And check
532  * for LATERAL RTEs, too. This must be done after we have done
533  * pull_up_subqueries(), of course.
534  */
535  root->hasJoinRTEs = false;
536  root->hasLateralRTEs = false;
537  hasOuterJoins = false;
538  foreach(l, parse->rtable)
539  {
540  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
541 
542  if (rte->rtekind == RTE_JOIN)
543  {
544  root->hasJoinRTEs = true;
545  if (IS_OUTER_JOIN(rte->jointype))
546  hasOuterJoins = true;
547  }
548  if (rte->lateral)
549  root->hasLateralRTEs = true;
550  }
551 
552  /*
553  * Preprocess RowMark information. We need to do this after subquery
554  * pullup (so that all non-inherited RTEs are present) and before
555  * inheritance expansion (so that the info is available for
556  * expand_inherited_tables to examine and modify).
557  */
558  preprocess_rowmarks(root);
559 
560  /*
561  * Expand any rangetable entries that are inheritance sets into "append
562  * relations". This can add entries to the rangetable, but they must be
563  * plain base relations not joins, so it's OK (and marginally more
564  * efficient) to do it after checking for join RTEs. We must do it after
565  * pulling up subqueries, else we'd fail to handle inherited tables in
566  * subqueries.
567  */
569 
570  /*
571  * Set hasHavingQual to remember if HAVING clause is present. Needed
572  * because preprocess_expression will reduce a constant-true condition to
573  * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
574  */
575  root->hasHavingQual = (parse->havingQual != NULL);
576 
577  /* Clear this flag; might get set in distribute_qual_to_rels */
578  root->hasPseudoConstantQuals = false;
579 
580  /*
581  * Do expression preprocessing on targetlist and quals, as well as other
582  * random expressions in the querytree. Note that we do not need to
583  * handle sort/group expressions explicitly, because they are actually
584  * part of the targetlist.
585  */
586  parse->targetList = (List *)
587  preprocess_expression(root, (Node *) parse->targetList,
589 
590  /* Constant-folding might have removed all set-returning functions */
591  if (parse->hasTargetSRFs)
593 
594  newWithCheckOptions = NIL;
595  foreach(l, parse->withCheckOptions)
596  {
597  WithCheckOption *wco = (WithCheckOption *) lfirst(l);
598 
599  wco->qual = preprocess_expression(root, wco->qual,
600  EXPRKIND_QUAL);
601  if (wco->qual != NULL)
602  newWithCheckOptions = lappend(newWithCheckOptions, wco);
603  }
604  parse->withCheckOptions = newWithCheckOptions;
605 
606  parse->returningList = (List *)
607  preprocess_expression(root, (Node *) parse->returningList,
609 
610  preprocess_qual_conditions(root, (Node *) parse->jointree);
611 
612  parse->havingQual = preprocess_expression(root, parse->havingQual,
613  EXPRKIND_QUAL);
614 
615  foreach(l, parse->windowClause)
616  {
617  WindowClause *wc = (WindowClause *) lfirst(l);
618 
619  /* partitionClause/orderClause are sort/group expressions */
622  wc->endOffset = preprocess_expression(root, wc->endOffset,
624  }
625 
626  parse->limitOffset = preprocess_expression(root, parse->limitOffset,
628  parse->limitCount = preprocess_expression(root, parse->limitCount,
630 
631  if (parse->onConflict)
632  {
633  parse->onConflict->arbiterElems = (List *)
635  (Node *) parse->onConflict->arbiterElems,
637  parse->onConflict->arbiterWhere =
639  parse->onConflict->arbiterWhere,
640  EXPRKIND_QUAL);
641  parse->onConflict->onConflictSet = (List *)
643  (Node *) parse->onConflict->onConflictSet,
645  parse->onConflict->onConflictWhere =
647  parse->onConflict->onConflictWhere,
648  EXPRKIND_QUAL);
649  /* exclRelTlist contains only Vars, so no preprocessing needed */
650  }
651 
652  root->append_rel_list = (List *)
655 
656  /* Also need to preprocess expressions within RTEs */
657  foreach(l, parse->rtable)
658  {
659  RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
660  int kind;
661  ListCell *lcsq;
662 
663  if (rte->rtekind == RTE_RELATION)
664  {
665  if (rte->tablesample)
666  rte->tablesample = (TableSampleClause *)
668  (Node *) rte->tablesample,
670  }
671  else if (rte->rtekind == RTE_SUBQUERY)
672  {
673  /*
674  * We don't want to do all preprocessing yet on the subquery's
675  * expressions, since that will happen when we plan it. But if it
676  * contains any join aliases of our level, those have to get
677  * expanded now, because planning of the subquery won't do it.
678  * That's only possible if the subquery is LATERAL.
679  */
680  if (rte->lateral && root->hasJoinRTEs)
681  rte->subquery = (Query *)
682  flatten_join_alias_vars(root, (Node *) rte->subquery);
683  }
684  else if (rte->rtekind == RTE_FUNCTION)
685  {
686  /* Preprocess the function expression(s) fully */
688  rte->functions = (List *) preprocess_expression(root, (Node *) rte->functions, kind);
689  }
690  else if (rte->rtekind == RTE_VALUES)
691  {
692  /* Preprocess the values lists fully */
694  rte->values_lists = (List *)
695  preprocess_expression(root, (Node *) rte->values_lists, kind);
696  }
697 
698  /*
699  * Process each element of the securityQuals list as if it were a
700  * separate qual expression (as indeed it is). We need to do it this
701  * way to get proper canonicalization of AND/OR structure. Note that
702  * this converts each element into an implicit-AND sublist.
703  */
704  foreach(lcsq, rte->securityQuals)
705  {
706  lfirst(lcsq) = preprocess_expression(root,
707  (Node *) lfirst(lcsq),
708  EXPRKIND_QUAL);
709  }
710  }
711 
712  /*
713  * In some cases we may want to transfer a HAVING clause into WHERE. We
714  * cannot do so if the HAVING clause contains aggregates (obviously) or
715  * volatile functions (since a HAVING clause is supposed to be executed
716  * only once per group). We also can't do this if there are any nonempty
717  * grouping sets; moving such a clause into WHERE would potentially change
718  * the results, if any referenced column isn't present in all the grouping
719  * sets. (If there are only empty grouping sets, then the HAVING clause
720  * must be degenerate as discussed below.)
721  *
722  * Also, it may be that the clause is so expensive to execute that we're
723  * better off doing it only once per group, despite the loss of
724  * selectivity. This is hard to estimate short of doing the entire
725  * planning process twice, so we use a heuristic: clauses containing
726  * subplans are left in HAVING. Otherwise, we move or copy the HAVING
727  * clause into WHERE, in hopes of eliminating tuples before aggregation
728  * instead of after.
729  *
730  * If the query has explicit grouping then we can simply move such a
731  * clause into WHERE; any group that fails the clause will not be in the
732  * output because none of its tuples will reach the grouping or
733  * aggregation stage. Otherwise we must have a degenerate (variable-free)
734  * HAVING clause, which we put in WHERE so that query_planner() can use it
735  * in a gating Result node, but also keep in HAVING to ensure that we
736  * don't emit a bogus aggregated row. (This could be done better, but it
737  * seems not worth optimizing.)
738  *
739  * Note that both havingQual and parse->jointree->quals are in
740  * implicitly-ANDed-list form at this point, even though they are declared
741  * as Node *.
742  */
743  newHaving = NIL;
744  foreach(l, (List *) parse->havingQual)
745  {
746  Node *havingclause = (Node *) lfirst(l);
747 
748  if ((parse->groupClause && parse->groupingSets) ||
749  contain_agg_clause(havingclause) ||
750  contain_volatile_functions(havingclause) ||
751  contain_subplans(havingclause))
752  {
753  /* keep it in HAVING */
754  newHaving = lappend(newHaving, havingclause);
755  }
756  else if (parse->groupClause && !parse->groupingSets)
757  {
758  /* move it to WHERE */
759  parse->jointree->quals = (Node *)
760  lappend((List *) parse->jointree->quals, havingclause);
761  }
762  else
763  {
764  /* put a copy in WHERE, keep it in HAVING */
765  parse->jointree->quals = (Node *)
766  lappend((List *) parse->jointree->quals,
767  copyObject(havingclause));
768  newHaving = lappend(newHaving, havingclause);
769  }
770  }
771  parse->havingQual = (Node *) newHaving;
772 
773  /* Remove any redundant GROUP BY columns */
775 
776  /*
777  * If we have any outer joins, try to reduce them to plain inner joins.
778  * This step is most easily done after we've done expression
779  * preprocessing.
780  */
781  if (hasOuterJoins)
782  reduce_outer_joins(root);
783 
784  /*
785  * Do the main planning. If we have an inherited target relation, that
786  * needs special processing, else go straight to grouping_planner.
787  */
788  if (parse->resultRelation &&
789  rt_fetch(parse->resultRelation, parse->rtable)->inh)
790  inheritance_planner(root);
791  else
792  grouping_planner(root, false, tuple_fraction);
793 
794  /*
795  * Capture the set of outer-level param IDs we have access to, for use in
796  * extParam/allParam calculations later.
797  */
799 
800  /*
801  * If any initPlans were created in this query level, adjust the surviving
802  * Paths' costs and parallel-safety flags to account for them. The
803  * initPlans won't actually get attached to the plan tree till
804  * create_plan() runs, but we must include their effects now.
805  */
806  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
807  SS_charge_for_initplans(root, final_rel);
808 
809  /*
810  * Make sure we've identified the cheapest Path for the final rel. (By
811  * doing this here not in grouping_planner, we include initPlan costs in
812  * the decision, though it's unlikely that will change anything.)
813  */
814  set_cheapest(final_rel);
815 
816  return root;
817 }
Node * limitOffset
Definition: parsenodes.h:149
#define NIL
Definition: pg_list.h:69
List * rowMarks
Definition: relation.h:251
Query * parse
Definition: relation.h:152
List * plan_params
Definition: relation.h:166
bool hasJoinRTEs
Definition: relation.h:294
#define EXPRKIND_ARBITER_ELEM
Definition: planner.c:82
void reduce_outer_joins(PlannerInfo *root)
FromExpr * jointree
Definition: parsenodes.h:129
int SS_assign_special_param(PlannerInfo *root)
Definition: subselect.c:415
OnConflictExpr * onConflict
Definition: parsenodes.h:133
static void preprocess_rowmarks(PlannerInfo *root)
Definition: planner.c:2105
List * securityQuals
Definition: parsenodes.h:970
List * withCheckOptions
Definition: parsenodes.h:160
#define EXPRKIND_APPINFO
Definition: planner.c:79
#define EXPRKIND_QUAL
Definition: planner.c:72
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:670
int resultRelation
Definition: parsenodes.h:113
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
Definition: subselect.c:2154
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:714
#define EXPRKIND_RTFUNC
Definition: planner.c:74
List * groupingSets
Definition: parsenodes.h:139
Definition: nodes.h:508
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:826
List * minmax_aggs
Definition: relation.h:280
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:950
#define EXPRKIND_VALUES_LATERAL
Definition: planner.c:77
void expand_inherited_tables(PlannerInfo *root)
Definition: prepunion.c:1318
AttrNumber * grouping_map
Definition: relation.h:279
bool hasRecursion
Definition: relation.h:300
void pull_up_subqueries(PlannerInfo *root)
Definition: prepjointree.c:607
#define EXPRKIND_TARGET
Definition: planner.c:73
List * values_lists
Definition: parsenodes.h:937
Node * quals
Definition: primnodes.h:1434
List * windowClause
Definition: parsenodes.h:143
List * targetList
Definition: parsenodes.h:131
List * arbiterElems
Definition: primnodes.h:1452
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
List * multiexpr_params
Definition: relation.h:229
bool contain_subplans(Node *clause)
Definition: clauses.c:842
#define EXPRKIND_LIMIT
Definition: planner.c:78
int wt_param_id
Definition: relation.h:303
List * rtable
Definition: parsenodes.h:128
bool hasLateralRTEs
Definition: relation.h:295
void inline_set_returning_functions(PlannerInfo *root)
Definition: prepjointree.c:573
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
static void remove_useless_groupby_columns(PlannerInfo *root)
Definition: planner.c:2524
Node * limitCount
Definition: parsenodes.h:150
PlannerGlobal * glob
Definition: relation.h:154
JoinType jointype
Definition: parsenodes.h:920
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
void SS_process_ctes(PlannerInfo *root)
Definition: subselect.c:1143
List * returningList
Definition: parsenodes.h:135
#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:158
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
Node * startOffset
Definition: parsenodes.h:1198
Node * flatten_join_alias_vars(PlannerInfo *root, Node *node)
Definition: var.c:670
List * append_rel_list
Definition: relation.h:249
List * cte_plan_ids
Definition: relation.h:227
List * init_plans
Definition: relation.h:225
bool hasPseudoConstantQuals
Definition: relation.h:298
static void inheritance_planner(PlannerInfo *root)
Definition: planner.c:980
bool hasTargetSRFs
Definition: parsenodes.h:118
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
void SS_identify_outer_params(PlannerInfo *root)
Definition: subselect.c:2092
List * eq_classes
Definition: relation.h:232
List * functions
Definition: parsenodes.h:931
bool hasInheritedTarget
Definition: relation.h:292
void flatten_simple_union_all(PlannerInfo *root)
Bitmapset * outer_params
Definition: relation.h:167
struct Path * non_recursive_path
Definition: relation.h:304
Node * endOffset
Definition: parsenodes.h:1199
#define EXPRKIND_RTFUNC_LATERAL
Definition: planner.c:75
Index qual_security_level
Definition: relation.h:289
Index query_level
Definition: relation.h:156
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:150
RTEKind rtekind
Definition: parsenodes.h:882
Node * arbiterWhere
Definition: primnodes.h:1454
List * cteList
Definition: parsenodes.h:126
Node * setOperations
Definition: parsenodes.h:154
bool contain_agg_clause(Node *clause)
Definition: clauses.c:416
Query * subquery
Definition: parsenodes.h:900
List * groupClause
Definition: parsenodes.h:137
bool hasSubLinks
Definition: parsenodes.h:119
static void grouping_planner(PlannerInfo *root, bool inheritance_update, double tuple_fraction)
Definition: planner.c:1382
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition: planner.c:911
List * onConflictSet
Definition: primnodes.h:1458
bool hasHavingQual
Definition: relation.h:297
#define EXPRKIND_TABLESAMPLE
Definition: planner.c:81
MemoryContext planner_cxt
Definition: relation.h:282
#define EXPRKIND_VALUES
Definition: planner.c:76
Node * havingQual
Definition: parsenodes.h:141
List * processed_tlist
Definition: relation.h:276
Node * onConflictWhere
Definition: primnodes.h:1459
Definition: pg_list.h:45
struct TableSampleClause * tablesample
Definition: parsenodes.h:895
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
struct PathTarget * upper_targets[UPPERREL_FINAL+1]
Definition: relation.h:270
List * upper_rels[UPPERREL_FINAL+1]
Definition: relation.h:267

Variable Documentation

Definition at line 65 of file planner.c.

Referenced by planner().