PostgreSQL Source Code  git master
planner.h File Reference
#include "nodes/pathnodes.h"
#include "nodes/plannodes.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, const char *query_string, int cursorOptions, ParamListInfo boundParams)
 
typedef void(* create_upper_paths_hook_type) (PlannerInfo *root, UpperRelationKind stage, RelOptInfo *input_rel, RelOptInfo *output_rel, void *extra)
 

Functions

PlannedStmtstandard_planner (Query *parse, const char *query_string, int cursorOptions, ParamListInfo boundParams)
 
PlannerInfosubquery_planner (PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
 
RowMarkType select_rowmark_type (RangeTblEntry *rte, LockClauseStrength strength)
 
bool limit_needed (Query *parse)
 
void mark_partial_aggref (Aggref *agg, AggSplit aggsplit)
 
Pathget_cheapest_fractional_path (RelOptInfo *rel, double tuple_fraction)
 
Exprpreprocess_phv_expression (PlannerInfo *root, Expr *expr)
 

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 33 of file planner.h.

◆ planner_hook_type

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

Definition at line 26 of file planner.h.

Function Documentation

◆ get_cheapest_fractional_path()

Path* get_cheapest_fractional_path ( RelOptInfo rel,
double  tuple_fraction 
)

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

5649 {
5650  Path *best_path = rel->cheapest_total_path;
5651  ListCell *l;
5652 
5653  /* If all tuples will be retrieved, just return the cheapest-total path */
5654  if (tuple_fraction <= 0.0)
5655  return best_path;
5656 
5657  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
5658  if (tuple_fraction >= 1.0 && best_path->rows > 0)
5659  tuple_fraction /= best_path->rows;
5660 
5661  foreach(l, rel->pathlist)
5662  {
5663  Path *path = (Path *) lfirst(l);
5664 
5665  if (path == rel->cheapest_total_path ||
5666  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
5667  continue;
5668 
5669  best_path = path;
5670  }
5671 
5672  return best_path;
5673 }
struct Path * cheapest_total_path
Definition: pathnodes.h:699
#define lfirst(lc)
Definition: pg_list.h:169
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:117
List * pathlist
Definition: pathnodes.h:695
Cardinality rows
Definition: pathnodes.h:1192

◆ limit_needed()

bool limit_needed ( Query parse)

Definition at line 2489 of file planner.c.

References DatumGetInt64, IsA, Query::limitCount, and Query::limitOffset.

Referenced by grouping_planner(), and set_rel_consider_parallel().

2490 {
2491  Node *node;
2492 
2493  node = parse->limitCount;
2494  if (node)
2495  {
2496  if (IsA(node, Const))
2497  {
2498  /* NULL indicates LIMIT ALL, ie, no limit */
2499  if (!((Const *) node)->constisnull)
2500  return true; /* LIMIT with a constant value */
2501  }
2502  else
2503  return true; /* non-constant LIMIT */
2504  }
2505 
2506  node = parse->limitOffset;
2507  if (node)
2508  {
2509  if (IsA(node, Const))
2510  {
2511  /* Treat NULL as no offset; the executor would too */
2512  if (!((Const *) node)->constisnull)
2513  {
2514  int64 offset = DatumGetInt64(((Const *) node)->constvalue);
2515 
2516  if (offset != 0)
2517  return true; /* OFFSET with a nonzero value */
2518  }
2519  }
2520  else
2521  return true; /* non-constant OFFSET */
2522  }
2523 
2524  return false; /* don't need a Limit plan node */
2525 }
Node * limitOffset
Definition: parsenodes.h:171
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Definition: nodes.h:536
#define DatumGetInt64(X)
Definition: postgres.h:651
Node * limitCount
Definition: parsenodes.h:172

◆ mark_partial_aggref()

void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)

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

5049 {
5050  /* aggtranstype should be computed by this point */
5052  /* ... but aggsplit should still be as the parser left it */
5053  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
5054 
5055  /* Mark the Aggref with the intended partial-aggregation mode */
5056  agg->aggsplit = aggsplit;
5057 
5058  /*
5059  * Adjust result type if needed. Normally, a partial aggregate returns
5060  * the aggregate's transition type; but if that's INTERNAL and we're
5061  * serializing, it returns BYTEA instead.
5062  */
5063  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
5064  {
5065  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
5066  agg->aggtype = BYTEAOID;
5067  else
5068  agg->aggtype = agg->aggtranstype;
5069  }
5070 }
#define OidIsValid(objectId)
Definition: c.h:710
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:801
#define Assert(condition)
Definition: c.h:804
AggSplit aggsplit
Definition: primnodes.h:339
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:800
Oid aggtranstype
Definition: primnodes.h:327
Oid aggtype
Definition: primnodes.h:324

◆ preprocess_phv_expression()

Expr* preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)

Definition at line 1205 of file planner.c.

References EXPRKIND_PHV, and preprocess_expression().

Referenced by extract_lateral_references().

1206 {
1207  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1208 }
Definition: nodes.h:536
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1059
#define EXPRKIND_PHV
Definition: planner.c:89

◆ select_rowmark_type()

RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)

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

2239 {
2240  if (rte->rtekind != RTE_RELATION)
2241  {
2242  /* If it's not a table at all, use ROW_MARK_COPY */
2243  return ROW_MARK_COPY;
2244  }
2245  else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2246  {
2247  /* Let the FDW select the rowmark type, if it wants to */
2248  FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2249 
2250  if (fdwroutine->GetForeignRowMarkType != NULL)
2251  return fdwroutine->GetForeignRowMarkType(rte, strength);
2252  /* Otherwise, use ROW_MARK_COPY by default */
2253  return ROW_MARK_COPY;
2254  }
2255  else
2256  {
2257  /* Regular table, apply the appropriate lock type */
2258  switch (strength)
2259  {
2260  case LCS_NONE:
2261 
2262  /*
2263  * We don't need a tuple lock, only the ability to re-fetch
2264  * the row.
2265  */
2266  return ROW_MARK_REFERENCE;
2267  break;
2268  case LCS_FORKEYSHARE:
2269  return ROW_MARK_KEYSHARE;
2270  break;
2271  case LCS_FORSHARE:
2272  return ROW_MARK_SHARE;
2273  break;
2274  case LCS_FORNOKEYUPDATE:
2275  return ROW_MARK_NOKEYEXCLUSIVE;
2276  break;
2277  case LCS_FORUPDATE:
2278  return ROW_MARK_EXCLUSIVE;
2279  break;
2280  }
2281  elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2282  return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2283  }
2284 }
#define ERROR
Definition: elog.h:46
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:404
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:247
RTEKind rtekind
Definition: parsenodes.h:1007
#define elog(elevel,...)
Definition: elog.h:232

◆ standard_planner()

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

Definition at line 282 of file planner.c.

References PlannedStmt::appendRelations, PlannerGlobal::appendRelations, 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, DestroyPartitionDirectory(), 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, 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, 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, PlannerGlobal::partition_directory, 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::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 delay_execution_planner(), pgss_planner(), and planner().

284 {
285  PlannedStmt *result;
286  PlannerGlobal *glob;
287  double tuple_fraction;
288  PlannerInfo *root;
289  RelOptInfo *final_rel;
290  Path *best_path;
291  Plan *top_plan;
292  ListCell *lp,
293  *lr;
294 
295  /*
296  * Set up global state for this planner invocation. This data is needed
297  * across all levels of sub-Query that might exist in the given command,
298  * so we keep it in a separate struct that's linked to by each per-Query
299  * PlannerInfo.
300  */
301  glob = makeNode(PlannerGlobal);
302 
303  glob->boundParams = boundParams;
304  glob->subplans = NIL;
305  glob->subroots = NIL;
306  glob->rewindPlanIDs = NULL;
307  glob->finalrtable = NIL;
308  glob->finalrowmarks = NIL;
309  glob->resultRelations = NIL;
310  glob->appendRelations = NIL;
311  glob->relationOids = NIL;
312  glob->invalItems = NIL;
313  glob->paramExecTypes = NIL;
314  glob->lastPHId = 0;
315  glob->lastRowMarkId = 0;
316  glob->lastPlanNodeId = 0;
317  glob->transientPlan = false;
318  glob->dependsOnRole = false;
319 
320  /*
321  * Assess whether it's feasible to use parallel mode for this query. We
322  * can't do this in a standalone backend, or if the command will try to
323  * modify any data, or if this is a cursor operation, or if GUCs are set
324  * to values that don't permit parallelism, or if parallel-unsafe
325  * functions are present in the query tree.
326  *
327  * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
328  * MATERIALIZED VIEW to use parallel plans, but as of now, only the leader
329  * backend writes into a completely new table. In the future, we can
330  * extend it to allow workers to write into the table. However, to allow
331  * parallel updates and deletes, we have to solve other problems,
332  * especially around combo CIDs.)
333  *
334  * For now, we don't try to use parallel mode if we're running inside a
335  * parallel worker. We might eventually be able to relax this
336  * restriction, but for now it seems best not to have parallel workers
337  * trying to create their own parallel workers.
338  */
339  if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
341  parse->commandType == CMD_SELECT &&
342  !parse->hasModifyingCTE &&
344  !IsParallelWorker())
345  {
346  /* all the cheap tests pass, so scan the query tree */
347  glob->maxParallelHazard = max_parallel_hazard(parse);
348  glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
349  }
350  else
351  {
352  /* skip the query tree scan, just assume it's unsafe */
353  glob->maxParallelHazard = PROPARALLEL_UNSAFE;
354  glob->parallelModeOK = false;
355  }
356 
357  /*
358  * glob->parallelModeNeeded is normally set to false here and changed to
359  * true during plan creation if a Gather or Gather Merge plan is actually
360  * created (cf. create_gather_plan, create_gather_merge_plan).
361  *
362  * However, if force_parallel_mode = on or force_parallel_mode = regress,
363  * then we impose parallel mode whenever it's safe to do so, even if the
364  * final plan doesn't use parallelism. It's not safe to do so if the
365  * query contains anything parallel-unsafe; parallelModeOK will be false
366  * in that case. Note that parallelModeOK can't change after this point.
367  * Otherwise, everything in the query is either parallel-safe or
368  * parallel-restricted, and in either case it should be OK to impose
369  * parallel-mode restrictions. If that ends up breaking something, then
370  * either some function the user included in the query is incorrectly
371  * labeled as parallel-safe or parallel-restricted when in reality it's
372  * parallel-unsafe, or else the query planner itself has a bug.
373  */
374  glob->parallelModeNeeded = glob->parallelModeOK &&
376 
377  /* Determine what fraction of the plan is likely to be scanned */
378  if (cursorOptions & CURSOR_OPT_FAST_PLAN)
379  {
380  /*
381  * We have no real idea how many tuples the user will ultimately FETCH
382  * from a cursor, but it is often the case that he doesn't want 'em
383  * all, or would prefer a fast-start plan anyway so that he can
384  * process some of the tuples sooner. Use a GUC parameter to decide
385  * what fraction to optimize for.
386  */
387  tuple_fraction = cursor_tuple_fraction;
388 
389  /*
390  * We document cursor_tuple_fraction as simply being a fraction, which
391  * means the edge cases 0 and 1 have to be treated specially here. We
392  * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
393  */
394  if (tuple_fraction >= 1.0)
395  tuple_fraction = 0.0;
396  else if (tuple_fraction <= 0.0)
397  tuple_fraction = 1e-10;
398  }
399  else
400  {
401  /* Default assumption is we need all the tuples */
402  tuple_fraction = 0.0;
403  }
404 
405  /* primary planning entry point (may recurse for subqueries) */
406  root = subquery_planner(glob, parse, NULL,
407  false, tuple_fraction);
408 
409  /* Select best Path and turn it into a Plan */
410  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
411  best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
412 
413  top_plan = create_plan(root, best_path);
414 
415  /*
416  * If creating a plan for a scrollable cursor, make sure it can run
417  * backwards on demand. Add a Material node at the top at need.
418  */
419  if (cursorOptions & CURSOR_OPT_SCROLL)
420  {
421  if (!ExecSupportsBackwardScan(top_plan))
422  top_plan = materialize_finished_plan(top_plan);
423  }
424 
425  /*
426  * Optionally add a Gather node for testing purposes, provided this is
427  * actually a safe thing to do.
428  */
430  {
431  Gather *gather = makeNode(Gather);
432 
433  /*
434  * If there are any initPlans attached to the formerly-top plan node,
435  * move them up to the Gather node; same as we do for Material node in
436  * materialize_finished_plan.
437  */
438  gather->plan.initPlan = top_plan->initPlan;
439  top_plan->initPlan = NIL;
440 
441  gather->plan.targetlist = top_plan->targetlist;
442  gather->plan.qual = NIL;
443  gather->plan.lefttree = top_plan;
444  gather->plan.righttree = NULL;
445  gather->num_workers = 1;
446  gather->single_copy = true;
448 
449  /*
450  * Since this Gather has no parallel-aware descendants to signal to,
451  * we don't need a rescan Param.
452  */
453  gather->rescan_param = -1;
454 
455  /*
456  * Ideally we'd use cost_gather here, but setting up dummy path data
457  * to satisfy it doesn't seem much cleaner than knowing what it does.
458  */
459  gather->plan.startup_cost = top_plan->startup_cost +
461  gather->plan.total_cost = top_plan->total_cost +
463  gather->plan.plan_rows = top_plan->plan_rows;
464  gather->plan.plan_width = top_plan->plan_width;
465  gather->plan.parallel_aware = false;
466  gather->plan.parallel_safe = false;
467 
468  /* use parallel mode for parallel plans. */
469  root->glob->parallelModeNeeded = true;
470 
471  top_plan = &gather->plan;
472  }
473 
474  /*
475  * If any Params were generated, run through the plan tree and compute
476  * each plan node's extParam/allParam sets. Ideally we'd merge this into
477  * set_plan_references' tree traversal, but for now it has to be separate
478  * because we need to visit subplans before not after main plan.
479  */
480  if (glob->paramExecTypes != NIL)
481  {
482  Assert(list_length(glob->subplans) == list_length(glob->subroots));
483  forboth(lp, glob->subplans, lr, glob->subroots)
484  {
485  Plan *subplan = (Plan *) lfirst(lp);
486  PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
487 
488  SS_finalize_plan(subroot, subplan);
489  }
490  SS_finalize_plan(root, top_plan);
491  }
492 
493  /* final cleanup of the plan */
494  Assert(glob->finalrtable == NIL);
495  Assert(glob->finalrowmarks == NIL);
496  Assert(glob->resultRelations == NIL);
497  Assert(glob->appendRelations == 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;
523  result->appendRelations = glob->appendRelations;
524  result->subplans = glob->subplans;
525  result->rewindPlanIDs = glob->rewindPlanIDs;
526  result->rowMarks = glob->finalrowmarks;
527  result->relationOids = glob->relationOids;
528  result->invalItems = glob->invalItems;
529  result->paramExecTypes = glob->paramExecTypes;
530  /* utilityStmt should be null, but we might as well copy it */
531  result->utilityStmt = parse->utilityStmt;
532  result->stmt_location = parse->stmt_location;
533  result->stmt_len = parse->stmt_len;
534 
535  result->jitFlags = PGJIT_NONE;
536  if (jit_enabled && jit_above_cost >= 0 &&
537  top_plan->total_cost > jit_above_cost)
538  {
539  result->jitFlags |= PGJIT_PERFORM;
540 
541  /*
542  * Decide how much effort should be put into generating better code.
543  */
544  if (jit_optimize_above_cost >= 0 &&
546  result->jitFlags |= PGJIT_OPT3;
547  if (jit_inline_above_cost >= 0 &&
548  top_plan->total_cost > jit_inline_above_cost)
549  result->jitFlags |= PGJIT_INLINE;
550 
551  /*
552  * Decide which operations should be JITed.
553  */
554  if (jit_expressions)
555  result->jitFlags |= PGJIT_EXPR;
557  result->jitFlags |= PGJIT_DEFORM;
558  }
559 
560  if (glob->partition_directory != NULL)
562 
563  return result;
564 }
char maxParallelHazard
Definition: pathnodes.h:130
bool dependsOnRole
Definition: plannodes.h:58
List * paramExecTypes
Definition: plannodes.h:84
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
#define PGJIT_EXPR
Definition: jit.h:23
#define PGJIT_NONE
Definition: jit.h:19
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
int stmt_location
Definition: parsenodes.h:192
List * relationOids
Definition: plannodes.h:80
int lastPlanNodeId
Definition: pathnodes.h:120
List * resultRelations
Definition: pathnodes.h:106
List * appendRelations
Definition: pathnodes.h:108
double parallel_setup_cost
Definition: costsize.c:125
Node * utilityStmt
Definition: parsenodes.h:128
bool transientPlan
Definition: plannodes.h:56
int stmt_len
Definition: plannodes.h:90
char max_parallel_hazard(Query *parse)
Definition: clauses.c:620
struct Plan * planTree
Definition: plannodes.h:64
List * invalItems
Definition: plannodes.h:82
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:332
bool dependsOnRole
Definition: pathnodes.h:124
struct Plan * righttree
Definition: plannodes.h:144
#define PGJIT_OPT3
Definition: jit.h:21
bool parallelModeNeeded
Definition: pathnodes.h:128
bool jit_enabled
Definition: jit.c:32
List * paramExecTypes
Definition: pathnodes.h:114
void DestroyPartitionDirectory(PartitionDirectory pdir)
Definition: partdesc.c:438
Plan plan
Definition: plannodes.h:930
bool single_copy
Definition: plannodes.h:933
bool parallelModeOK
Definition: pathnodes.h:126
Bitmapset * rewindPlanIDs
Definition: pathnodes.h:100
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1210
#define lfirst_node(type, lc)
Definition: pg_list.h:172
int stmt_location
Definition: plannodes.h:89
List * subplans
Definition: pathnodes.h:96
Cost startup_cost
Definition: plannodes.h:117
PlannerGlobal * glob
Definition: pathnodes.h:164
bool IsUnderPostmaster
Definition: globals.c:112
bool hasReturning
Definition: plannodes.h:50
Plan * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:6385
Node * utilityStmt
Definition: plannodes.h:86
bool parallel_aware
Definition: plannodes.h:129
int jitFlags
Definition: plannodes.h:62
double cursor_tuple_fraction
Definition: planner.c:69
bool jit_expressions
Definition: jit.c:36
List * returningList
Definition: parsenodes.h:156
#define IsParallelWorker()
Definition: parallel.h:61
uint64 queryId
Definition: parsenodes.h:124
List * invalItems
Definition: pathnodes.h:112
bool canSetTag
Definition: plannodes.h:54
CmdType commandType
Definition: plannodes.h:46
#define CURSOR_OPT_FAST_PLAN
Definition: parsenodes.h:2825
double jit_above_cost
Definition: jit.c:39
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:512
Index lastPHId
Definition: pathnodes.h:116
#define PGJIT_INLINE
Definition: jit.h:22
bool jit_tuple_deforming
Definition: jit.c:38
List * rowMarks
Definition: plannodes.h:78
int num_workers
Definition: plannodes.h:931
double jit_inline_above_cost
Definition: jit.c:40
CmdType commandType
Definition: parsenodes.h:120
#define makeNode(_type_)
Definition: nodes.h:584
List * subplans
Definition: plannodes.h:73
int plan_width
Definition: plannodes.h:124
int force_parallel_mode
Definition: planner.c:70
ParamListInfo boundParams
Definition: pathnodes.h:94
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Bitmapset * rewindPlanIDs
Definition: plannodes.h:76
bool hasModifyingCTE
Definition: plannodes.h:52
bool canSetTag
Definition: parsenodes.h:126
int rescan_param
Definition: plannodes.h:932
#define PGJIT_PERFORM
Definition: jit.h:20
static int list_length(const List *l)
Definition: pg_list.h:149
List * relationOids
Definition: pathnodes.h:110
List * subroots
Definition: pathnodes.h:98
Cardinality plan_rows
Definition: plannodes.h:123
List * rtable
Definition: plannodes.h:66
struct Plan * lefttree
Definition: plannodes.h:143
double jit_optimize_above_cost
Definition: jit.c:41
List * targetlist
Definition: plannodes.h:141
bool invisible
Definition: plannodes.h:934
e
Definition: preproc-init.c:82
List * finalrtable
Definition: pathnodes.h:102
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:2828
Index lastRowMarkId
Definition: pathnodes.h:118
uint64 queryId
Definition: plannodes.h:48
List * resultRelations
Definition: plannodes.h:69
bool parallelModeNeeded
Definition: plannodes.h:60
List * initPlan
Definition: plannodes.h:145
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:2819
Cost total_cost
Definition: plannodes.h:118
bool hasModifyingCTE
Definition: parsenodes.h:139
bool parallel_safe
Definition: plannodes.h:130
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:250
#define PGJIT_DEFORM
Definition: jit.h:24
PartitionDirectory partition_directory
Definition: pathnodes.h:132
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2199
int max_parallel_workers_per_gather
Definition: costsize.c:131
List * finalrowmarks
Definition: pathnodes.h:104
int stmt_len
Definition: parsenodes.h:193
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction)
Definition: planner.c:596
List * appendRelations
Definition: plannodes.h:71
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition: planner.c:5648
bool transientPlan
Definition: pathnodes.h:122
double parallel_tuple_cost
Definition: costsize.c:124

◆ subquery_planner()

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

Definition at line 596 of file planner.c.

References PlannerInfo::all_result_relids, PlannerInfo::append_rel_list, OnConflictExpr::arbiterElems, OnConflictExpr::arbiterWhere, assign_special_exec_param(), bms_make_singleton(), contain_agg_clause(), contain_subplans(), contain_volatile_functions(), copyObject, PlannerInfo::cte_plan_ids, Query::cteList, CurrentMemoryContext, PlannerInfo::ec_merging_done, WindowClause::endOffset, PlannerInfo::eq_classes, 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, has_subclass(), PlannerInfo::hasAlternativeSubPlans, PlannerInfo::hasHavingQual, PlannerInfo::hasJoinRTEs, PlannerInfo::hasLateralRTEs, PlannerInfo::hasPseudoConstantQuals, PlannerInfo::hasRecursion, Query::hasSubLinks, Query::hasTargetSRFs, Query::havingQual, RangeTblEntry::inh, PlannerInfo::init_plans, IS_OUTER_JOIN, RangeTblEntry::joinaliasvars, Query::jointree, RangeTblEntry::jointype, lappend(), RangeTblEntry::lateral, PlannerInfo::leaf_result_relids, lfirst, lfirst_node, Query::limitCount, Query::limitOffset, list_length(), makeNode, Max, 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_function_rtes(), 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(), RangeTblEntry::relid, remove_useless_groupby_columns(), remove_useless_result_rtes(), replace_empty_jointree(), Query::resultRelation, Query::returningList, PlannerInfo::row_identity_vars, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, set_cheapest(), Query::setOperations, SS_charge_for_initplans(), SS_identify_outer_params(), SS_process_ctes(), WindowClause::startOffset, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, Query::targetList, PlannerInfo::update_colnos, 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().

599 {
600  PlannerInfo *root;
601  List *newWithCheckOptions;
602  List *newHaving;
603  bool hasOuterJoins;
604  bool hasResultRTEs;
605  RelOptInfo *final_rel;
606  ListCell *l;
607 
608  /* Create a PlannerInfo data structure for this subquery */
609  root = makeNode(PlannerInfo);
610  root->parse = parse;
611  root->glob = glob;
612  root->query_level = parent_root ? parent_root->query_level + 1 : 1;
613  root->parent_root = parent_root;
614  root->plan_params = NIL;
615  root->outer_params = NULL;
617  root->init_plans = NIL;
618  root->cte_plan_ids = NIL;
619  root->multiexpr_params = NIL;
620  root->eq_classes = NIL;
621  root->ec_merging_done = false;
622  root->all_result_relids =
623  parse->resultRelation ? bms_make_singleton(parse->resultRelation) : NULL;
624  root->leaf_result_relids = NULL; /* we'll find out leaf-ness later */
625  root->append_rel_list = NIL;
626  root->row_identity_vars = NIL;
627  root->rowMarks = NIL;
628  memset(root->upper_rels, 0, sizeof(root->upper_rels));
629  memset(root->upper_targets, 0, sizeof(root->upper_targets));
630  root->processed_tlist = NIL;
631  root->update_colnos = NIL;
632  root->grouping_map = NULL;
633  root->minmax_aggs = NIL;
634  root->qual_security_level = 0;
635  root->hasPseudoConstantQuals = false;
636  root->hasAlternativeSubPlans = false;
637  root->hasRecursion = hasRecursion;
638  if (hasRecursion)
640  else
641  root->wt_param_id = -1;
642  root->non_recursive_path = NULL;
643  root->partColsUpdated = false;
644 
645  /*
646  * If there is a WITH list, process each WITH query and either convert it
647  * to RTE_SUBQUERY RTE(s) or build an initplan SubPlan structure for it.
648  */
649  if (parse->cteList)
650  SS_process_ctes(root);
651 
652  /*
653  * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
654  * that we don't need so many special cases to deal with that situation.
655  */
656  replace_empty_jointree(parse);
657 
658  /*
659  * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
660  * to transform them into joins. Note that this step does not descend
661  * into subqueries; if we pull up any subqueries below, their SubLinks are
662  * processed just before pulling them up.
663  */
664  if (parse->hasSubLinks)
665  pull_up_sublinks(root);
666 
667  /*
668  * Scan the rangetable for function RTEs, do const-simplification on them,
669  * and then inline them if possible (producing subqueries that might get
670  * pulled up next). Recursion issues here are handled in the same way as
671  * for SubLinks.
672  */
674 
675  /*
676  * Check to see if any subqueries in the jointree can be merged into this
677  * query.
678  */
679  pull_up_subqueries(root);
680 
681  /*
682  * If this is a simple UNION ALL query, flatten it into an appendrel. We
683  * do this now because it requires applying pull_up_subqueries to the leaf
684  * queries of the UNION ALL, which weren't touched above because they
685  * weren't referenced by the jointree (they will be after we do this).
686  */
687  if (parse->setOperations)
689 
690  /*
691  * Survey the rangetable to see what kinds of entries are present. We can
692  * skip some later processing if relevant SQL features are not used; for
693  * example if there are no JOIN RTEs we can avoid the expense of doing
694  * flatten_join_alias_vars(). This must be done after we have finished
695  * adding rangetable entries, of course. (Note: actually, processing of
696  * inherited or partitioned rels can cause RTEs for their child tables to
697  * get added later; but those must all be RTE_RELATION entries, so they
698  * don't invalidate the conclusions drawn here.)
699  */
700  root->hasJoinRTEs = false;
701  root->hasLateralRTEs = false;
702  hasOuterJoins = false;
703  hasResultRTEs = false;
704  foreach(l, parse->rtable)
705  {
707 
708  switch (rte->rtekind)
709  {
710  case RTE_RELATION:
711  if (rte->inh)
712  {
713  /*
714  * Check to see if the relation actually has any children;
715  * if not, clear the inh flag so we can treat it as a
716  * plain base relation.
717  *
718  * Note: this could give a false-positive result, if the
719  * rel once had children but no longer does. We used to
720  * be able to clear rte->inh later on when we discovered
721  * that, but no more; we have to handle such cases as
722  * full-fledged inheritance.
723  */
724  rte->inh = has_subclass(rte->relid);
725  }
726  break;
727  case RTE_JOIN:
728  root->hasJoinRTEs = true;
729  if (IS_OUTER_JOIN(rte->jointype))
730  hasOuterJoins = true;
731  break;
732  case RTE_RESULT:
733  hasResultRTEs = true;
734  break;
735  default:
736  /* No work here for other RTE types */
737  break;
738  }
739 
740  if (rte->lateral)
741  root->hasLateralRTEs = true;
742 
743  /*
744  * We can also determine the maximum security level required for any
745  * securityQuals now. Addition of inheritance-child RTEs won't affect
746  * this, because child tables don't have their own securityQuals; see
747  * expand_single_inheritance_child().
748  */
749  if (rte->securityQuals)
751  list_length(rte->securityQuals));
752  }
753 
754  /*
755  * If we have now verified that the query target relation is
756  * non-inheriting, mark it as a leaf target.
757  */
758  if (parse->resultRelation)
759  {
760  RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
761 
762  if (!rte->inh)
763  root->leaf_result_relids =
765  }
766 
767  /*
768  * Preprocess RowMark information. We need to do this after subquery
769  * pullup, so that all base relations are present.
770  */
771  preprocess_rowmarks(root);
772 
773  /*
774  * Set hasHavingQual to remember if HAVING clause is present. Needed
775  * because preprocess_expression will reduce a constant-true condition to
776  * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
777  */
778  root->hasHavingQual = (parse->havingQual != NULL);
779 
780  /*
781  * Do expression preprocessing on targetlist and quals, as well as other
782  * random expressions in the querytree. Note that we do not need to
783  * handle sort/group expressions explicitly, because they are actually
784  * part of the targetlist.
785  */
786  parse->targetList = (List *)
787  preprocess_expression(root, (Node *) parse->targetList,
789 
790  /* Constant-folding might have removed all set-returning functions */
791  if (parse->hasTargetSRFs)
793 
794  newWithCheckOptions = NIL;
795  foreach(l, parse->withCheckOptions)
796  {
798 
799  wco->qual = preprocess_expression(root, wco->qual,
800  EXPRKIND_QUAL);
801  if (wco->qual != NULL)
802  newWithCheckOptions = lappend(newWithCheckOptions, wco);
803  }
804  parse->withCheckOptions = newWithCheckOptions;
805 
806  parse->returningList = (List *)
807  preprocess_expression(root, (Node *) parse->returningList,
809 
810  preprocess_qual_conditions(root, (Node *) parse->jointree);
811 
812  parse->havingQual = preprocess_expression(root, parse->havingQual,
813  EXPRKIND_QUAL);
814 
815  foreach(l, parse->windowClause)
816  {
818 
819  /* partitionClause/orderClause are sort/group expressions */
822  wc->endOffset = preprocess_expression(root, wc->endOffset,
824  }
825 
826  parse->limitOffset = preprocess_expression(root, parse->limitOffset,
828  parse->limitCount = preprocess_expression(root, parse->limitCount,
830 
831  if (parse->onConflict)
832  {
833  parse->onConflict->arbiterElems = (List *)
835  (Node *) parse->onConflict->arbiterElems,
837  parse->onConflict->arbiterWhere =
839  parse->onConflict->arbiterWhere,
840  EXPRKIND_QUAL);
841  parse->onConflict->onConflictSet = (List *)
843  (Node *) parse->onConflict->onConflictSet,
845  parse->onConflict->onConflictWhere =
847  parse->onConflict->onConflictWhere,
848  EXPRKIND_QUAL);
849  /* exclRelTlist contains only Vars, so no preprocessing needed */
850  }
851 
852  root->append_rel_list = (List *)
855 
856  /* Also need to preprocess expressions within RTEs */
857  foreach(l, parse->rtable)
858  {
860  int kind;
861  ListCell *lcsq;
862 
863  if (rte->rtekind == RTE_RELATION)
864  {
865  if (rte->tablesample)
866  rte->tablesample = (TableSampleClause *)
868  (Node *) rte->tablesample,
870  }
871  else if (rte->rtekind == RTE_SUBQUERY)
872  {
873  /*
874  * We don't want to do all preprocessing yet on the subquery's
875  * expressions, since that will happen when we plan it. But if it
876  * contains any join aliases of our level, those have to get
877  * expanded now, because planning of the subquery won't do it.
878  * That's only possible if the subquery is LATERAL.
879  */
880  if (rte->lateral && root->hasJoinRTEs)
881  rte->subquery = (Query *)
883  (Node *) rte->subquery);
884  }
885  else if (rte->rtekind == RTE_FUNCTION)
886  {
887  /* Preprocess the function expression(s) fully */
889  rte->functions = (List *)
890  preprocess_expression(root, (Node *) rte->functions, kind);
891  }
892  else if (rte->rtekind == RTE_TABLEFUNC)
893  {
894  /* Preprocess the function expression(s) fully */
896  rte->tablefunc = (TableFunc *)
897  preprocess_expression(root, (Node *) rte->tablefunc, kind);
898  }
899  else if (rte->rtekind == RTE_VALUES)
900  {
901  /* Preprocess the values lists fully */
903  rte->values_lists = (List *)
904  preprocess_expression(root, (Node *) rte->values_lists, kind);
905  }
906 
907  /*
908  * Process each element of the securityQuals list as if it were a
909  * separate qual expression (as indeed it is). We need to do it this
910  * way to get proper canonicalization of AND/OR structure. Note that
911  * this converts each element into an implicit-AND sublist.
912  */
913  foreach(lcsq, rte->securityQuals)
914  {
915  lfirst(lcsq) = preprocess_expression(root,
916  (Node *) lfirst(lcsq),
917  EXPRKIND_QUAL);
918  }
919  }
920 
921  /*
922  * Now that we are done preprocessing expressions, and in particular done
923  * flattening join alias variables, get rid of the joinaliasvars lists.
924  * They no longer match what expressions in the rest of the tree look
925  * like, because we have not preprocessed expressions in those lists (and
926  * do not want to; for example, expanding a SubLink there would result in
927  * a useless unreferenced subplan). Leaving them in place simply creates
928  * a hazard for later scans of the tree. We could try to prevent that by
929  * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
930  * but that doesn't sound very reliable.
931  */
932  if (root->hasJoinRTEs)
933  {
934  foreach(l, parse->rtable)
935  {
937 
938  rte->joinaliasvars = NIL;
939  }
940  }
941 
942  /*
943  * In some cases we may want to transfer a HAVING clause into WHERE. We
944  * cannot do so if the HAVING clause contains aggregates (obviously) or
945  * volatile functions (since a HAVING clause is supposed to be executed
946  * only once per group). We also can't do this if there are any nonempty
947  * grouping sets; moving such a clause into WHERE would potentially change
948  * the results, if any referenced column isn't present in all the grouping
949  * sets. (If there are only empty grouping sets, then the HAVING clause
950  * must be degenerate as discussed below.)
951  *
952  * Also, it may be that the clause is so expensive to execute that we're
953  * better off doing it only once per group, despite the loss of
954  * selectivity. This is hard to estimate short of doing the entire
955  * planning process twice, so we use a heuristic: clauses containing
956  * subplans are left in HAVING. Otherwise, we move or copy the HAVING
957  * clause into WHERE, in hopes of eliminating tuples before aggregation
958  * instead of after.
959  *
960  * If the query has explicit grouping then we can simply move such a
961  * clause into WHERE; any group that fails the clause will not be in the
962  * output because none of its tuples will reach the grouping or
963  * aggregation stage. Otherwise we must have a degenerate (variable-free)
964  * HAVING clause, which we put in WHERE so that query_planner() can use it
965  * in a gating Result node, but also keep in HAVING to ensure that we
966  * don't emit a bogus aggregated row. (This could be done better, but it
967  * seems not worth optimizing.)
968  *
969  * Note that both havingQual and parse->jointree->quals are in
970  * implicitly-ANDed-list form at this point, even though they are declared
971  * as Node *.
972  */
973  newHaving = NIL;
974  foreach(l, (List *) parse->havingQual)
975  {
976  Node *havingclause = (Node *) lfirst(l);
977 
978  if ((parse->groupClause && parse->groupingSets) ||
979  contain_agg_clause(havingclause) ||
980  contain_volatile_functions(havingclause) ||
981  contain_subplans(havingclause))
982  {
983  /* keep it in HAVING */
984  newHaving = lappend(newHaving, havingclause);
985  }
986  else if (parse->groupClause && !parse->groupingSets)
987  {
988  /* move it to WHERE */
989  parse->jointree->quals = (Node *)
990  lappend((List *) parse->jointree->quals, havingclause);
991  }
992  else
993  {
994  /* put a copy in WHERE, keep it in HAVING */
995  parse->jointree->quals = (Node *)
996  lappend((List *) parse->jointree->quals,
997  copyObject(havingclause));
998  newHaving = lappend(newHaving, havingclause);
999  }
1000  }
1001  parse->havingQual = (Node *) newHaving;
1002 
1003  /* Remove any redundant GROUP BY columns */
1005 
1006  /*
1007  * If we have any outer joins, try to reduce them to plain inner joins.
1008  * This step is most easily done after we've done expression
1009  * preprocessing.
1010  */
1011  if (hasOuterJoins)
1012  reduce_outer_joins(root);
1013 
1014  /*
1015  * If we have any RTE_RESULT relations, see if they can be deleted from
1016  * the jointree. This step is most effectively done after we've done
1017  * expression preprocessing and outer join reduction.
1018  */
1019  if (hasResultRTEs)
1021 
1022  /*
1023  * Do the main planning.
1024  */
1025  grouping_planner(root, tuple_fraction);
1026 
1027  /*
1028  * Capture the set of outer-level param IDs we have access to, for use in
1029  * extParam/allParam calculations later.
1030  */
1032 
1033  /*
1034  * If any initPlans were created in this query level, adjust the surviving
1035  * Paths' costs and parallel-safety flags to account for them. The
1036  * initPlans won't actually get attached to the plan tree till
1037  * create_plan() runs, but we must include their effects now.
1038  */
1039  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
1040  SS_charge_for_initplans(root, final_rel);
1041 
1042  /*
1043  * Make sure we've identified the cheapest Path for the final rel. (By
1044  * doing this here not in grouping_planner, we include initPlan costs in
1045  * the decision, though it's unlikely that will change anything.)
1046  */
1047  set_cheapest(final_rel);
1048 
1049  return root;
1050 }
Node * limitOffset
Definition: parsenodes.h:171
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:288
void remove_useless_result_rtes(PlannerInfo *root)
Relids all_result_relids
Definition: pathnodes.h:276
Query * parse
Definition: pathnodes.h:162
List * joinaliasvars
Definition: parsenodes.h:1082
List * plan_params
Definition: pathnodes.h:176
bool hasJoinRTEs
Definition: pathnodes.h:346
bool ec_merging_done
Definition: pathnodes.h:251
#define EXPRKIND_ARBITER_ELEM
Definition: planner.c:91
void reduce_outer_joins(PlannerInfo *root)
FromExpr * jointree
Definition: parsenodes.h:148
OnConflictExpr * onConflict
Definition: parsenodes.h:154
PlannerInfo * parent_root
Definition: pathnodes.h:168
static void preprocess_rowmarks(PlannerInfo *root)
Definition: planner.c:2127
List * withCheckOptions
Definition: parsenodes.h:183
List * securityQuals
Definition: parsenodes.h:1163
#define EXPRKIND_APPINFO
Definition: planner.c:88
#define EXPRKIND_QUAL
Definition: planner.c:81
#define EXPRKIND_TABLEFUNC_LATERAL
Definition: planner.c:93
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:709
int resultRelation
Definition: parsenodes.h:130
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
Definition: subselect.c:2127
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:753
#define EXPRKIND_RTFUNC
Definition: planner.c:83
List * groupingSets
Definition: parsenodes.h:161
Definition: nodes.h:536
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1059
List * minmax_aggs
Definition: pathnodes.h:333
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:452
int assign_special_exec_param(PlannerInfo *root)
Definition: paramassign.c:584
#define EXPRKIND_VALUES_LATERAL
Definition: planner.c:86
AttrNumber * grouping_map
Definition: pathnodes.h:332
bool hasRecursion
Definition: pathnodes.h:352
void pull_up_subqueries(PlannerInfo *root)
Definition: prepjointree.c:680
#define EXPRKIND_TARGET
Definition: planner.c:82
void replace_empty_jointree(Query *parse)
Definition: prepjointree.c:150
List * values_lists
Definition: parsenodes.h:1112
Node * quals
Definition: primnodes.h:1565
List * windowClause
Definition: parsenodes.h:165
List * targetList
Definition: parsenodes.h:150
List * arbiterElems
Definition: primnodes.h:1583
List * multiexpr_params
Definition: pathnodes.h:246
bool contain_subplans(Node *clause)
Definition: clauses.c:328
#define EXPRKIND_LIMIT
Definition: planner.c:87
void preprocess_function_rtes(PlannerInfo *root)
Definition: prepjointree.c:639
int wt_param_id
Definition: pathnodes.h:364
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:356
List * rtable
Definition: parsenodes.h:147
List * row_identity_vars
Definition: pathnodes.h:286
TableFunc * tablefunc
Definition: parsenodes.h:1107
bool hasLateralRTEs
Definition: pathnodes.h:347
bool hasAlternativeSubPlans
Definition: pathnodes.h:351
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1210
#define lfirst_node(type, lc)
Definition: pg_list.h:172
static void remove_useless_groupby_columns(PlannerInfo *root)
Definition: planner.c:2548
Node * limitCount
Definition: parsenodes.h:172
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
PlannerGlobal * glob
Definition: pathnodes.h:164
bool partColsUpdated
Definition: pathnodes.h:379
JoinType jointype
Definition: parsenodes.h:1080
MemoryContext CurrentMemoryContext
Definition: mcxt.c:42
void SS_process_ctes(PlannerInfo *root)
Definition: subselect.c:892
List * returningList
Definition: parsenodes.h:156
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:336
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:244
Node * startOffset
Definition: parsenodes.h:1394
List * append_rel_list
Definition: pathnodes.h:284
List * cte_plan_ids
Definition: pathnodes.h:244
List * init_plans
Definition: pathnodes.h:242
bool hasPseudoConstantQuals
Definition: pathnodes.h:349
Node * flatten_join_alias_vars(Query *query, Node *node)
Definition: var.c:732
bool hasTargetSRFs
Definition: parsenodes.h:135
#define Max(x, y)
Definition: c.h:980
#define makeNode(_type_)
Definition: nodes.h:584
#define lfirst(lc)
Definition: pg_list.h:169
void SS_identify_outer_params(PlannerInfo *root)
Definition: subselect.c:2065
List * eq_classes
Definition: pathnodes.h:249
List * functions
Definition: parsenodes.h:1101
void flatten_simple_union_all(PlannerInfo *root)
Bitmapset * outer_params
Definition: pathnodes.h:177
struct Path * non_recursive_path
Definition: pathnodes.h:365
Node * endOffset
Definition: parsenodes.h:1395
static int list_length(const List *l)
Definition: pg_list.h:149
#define EXPRKIND_RTFUNC_LATERAL
Definition: planner.c:84
static void grouping_planner(PlannerInfo *root, double tuple_fraction)
Definition: planner.c:1234
Index qual_security_level
Definition: pathnodes.h:343
Index query_level
Definition: pathnodes.h:166
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:208
RTEKind rtekind
Definition: parsenodes.h:1007
Node * arbiterWhere
Definition: primnodes.h:1585
List * cteList
Definition: parsenodes.h:145
Node * setOperations
Definition: parsenodes.h:177
bool contain_agg_clause(Node *clause)
Definition: clauses.c:175
Query * subquery
Definition: parsenodes.h:1042
List * groupClause
Definition: parsenodes.h:158
bool hasSubLinks
Definition: parsenodes.h:136
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition: planner.c:1161
Relids leaf_result_relids
Definition: pathnodes.h:277
List * onConflictSet
Definition: primnodes.h:1589
bool hasHavingQual
Definition: pathnodes.h:348
#define EXPRKIND_TABLESAMPLE
Definition: planner.c:90
MemoryContext planner_cxt
Definition: pathnodes.h:335
#define copyObject(obj)
Definition: nodes.h:652
#define EXPRKIND_VALUES
Definition: planner.c:85
Node * havingQual
Definition: parsenodes.h:163
List * processed_tlist
Definition: pathnodes.h:321
Node * onConflictWhere
Definition: primnodes.h:1590
Definition: pg_list.h:50
struct TableSampleClause * tablesample
Definition: parsenodes.h:1037
List * update_colnos
Definition: pathnodes.h:329
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:673
struct PathTarget * upper_targets[UPPERREL_FINAL+1]
Definition: pathnodes.h:310
#define EXPRKIND_TABLEFUNC
Definition: planner.c:92
List * upper_rels[UPPERREL_FINAL+1]
Definition: pathnodes.h:307

Variable Documentation

◆ create_upper_paths_hook

◆ planner_hook

Definition at line 74 of file planner.c.

Referenced by _PG_fini(), _PG_init(), and planner().