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, SetOperationStmt *setops)
 
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 6524 of file planner.c.

6525 {
6526  Path *best_path = rel->cheapest_total_path;
6527  ListCell *l;
6528 
6529  /* If all tuples will be retrieved, just return the cheapest-total path */
6530  if (tuple_fraction <= 0.0)
6531  return best_path;
6532 
6533  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
6534  if (tuple_fraction >= 1.0 && best_path->rows > 0)
6535  tuple_fraction /= best_path->rows;
6536 
6537  foreach(l, rel->pathlist)
6538  {
6539  Path *path = (Path *) lfirst(l);
6540 
6541  if (path == rel->cheapest_total_path ||
6542  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
6543  continue;
6544 
6545  best_path = path;
6546  }
6547 
6548  return best_path;
6549 }
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:124
#define lfirst(lc)
Definition: pg_list.h:172
Cardinality rows
Definition: pathnodes.h:1669
List * pathlist
Definition: pathnodes.h:898
struct Path * cheapest_total_path
Definition: pathnodes.h:902

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

Referenced by make_subplan(), and standard_planner().

◆ limit_needed()

bool limit_needed ( Query parse)

Definition at line 2679 of file planner.c.

2680 {
2681  Node *node;
2682 
2683  node = parse->limitCount;
2684  if (node)
2685  {
2686  if (IsA(node, Const))
2687  {
2688  /* NULL indicates LIMIT ALL, ie, no limit */
2689  if (!((Const *) node)->constisnull)
2690  return true; /* LIMIT with a constant value */
2691  }
2692  else
2693  return true; /* non-constant LIMIT */
2694  }
2695 
2696  node = parse->limitOffset;
2697  if (node)
2698  {
2699  if (IsA(node, Const))
2700  {
2701  /* Treat NULL as no offset; the executor would too */
2702  if (!((Const *) node)->constisnull)
2703  {
2704  int64 offset = DatumGetInt64(((Const *) node)->constvalue);
2705 
2706  if (offset != 0)
2707  return true; /* OFFSET with a nonzero value */
2708  }
2709  }
2710  else
2711  return true; /* non-constant OFFSET */
2712  }
2713 
2714  return false; /* don't need a Limit plan node */
2715 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:385
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:715
Definition: nodes.h:129

References DatumGetInt64(), IsA, and parse().

Referenced by grouping_planner(), and set_rel_consider_parallel().

◆ mark_partial_aggref()

void mark_partial_aggref ( Aggref agg,
AggSplit  aggsplit 
)

Definition at line 5736 of file planner.c.

5737 {
5738  /* aggtranstype should be computed by this point */
5739  Assert(OidIsValid(agg->aggtranstype));
5740  /* ... but aggsplit should still be as the parser left it */
5741  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
5742 
5743  /* Mark the Aggref with the intended partial-aggregation mode */
5744  agg->aggsplit = aggsplit;
5745 
5746  /*
5747  * Adjust result type if needed. Normally, a partial aggregate returns
5748  * the aggregate's transition type; but if that's INTERNAL and we're
5749  * serializing, it returns BYTEA instead.
5750  */
5751  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
5752  {
5753  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
5754  agg->aggtype = BYTEAOID;
5755  else
5756  agg->aggtype = agg->aggtranstype;
5757  }
5758 }
#define Assert(condition)
Definition: c.h:861
#define OidIsValid(objectId)
Definition: c.h:778
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:386
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:387
@ AGGSPLIT_SIMPLE
Definition: nodes.h:377

References AGGSPLIT_SIMPLE, Assert, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, and OidIsValid.

Referenced by convert_combining_aggrefs(), and make_partial_grouping_target().

◆ preprocess_phv_expression()

Expr* preprocess_phv_expression ( PlannerInfo root,
Expr expr 
)

Definition at line 1323 of file planner.c.

1324 {
1325  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1326 }
#define EXPRKIND_PHV
Definition: planner.c:87
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1177
tree ctl root
Definition: radixtree.h:1886

References EXPRKIND_PHV, preprocess_expression(), and root.

Referenced by extract_lateral_references().

◆ select_rowmark_type()

RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)

Definition at line 2428 of file planner.c.

2429 {
2430  if (rte->rtekind != RTE_RELATION)
2431  {
2432  /* If it's not a table at all, use ROW_MARK_COPY */
2433  return ROW_MARK_COPY;
2434  }
2435  else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2436  {
2437  /* Let the FDW select the rowmark type, if it wants to */
2438  FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2439 
2440  if (fdwroutine->GetForeignRowMarkType != NULL)
2441  return fdwroutine->GetForeignRowMarkType(rte, strength);
2442  /* Otherwise, use ROW_MARK_COPY by default */
2443  return ROW_MARK_COPY;
2444  }
2445  else
2446  {
2447  /* Regular table, apply the appropriate lock type */
2448  switch (strength)
2449  {
2450  case LCS_NONE:
2451 
2452  /*
2453  * We don't need a tuple lock, only the ability to re-fetch
2454  * the row.
2455  */
2456  return ROW_MARK_REFERENCE;
2457  break;
2458  case LCS_FORKEYSHARE:
2459  return ROW_MARK_KEYSHARE;
2460  break;
2461  case LCS_FORSHARE:
2462  return ROW_MARK_SHARE;
2463  break;
2464  case LCS_FORNOKEYUPDATE:
2465  return ROW_MARK_NOKEYEXCLUSIVE;
2466  break;
2467  case LCS_FORUPDATE:
2468  return ROW_MARK_EXCLUSIVE;
2469  break;
2470  }
2471  elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2472  return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2473  }
2474 }
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:419
@ LCS_FORUPDATE
Definition: lockoptions.h:27
@ LCS_NONE
Definition: lockoptions.h:23
@ LCS_FORSHARE
Definition: lockoptions.h:25
@ LCS_FORKEYSHARE
Definition: lockoptions.h:24
@ LCS_FORNOKEYUPDATE
Definition: lockoptions.h:26
@ RTE_RELATION
Definition: parsenodes.h:1017
@ ROW_MARK_COPY
Definition: plannodes.h:1335
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1334
@ ROW_MARK_SHARE
Definition: plannodes.h:1332
@ ROW_MARK_EXCLUSIVE
Definition: plannodes.h:1330
@ ROW_MARK_NOKEYEXCLUSIVE
Definition: plannodes.h:1331
@ ROW_MARK_KEYSHARE
Definition: plannodes.h:1333
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:247
RTEKind rtekind
Definition: parsenodes.h:1047

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

◆ standard_planner()

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

Definition at line 289 of file planner.c.

291 {
292  PlannedStmt *result;
293  PlannerGlobal *glob;
294  double tuple_fraction;
295  PlannerInfo *root;
296  RelOptInfo *final_rel;
297  Path *best_path;
298  Plan *top_plan;
299  ListCell *lp,
300  *lr;
301 
302  /*
303  * Set up global state for this planner invocation. This data is needed
304  * across all levels of sub-Query that might exist in the given command,
305  * so we keep it in a separate struct that's linked to by each per-Query
306  * PlannerInfo.
307  */
308  glob = makeNode(PlannerGlobal);
309 
310  glob->boundParams = boundParams;
311  glob->subplans = NIL;
312  glob->subpaths = NIL;
313  glob->subroots = NIL;
314  glob->rewindPlanIDs = NULL;
315  glob->finalrtable = NIL;
316  glob->finalrteperminfos = NIL;
317  glob->finalrowmarks = NIL;
318  glob->resultRelations = NIL;
319  glob->appendRelations = NIL;
320  glob->relationOids = NIL;
321  glob->invalItems = NIL;
322  glob->paramExecTypes = NIL;
323  glob->lastPHId = 0;
324  glob->lastRowMarkId = 0;
325  glob->lastPlanNodeId = 0;
326  glob->transientPlan = false;
327  glob->dependsOnRole = false;
328 
329  /*
330  * Assess whether it's feasible to use parallel mode for this query. We
331  * can't do this in a standalone backend, or if the command will try to
332  * modify any data, or if this is a cursor operation, or if GUCs are set
333  * to values that don't permit parallelism, or if parallel-unsafe
334  * functions are present in the query tree.
335  *
336  * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
337  * MATERIALIZED VIEW to use parallel plans, but this is safe only because
338  * the command is writing into a completely new table which workers won't
339  * be able to see. If the workers could see the table, the fact that
340  * group locking would cause them to ignore the leader's heavyweight GIN
341  * page locks would make this unsafe. We'll have to fix that somehow if
342  * we want to allow parallel inserts in general; updates and deletes have
343  * additional problems especially around combo CIDs.)
344  *
345  * For now, we don't try to use parallel mode if we're running inside a
346  * parallel worker. We might eventually be able to relax this
347  * restriction, but for now it seems best not to have parallel workers
348  * trying to create their own parallel workers.
349  */
350  if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
352  parse->commandType == CMD_SELECT &&
353  !parse->hasModifyingCTE &&
355  !IsParallelWorker())
356  {
357  /* all the cheap tests pass, so scan the query tree */
359  glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
360  }
361  else
362  {
363  /* skip the query tree scan, just assume it's unsafe */
364  glob->maxParallelHazard = PROPARALLEL_UNSAFE;
365  glob->parallelModeOK = false;
366  }
367 
368  /*
369  * glob->parallelModeNeeded is normally set to false here and changed to
370  * true during plan creation if a Gather or Gather Merge plan is actually
371  * created (cf. create_gather_plan, create_gather_merge_plan).
372  *
373  * However, if debug_parallel_query = on or debug_parallel_query =
374  * regress, then we impose parallel mode whenever it's safe to do so, even
375  * if the final plan doesn't use parallelism. It's not safe to do so if
376  * the query contains anything parallel-unsafe; parallelModeOK will be
377  * false in that case. Note that parallelModeOK can't change after this
378  * point. Otherwise, everything in the query is either parallel-safe or
379  * parallel-restricted, and in either case it should be OK to impose
380  * parallel-mode restrictions. If that ends up breaking something, then
381  * either some function the user included in the query is incorrectly
382  * labeled as parallel-safe or parallel-restricted when in reality it's
383  * parallel-unsafe, or else the query planner itself has a bug.
384  */
385  glob->parallelModeNeeded = glob->parallelModeOK &&
387 
388  /* Determine what fraction of the plan is likely to be scanned */
389  if (cursorOptions & CURSOR_OPT_FAST_PLAN)
390  {
391  /*
392  * We have no real idea how many tuples the user will ultimately FETCH
393  * from a cursor, but it is often the case that he doesn't want 'em
394  * all, or would prefer a fast-start plan anyway so that he can
395  * process some of the tuples sooner. Use a GUC parameter to decide
396  * what fraction to optimize for.
397  */
398  tuple_fraction = cursor_tuple_fraction;
399 
400  /*
401  * We document cursor_tuple_fraction as simply being a fraction, which
402  * means the edge cases 0 and 1 have to be treated specially here. We
403  * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
404  */
405  if (tuple_fraction >= 1.0)
406  tuple_fraction = 0.0;
407  else if (tuple_fraction <= 0.0)
408  tuple_fraction = 1e-10;
409  }
410  else
411  {
412  /* Default assumption is we need all the tuples */
413  tuple_fraction = 0.0;
414  }
415 
416  /* primary planning entry point (may recurse for subqueries) */
417  root = subquery_planner(glob, parse, NULL, false, tuple_fraction, NULL);
418 
419  /* Select best Path and turn it into a Plan */
420  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
421  best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
422 
423  top_plan = create_plan(root, best_path);
424 
425  /*
426  * If creating a plan for a scrollable cursor, make sure it can run
427  * backwards on demand. Add a Material node at the top at need.
428  */
429  if (cursorOptions & CURSOR_OPT_SCROLL)
430  {
431  if (!ExecSupportsBackwardScan(top_plan))
432  top_plan = materialize_finished_plan(top_plan);
433  }
434 
435  /*
436  * Optionally add a Gather node for testing purposes, provided this is
437  * actually a safe thing to do.
438  *
439  * We can add Gather even when top_plan has parallel-safe initPlans, but
440  * then we have to move the initPlans to the Gather node because of
441  * SS_finalize_plan's limitations. That would cause cosmetic breakage of
442  * regression tests when debug_parallel_query = regress, because initPlans
443  * that would normally appear on the top_plan move to the Gather, causing
444  * them to disappear from EXPLAIN output. That doesn't seem worth kluging
445  * EXPLAIN to hide, so skip it when debug_parallel_query = regress.
446  */
448  top_plan->parallel_safe &&
449  (top_plan->initPlan == NIL ||
451  {
452  Gather *gather = makeNode(Gather);
453  Cost initplan_cost;
454  bool unsafe_initplans;
455 
456  gather->plan.targetlist = top_plan->targetlist;
457  gather->plan.qual = NIL;
458  gather->plan.lefttree = top_plan;
459  gather->plan.righttree = NULL;
460  gather->num_workers = 1;
461  gather->single_copy = true;
463 
464  /* Transfer any initPlans to the new top node */
465  gather->plan.initPlan = top_plan->initPlan;
466  top_plan->initPlan = NIL;
467 
468  /*
469  * Since this Gather has no parallel-aware descendants to signal to,
470  * we don't need a rescan Param.
471  */
472  gather->rescan_param = -1;
473 
474  /*
475  * Ideally we'd use cost_gather here, but setting up dummy path data
476  * to satisfy it doesn't seem much cleaner than knowing what it does.
477  */
478  gather->plan.startup_cost = top_plan->startup_cost +
480  gather->plan.total_cost = top_plan->total_cost +
482  gather->plan.plan_rows = top_plan->plan_rows;
483  gather->plan.plan_width = top_plan->plan_width;
484  gather->plan.parallel_aware = false;
485  gather->plan.parallel_safe = false;
486 
487  /*
488  * Delete the initplans' cost from top_plan. We needn't add it to the
489  * Gather node, since the above coding already included it there.
490  */
492  &initplan_cost, &unsafe_initplans);
493  top_plan->startup_cost -= initplan_cost;
494  top_plan->total_cost -= initplan_cost;
495 
496  /* use parallel mode for parallel plans. */
497  root->glob->parallelModeNeeded = true;
498 
499  top_plan = &gather->plan;
500  }
501 
502  /*
503  * If any Params were generated, run through the plan tree and compute
504  * each plan node's extParam/allParam sets. Ideally we'd merge this into
505  * set_plan_references' tree traversal, but for now it has to be separate
506  * because we need to visit subplans before not after main plan.
507  */
508  if (glob->paramExecTypes != NIL)
509  {
510  Assert(list_length(glob->subplans) == list_length(glob->subroots));
511  forboth(lp, glob->subplans, lr, glob->subroots)
512  {
513  Plan *subplan = (Plan *) lfirst(lp);
514  PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
515 
516  SS_finalize_plan(subroot, subplan);
517  }
518  SS_finalize_plan(root, top_plan);
519  }
520 
521  /* final cleanup of the plan */
522  Assert(glob->finalrtable == NIL);
523  Assert(glob->finalrteperminfos == NIL);
524  Assert(glob->finalrowmarks == NIL);
525  Assert(glob->resultRelations == NIL);
526  Assert(glob->appendRelations == NIL);
527  top_plan = set_plan_references(root, top_plan);
528  /* ... and the subplans (both regular subplans and initplans) */
529  Assert(list_length(glob->subplans) == list_length(glob->subroots));
530  forboth(lp, glob->subplans, lr, glob->subroots)
531  {
532  Plan *subplan = (Plan *) lfirst(lp);
533  PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
534 
535  lfirst(lp) = set_plan_references(subroot, subplan);
536  }
537 
538  /* build the PlannedStmt result */
539  result = makeNode(PlannedStmt);
540 
541  result->commandType = parse->commandType;
542  result->queryId = parse->queryId;
543  result->hasReturning = (parse->returningList != NIL);
544  result->hasModifyingCTE = parse->hasModifyingCTE;
545  result->canSetTag = parse->canSetTag;
546  result->transientPlan = glob->transientPlan;
547  result->dependsOnRole = glob->dependsOnRole;
548  result->parallelModeNeeded = glob->parallelModeNeeded;
549  result->planTree = top_plan;
550  result->rtable = glob->finalrtable;
551  result->permInfos = glob->finalrteperminfos;
552  result->resultRelations = glob->resultRelations;
553  result->appendRelations = glob->appendRelations;
554  result->subplans = glob->subplans;
555  result->rewindPlanIDs = glob->rewindPlanIDs;
556  result->rowMarks = glob->finalrowmarks;
557  result->relationOids = glob->relationOids;
558  result->invalItems = glob->invalItems;
559  result->paramExecTypes = glob->paramExecTypes;
560  /* utilityStmt should be null, but we might as well copy it */
561  result->utilityStmt = parse->utilityStmt;
562  result->stmt_location = parse->stmt_location;
563  result->stmt_len = parse->stmt_len;
564 
565  result->jitFlags = PGJIT_NONE;
566  if (jit_enabled && jit_above_cost >= 0 &&
567  top_plan->total_cost > jit_above_cost)
568  {
569  result->jitFlags |= PGJIT_PERFORM;
570 
571  /*
572  * Decide how much effort should be put into generating better code.
573  */
574  if (jit_optimize_above_cost >= 0 &&
576  result->jitFlags |= PGJIT_OPT3;
577  if (jit_inline_above_cost >= 0 &&
578  top_plan->total_cost > jit_inline_above_cost)
579  result->jitFlags |= PGJIT_INLINE;
580 
581  /*
582  * Decide which operations should be JITed.
583  */
584  if (jit_expressions)
585  result->jitFlags |= PGJIT_EXPR;
587  result->jitFlags |= PGJIT_DEFORM;
588  }
589 
590  if (glob->partition_directory != NULL)
591  DestroyPartitionDirectory(glob->partition_directory);
592 
593  return result;
594 }
char max_parallel_hazard(Query *parse)
Definition: clauses.c:734
int max_parallel_workers_per_gather
Definition: costsize.c:143
double parallel_setup_cost
Definition: costsize.c:136
double parallel_tuple_cost
Definition: costsize.c:135
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:340
Plan * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:6602
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:510
bool IsUnderPostmaster
Definition: globals.c:119
#define IsParallelWorker()
Definition: parallel.h:60
double jit_optimize_above_cost
Definition: jit.c:41
bool jit_enabled
Definition: jit.c:32
bool jit_expressions
Definition: jit.c:36
bool jit_tuple_deforming
Definition: jit.c:38
double jit_above_cost
Definition: jit.c:39
double jit_inline_above_cost
Definition: jit.c:40
#define PGJIT_OPT3
Definition: jit.h:21
#define PGJIT_NONE
Definition: jit.h:19
#define PGJIT_EXPR
Definition: jit.h:23
#define PGJIT_DEFORM
Definition: jit.h:24
#define PGJIT_INLINE
Definition: jit.h:22
#define PGJIT_PERFORM
Definition: jit.h:20
double Cost
Definition: nodes.h:251
@ CMD_SELECT
Definition: nodes.h:265
#define makeNode(_type_)
Definition: nodes.h:155
@ DEBUG_PARALLEL_REGRESS
Definition: optimizer.h:108
@ DEBUG_PARALLEL_OFF
Definition: optimizer.h:106
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3308
#define CURSOR_OPT_FAST_PLAN
Definition: parsenodes.h:3314
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3317
void DestroyPartitionDirectory(PartitionDirectory pdir)
Definition: partdesc.c:484
@ UPPERREL_FINAL
Definition: pathnodes.h:79
#define lfirst_node(type, lc)
Definition: pg_list.h:176
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:518
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
Definition: planner.c:630
double cursor_tuple_fraction
Definition: planner.c:67
int debug_parallel_query
Definition: planner.c:68
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition: planner.c:6524
e
Definition: preproc-init.c:82
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1458
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:288
int num_workers
Definition: plannodes.h:1144
bool invisible
Definition: plannodes.h:1147
bool single_copy
Definition: plannodes.h:1146
Plan plan
Definition: plannodes.h:1143
int rescan_param
Definition: plannodes.h:1145
struct Plan * lefttree
Definition: plannodes.h:155
Cost total_cost
Definition: plannodes.h:130
struct Plan * righttree
Definition: plannodes.h:156
bool parallel_aware
Definition: plannodes.h:141
Cost startup_cost
Definition: plannodes.h:129
List * qual
Definition: plannodes.h:154
int plan_width
Definition: plannodes.h:136
bool parallel_safe
Definition: plannodes.h:142
Cardinality plan_rows
Definition: plannodes.h:135
List * targetlist
Definition: plannodes.h:153
List * initPlan
Definition: plannodes.h:157
struct Plan * planTree
Definition: plannodes.h:70
bool hasModifyingCTE
Definition: plannodes.h:58
List * appendRelations
Definition: plannodes.h:80
List * permInfos
Definition: plannodes.h:74
bool canSetTag
Definition: plannodes.h:60
List * rowMarks
Definition: plannodes.h:87
int jitFlags
Definition: plannodes.h:68
Bitmapset * rewindPlanIDs
Definition: plannodes.h:85
ParseLoc stmt_len
Definition: plannodes.h:99
bool hasReturning
Definition: plannodes.h:56
ParseLoc stmt_location
Definition: plannodes.h:98
List * invalItems
Definition: plannodes.h:91
bool transientPlan
Definition: plannodes.h:62
List * resultRelations
Definition: plannodes.h:78
List * subplans
Definition: plannodes.h:82
List * relationOids
Definition: plannodes.h:89
bool dependsOnRole
Definition: plannodes.h:64
CmdType commandType
Definition: plannodes.h:52
Node * utilityStmt
Definition: plannodes.h:95
List * rtable
Definition: plannodes.h:72
List * paramExecTypes
Definition: plannodes.h:93
bool parallelModeNeeded
Definition: plannodes.h:66
uint64 queryId
Definition: plannodes.h:54
int lastPlanNodeId
Definition: pathnodes.h:147
char maxParallelHazard
Definition: pathnodes.h:162
List * subplans
Definition: pathnodes.h:105
bool dependsOnRole
Definition: pathnodes.h:153
List * appendRelations
Definition: pathnodes.h:129
List * finalrowmarks
Definition: pathnodes.h:123
List * invalItems
Definition: pathnodes.h:135
List * relationOids
Definition: pathnodes.h:132
List * paramExecTypes
Definition: pathnodes.h:138
bool parallelModeOK
Definition: pathnodes.h:156
bool transientPlan
Definition: pathnodes.h:150
Bitmapset * rewindPlanIDs
Definition: pathnodes.h:114
List * finalrteperminfos
Definition: pathnodes.h:120
List * subpaths
Definition: pathnodes.h:108
Index lastPHId
Definition: pathnodes.h:141
Index lastRowMarkId
Definition: pathnodes.h:144
List * resultRelations
Definition: pathnodes.h:126
List * finalrtable
Definition: pathnodes.h:117
bool parallelModeNeeded
Definition: pathnodes.h:159
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2278
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition: subselect.c:2222

References PlannerGlobal::appendRelations, PlannedStmt::appendRelations, Assert, PlannedStmt::canSetTag, CMD_SELECT, PlannedStmt::commandType, create_plan(), CURSOR_OPT_FAST_PLAN, CURSOR_OPT_PARALLEL_OK, CURSOR_OPT_SCROLL, cursor_tuple_fraction, DEBUG_PARALLEL_OFF, debug_parallel_query, DEBUG_PARALLEL_REGRESS, PlannerGlobal::dependsOnRole, PlannedStmt::dependsOnRole, DestroyPartitionDirectory(), ExecSupportsBackwardScan(), fetch_upper_rel(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerGlobal::finalrteperminfos, forboth, get_cheapest_fractional_path(), PlannedStmt::hasModifyingCTE, PlannedStmt::hasReturning, Plan::initPlan, PlannerGlobal::invalItems, PlannedStmt::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, PlannerGlobal::parallelModeNeeded, PlannedStmt::parallelModeNeeded, PlannerGlobal::parallelModeOK, PlannerGlobal::paramExecTypes, PlannedStmt::paramExecTypes, parse(), PlannedStmt::permInfos, 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, PlannerGlobal::relationOids, PlannedStmt::relationOids, Gather::rescan_param, PlannerGlobal::resultRelations, PlannedStmt::resultRelations, PlannerGlobal::rewindPlanIDs, PlannedStmt::rewindPlanIDs, Plan::righttree, root, PlannedStmt::rowMarks, PlannedStmt::rtable, set_plan_references(), Gather::single_copy, SS_compute_initplan_cost(), SS_finalize_plan(), Plan::startup_cost, PlannedStmt::stmt_len, PlannedStmt::stmt_location, PlannerGlobal::subpaths, PlannerGlobal::subplans, PlannedStmt::subplans, subquery_planner(), Plan::targetlist, Plan::total_cost, PlannerGlobal::transientPlan, PlannedStmt::transientPlan, UPPERREL_FINAL, and PlannedStmt::utilityStmt.

Referenced by delay_execution_planner(), pgss_planner(), and planner().

◆ subquery_planner()

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

Definition at line 630 of file planner.c.

633 {
634  PlannerInfo *root;
635  List *newWithCheckOptions;
636  List *newHaving;
637  bool hasOuterJoins;
638  bool hasResultRTEs;
639  RelOptInfo *final_rel;
640  ListCell *l;
641 
642  /* Create a PlannerInfo data structure for this subquery */
644  root->parse = parse;
645  root->glob = glob;
646  root->query_level = parent_root ? parent_root->query_level + 1 : 1;
647  root->parent_root = parent_root;
648  root->plan_params = NIL;
649  root->outer_params = NULL;
650  root->planner_cxt = CurrentMemoryContext;
651  root->init_plans = NIL;
652  root->cte_plan_ids = NIL;
653  root->multiexpr_params = NIL;
654  root->join_domains = NIL;
655  root->eq_classes = NIL;
656  root->ec_merging_done = false;
657  root->last_rinfo_serial = 0;
658  root->all_result_relids =
659  parse->resultRelation ? bms_make_singleton(parse->resultRelation) : NULL;
660  root->leaf_result_relids = NULL; /* we'll find out leaf-ness later */
661  root->append_rel_list = NIL;
662  root->row_identity_vars = NIL;
663  root->rowMarks = NIL;
664  memset(root->upper_rels, 0, sizeof(root->upper_rels));
665  memset(root->upper_targets, 0, sizeof(root->upper_targets));
666  root->processed_groupClause = NIL;
667  root->processed_distinctClause = NIL;
668  root->processed_tlist = NIL;
669  root->update_colnos = NIL;
670  root->grouping_map = NULL;
671  root->minmax_aggs = NIL;
672  root->qual_security_level = 0;
673  root->hasPseudoConstantQuals = false;
674  root->hasAlternativeSubPlans = false;
675  root->placeholdersFrozen = false;
676  root->hasRecursion = hasRecursion;
677  if (hasRecursion)
678  root->wt_param_id = assign_special_exec_param(root);
679  else
680  root->wt_param_id = -1;
681  root->non_recursive_path = NULL;
682  root->partColsUpdated = false;
683 
684  /*
685  * Create the top-level join domain. This won't have valid contents until
686  * deconstruct_jointree fills it in, but the node needs to exist before
687  * that so we can build EquivalenceClasses referencing it.
688  */
689  root->join_domains = list_make1(makeNode(JoinDomain));
690 
691  /*
692  * If there is a WITH list, process each WITH query and either convert it
693  * to RTE_SUBQUERY RTE(s) or build an initplan SubPlan structure for it.
694  */
695  if (parse->cteList)
697 
698  /*
699  * If it's a MERGE command, transform the joinlist as appropriate.
700  */
702 
703  /*
704  * If the FROM clause is empty, replace it with a dummy RTE_RESULT RTE, so
705  * that we don't need so many special cases to deal with that situation.
706  */
708 
709  /*
710  * Look for ANY and EXISTS SubLinks in WHERE and JOIN/ON clauses, and try
711  * to transform them into joins. Note that this step does not descend
712  * into subqueries; if we pull up any subqueries below, their SubLinks are
713  * processed just before pulling them up.
714  */
715  if (parse->hasSubLinks)
717 
718  /*
719  * Scan the rangetable for function RTEs, do const-simplification on them,
720  * and then inline them if possible (producing subqueries that might get
721  * pulled up next). Recursion issues here are handled in the same way as
722  * for SubLinks.
723  */
725 
726  /*
727  * Check to see if any subqueries in the jointree can be merged into this
728  * query.
729  */
731 
732  /*
733  * If this is a simple UNION ALL query, flatten it into an appendrel. We
734  * do this now because it requires applying pull_up_subqueries to the leaf
735  * queries of the UNION ALL, which weren't touched above because they
736  * weren't referenced by the jointree (they will be after we do this).
737  */
738  if (parse->setOperations)
740 
741  /*
742  * Survey the rangetable to see what kinds of entries are present. We can
743  * skip some later processing if relevant SQL features are not used; for
744  * example if there are no JOIN RTEs we can avoid the expense of doing
745  * flatten_join_alias_vars(). This must be done after we have finished
746  * adding rangetable entries, of course. (Note: actually, processing of
747  * inherited or partitioned rels can cause RTEs for their child tables to
748  * get added later; but those must all be RTE_RELATION entries, so they
749  * don't invalidate the conclusions drawn here.)
750  */
751  root->hasJoinRTEs = false;
752  root->hasLateralRTEs = false;
753  root->group_rtindex = 0;
754  hasOuterJoins = false;
755  hasResultRTEs = false;
756  foreach(l, parse->rtable)
757  {
759 
760  switch (rte->rtekind)
761  {
762  case RTE_RELATION:
763  if (rte->inh)
764  {
765  /*
766  * Check to see if the relation actually has any children;
767  * if not, clear the inh flag so we can treat it as a
768  * plain base relation.
769  *
770  * Note: this could give a false-positive result, if the
771  * rel once had children but no longer does. We used to
772  * be able to clear rte->inh later on when we discovered
773  * that, but no more; we have to handle such cases as
774  * full-fledged inheritance.
775  */
776  rte->inh = has_subclass(rte->relid);
777  }
778  break;
779  case RTE_JOIN:
780  root->hasJoinRTEs = true;
781  if (IS_OUTER_JOIN(rte->jointype))
782  hasOuterJoins = true;
783  break;
784  case RTE_RESULT:
785  hasResultRTEs = true;
786  break;
787  case RTE_GROUP:
788  Assert(parse->hasGroupRTE);
789  root->group_rtindex = list_cell_number(parse->rtable, l) + 1;
790  break;
791  default:
792  /* No work here for other RTE types */
793  break;
794  }
795 
796  if (rte->lateral)
797  root->hasLateralRTEs = true;
798 
799  /*
800  * We can also determine the maximum security level required for any
801  * securityQuals now. Addition of inheritance-child RTEs won't affect
802  * this, because child tables don't have their own securityQuals; see
803  * expand_single_inheritance_child().
804  */
805  if (rte->securityQuals)
806  root->qual_security_level = Max(root->qual_security_level,
807  list_length(rte->securityQuals));
808  }
809 
810  /*
811  * If we have now verified that the query target relation is
812  * non-inheriting, mark it as a leaf target.
813  */
814  if (parse->resultRelation)
815  {
816  RangeTblEntry *rte = rt_fetch(parse->resultRelation, parse->rtable);
817 
818  if (!rte->inh)
819  root->leaf_result_relids =
820  bms_make_singleton(parse->resultRelation);
821  }
822 
823  /*
824  * Preprocess RowMark information. We need to do this after subquery
825  * pullup, so that all base relations are present.
826  */
828 
829  /*
830  * Set hasHavingQual to remember if HAVING clause is present. Needed
831  * because preprocess_expression will reduce a constant-true condition to
832  * an empty qual list ... but "HAVING TRUE" is not a semantic no-op.
833  */
834  root->hasHavingQual = (parse->havingQual != NULL);
835 
836  /*
837  * Do expression preprocessing on targetlist and quals, as well as other
838  * random expressions in the querytree. Note that we do not need to
839  * handle sort/group expressions explicitly, because they are actually
840  * part of the targetlist.
841  */
842  parse->targetList = (List *)
843  preprocess_expression(root, (Node *) parse->targetList,
845 
846  newWithCheckOptions = NIL;
847  foreach(l, parse->withCheckOptions)
848  {
850 
851  wco->qual = preprocess_expression(root, wco->qual,
852  EXPRKIND_QUAL);
853  if (wco->qual != NULL)
854  newWithCheckOptions = lappend(newWithCheckOptions, wco);
855  }
856  parse->withCheckOptions = newWithCheckOptions;
857 
858  parse->returningList = (List *)
859  preprocess_expression(root, (Node *) parse->returningList,
861 
862  preprocess_qual_conditions(root, (Node *) parse->jointree);
863 
864  parse->havingQual = preprocess_expression(root, parse->havingQual,
865  EXPRKIND_QUAL);
866 
867  foreach(l, parse->windowClause)
868  {
870 
871  /* partitionClause/orderClause are sort/group expressions */
876  }
877 
878  parse->limitOffset = preprocess_expression(root, parse->limitOffset,
880  parse->limitCount = preprocess_expression(root, parse->limitCount,
882 
883  if (parse->onConflict)
884  {
885  parse->onConflict->arbiterElems = (List *)
887  (Node *) parse->onConflict->arbiterElems,
889  parse->onConflict->arbiterWhere =
891  parse->onConflict->arbiterWhere,
892  EXPRKIND_QUAL);
893  parse->onConflict->onConflictSet = (List *)
895  (Node *) parse->onConflict->onConflictSet,
897  parse->onConflict->onConflictWhere =
899  parse->onConflict->onConflictWhere,
900  EXPRKIND_QUAL);
901  /* exclRelTlist contains only Vars, so no preprocessing needed */
902  }
903 
904  foreach(l, parse->mergeActionList)
905  {
907 
908  action->targetList = (List *)
910  (Node *) action->targetList,
912  action->qual =
914  (Node *) action->qual,
915  EXPRKIND_QUAL);
916  }
917 
918  parse->mergeJoinCondition =
919  preprocess_expression(root, parse->mergeJoinCondition, EXPRKIND_QUAL);
920 
921  root->append_rel_list = (List *)
922  preprocess_expression(root, (Node *) root->append_rel_list,
924 
925  /* Also need to preprocess expressions within RTEs */
926  foreach(l, parse->rtable)
927  {
929  int kind;
930  ListCell *lcsq;
931 
932  if (rte->rtekind == RTE_RELATION)
933  {
934  if (rte->tablesample)
935  rte->tablesample = (TableSampleClause *)
937  (Node *) rte->tablesample,
939  }
940  else if (rte->rtekind == RTE_SUBQUERY)
941  {
942  /*
943  * We don't want to do all preprocessing yet on the subquery's
944  * expressions, since that will happen when we plan it. But if it
945  * contains any join aliases of our level, those have to get
946  * expanded now, because planning of the subquery won't do it.
947  * That's only possible if the subquery is LATERAL.
948  */
949  if (rte->lateral && root->hasJoinRTEs)
950  rte->subquery = (Query *)
952  (Node *) rte->subquery);
953  }
954  else if (rte->rtekind == RTE_FUNCTION)
955  {
956  /* Preprocess the function expression(s) fully */
957  kind = rte->lateral ? EXPRKIND_RTFUNC_LATERAL : EXPRKIND_RTFUNC;
958  rte->functions = (List *)
959  preprocess_expression(root, (Node *) rte->functions, kind);
960  }
961  else if (rte->rtekind == RTE_TABLEFUNC)
962  {
963  /* Preprocess the function expression(s) fully */
964  kind = rte->lateral ? EXPRKIND_TABLEFUNC_LATERAL : EXPRKIND_TABLEFUNC;
965  rte->tablefunc = (TableFunc *)
966  preprocess_expression(root, (Node *) rte->tablefunc, kind);
967  }
968  else if (rte->rtekind == RTE_VALUES)
969  {
970  /* Preprocess the values lists fully */
971  kind = rte->lateral ? EXPRKIND_VALUES_LATERAL : EXPRKIND_VALUES;
972  rte->values_lists = (List *)
973  preprocess_expression(root, (Node *) rte->values_lists, kind);
974  }
975  else if (rte->rtekind == RTE_GROUP)
976  {
977  /* Preprocess the groupexprs list fully */
978  rte->groupexprs = (List *)
979  preprocess_expression(root, (Node *) rte->groupexprs,
981  }
982 
983  /*
984  * Process each element of the securityQuals list as if it were a
985  * separate qual expression (as indeed it is). We need to do it this
986  * way to get proper canonicalization of AND/OR structure. Note that
987  * this converts each element into an implicit-AND sublist.
988  */
989  foreach(lcsq, rte->securityQuals)
990  {
992  (Node *) lfirst(lcsq),
993  EXPRKIND_QUAL);
994  }
995  }
996 
997  /*
998  * Now that we are done preprocessing expressions, and in particular done
999  * flattening join alias variables, get rid of the joinaliasvars lists.
1000  * They no longer match what expressions in the rest of the tree look
1001  * like, because we have not preprocessed expressions in those lists (and
1002  * do not want to; for example, expanding a SubLink there would result in
1003  * a useless unreferenced subplan). Leaving them in place simply creates
1004  * a hazard for later scans of the tree. We could try to prevent that by
1005  * using QTW_IGNORE_JOINALIASES in every tree scan done after this point,
1006  * but that doesn't sound very reliable.
1007  */
1008  if (root->hasJoinRTEs)
1009  {
1010  foreach(l, parse->rtable)
1011  {
1013 
1014  rte->joinaliasvars = NIL;
1015  }
1016  }
1017 
1018  /*
1019  * Replace any Vars in the subquery's targetlist and havingQual that
1020  * reference GROUP outputs with the underlying grouping expressions.
1021  *
1022  * Note that we need to perform this replacement after we've preprocessed
1023  * the grouping expressions. This is to ensure that there is only one
1024  * instance of SubPlan for each SubLink contained within the grouping
1025  * expressions.
1026  */
1027  if (parse->hasGroupRTE)
1028  {
1029  parse->targetList = (List *)
1030  flatten_group_exprs(root, root->parse, (Node *) parse->targetList);
1031  parse->havingQual =
1032  flatten_group_exprs(root, root->parse, parse->havingQual);
1033  }
1034 
1035  /* Constant-folding might have removed all set-returning functions */
1036  if (parse->hasTargetSRFs)
1037  parse->hasTargetSRFs = expression_returns_set((Node *) parse->targetList);
1038 
1039  /*
1040  * In some cases we may want to transfer a HAVING clause into WHERE. We
1041  * cannot do so if the HAVING clause contains aggregates (obviously) or
1042  * volatile functions (since a HAVING clause is supposed to be executed
1043  * only once per group). We also can't do this if there are any nonempty
1044  * grouping sets and the clause references any columns that are nullable
1045  * by the grouping sets; moving such a clause into WHERE would potentially
1046  * change the results. (If there are only empty grouping sets, then the
1047  * HAVING clause must be degenerate as discussed below.)
1048  *
1049  * Also, it may be that the clause is so expensive to execute that we're
1050  * better off doing it only once per group, despite the loss of
1051  * selectivity. This is hard to estimate short of doing the entire
1052  * planning process twice, so we use a heuristic: clauses containing
1053  * subplans are left in HAVING. Otherwise, we move or copy the HAVING
1054  * clause into WHERE, in hopes of eliminating tuples before aggregation
1055  * instead of after.
1056  *
1057  * If the query has explicit grouping then we can simply move such a
1058  * clause into WHERE; any group that fails the clause will not be in the
1059  * output because none of its tuples will reach the grouping or
1060  * aggregation stage. Otherwise we must have a degenerate (variable-free)
1061  * HAVING clause, which we put in WHERE so that query_planner() can use it
1062  * in a gating Result node, but also keep in HAVING to ensure that we
1063  * don't emit a bogus aggregated row. (This could be done better, but it
1064  * seems not worth optimizing.)
1065  *
1066  * Note that a HAVING clause may contain expressions that are not fully
1067  * preprocessed. This can happen if these expressions are part of
1068  * grouping items. In such cases, they are replaced with GROUP Vars in
1069  * the parser and then replaced back after we've done with expression
1070  * preprocessing on havingQual. This is not an issue if the clause
1071  * remains in HAVING, because these expressions will be matched to lower
1072  * target items in setrefs.c. However, if the clause is moved or copied
1073  * into WHERE, we need to ensure that these expressions are fully
1074  * preprocessed.
1075  *
1076  * Note that both havingQual and parse->jointree->quals are in
1077  * implicitly-ANDed-list form at this point, even though they are declared
1078  * as Node *.
1079  */
1080  newHaving = NIL;
1081  foreach(l, (List *) parse->havingQual)
1082  {
1083  Node *havingclause = (Node *) lfirst(l);
1084 
1085  if (contain_agg_clause(havingclause) ||
1086  contain_volatile_functions(havingclause) ||
1087  contain_subplans(havingclause) ||
1088  (parse->groupClause && parse->groupingSets &&
1089  bms_is_member(root->group_rtindex, pull_varnos(root, havingclause))))
1090  {
1091  /* keep it in HAVING */
1092  newHaving = lappend(newHaving, havingclause);
1093  }
1094  else if (parse->groupClause)
1095  {
1096  Node *whereclause;
1097 
1098  /* Preprocess the HAVING clause fully */
1099  whereclause = preprocess_expression(root, havingclause,
1100  EXPRKIND_QUAL);
1101  /* ... and move it to WHERE */
1102  parse->jointree->quals = (Node *)
1103  list_concat((List *) parse->jointree->quals,
1104  (List *) whereclause);
1105  }
1106  else
1107  {
1108  Node *whereclause;
1109 
1110  /* Preprocess the HAVING clause fully */
1111  whereclause = preprocess_expression(root, copyObject(havingclause),
1112  EXPRKIND_QUAL);
1113  /* ... and put a copy in WHERE */
1114  parse->jointree->quals = (Node *)
1115  list_concat((List *) parse->jointree->quals,
1116  (List *) whereclause);
1117  /* ... and also keep it in HAVING */
1118  newHaving = lappend(newHaving, havingclause);
1119  }
1120  }
1121  parse->havingQual = (Node *) newHaving;
1122 
1123  /*
1124  * If we have any outer joins, try to reduce them to plain inner joins.
1125  * This step is most easily done after we've done expression
1126  * preprocessing.
1127  */
1128  if (hasOuterJoins)
1130 
1131  /*
1132  * If we have any RTE_RESULT relations, see if they can be deleted from
1133  * the jointree. We also rely on this processing to flatten single-child
1134  * FromExprs underneath outer joins. This step is most effectively done
1135  * after we've done expression preprocessing and outer join reduction.
1136  */
1137  if (hasResultRTEs || hasOuterJoins)
1139 
1140  /*
1141  * Do the main planning.
1142  */
1143  grouping_planner(root, tuple_fraction, setops);
1144 
1145  /*
1146  * Capture the set of outer-level param IDs we have access to, for use in
1147  * extParam/allParam calculations later.
1148  */
1150 
1151  /*
1152  * If any initPlans were created in this query level, adjust the surviving
1153  * Paths' costs and parallel-safety flags to account for them. The
1154  * initPlans won't actually get attached to the plan tree till
1155  * create_plan() runs, but we must include their effects now.
1156  */
1157  final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
1158  SS_charge_for_initplans(root, final_rel);
1159 
1160  /*
1161  * Make sure we've identified the cheapest Path for the final rel. (By
1162  * doing this here not in grouping_planner, we include initPlan costs in
1163  * the decision, though it's unlikely that will change anything.)
1164  */
1165  set_cheapest(final_rel);
1166 
1167  return root;
1168 }
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:510
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:216
#define Max(x, y)
Definition: c.h:1001
bool contain_agg_clause(Node *clause)
Definition: clauses.c:177
bool contain_subplans(Node *clause)
Definition: clauses.c:330
bool contain_volatile_functions(Node *clause)
Definition: clauses.c:538
List * lappend(List *list, void *datum)
Definition: list.c:339
List * list_concat(List *list1, const List *list2)
Definition: list.c:561
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:758
#define copyObject(obj)
Definition: nodes.h:224
#define IS_OUTER_JOIN(jointype)
Definition: nodes.h:338
int assign_special_exec_param(PlannerInfo *root)
Definition: paramassign.c:664
@ RTE_JOIN
Definition: parsenodes.h:1019
@ RTE_VALUES
Definition: parsenodes.h:1022
@ RTE_SUBQUERY
Definition: parsenodes.h:1018
@ RTE_RESULT
Definition: parsenodes.h:1025
@ RTE_FUNCTION
Definition: parsenodes.h:1020
@ RTE_TABLEFUNC
Definition: parsenodes.h:1021
@ RTE_GROUP
Definition: parsenodes.h:1028
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:269
bool has_subclass(Oid relationId)
Definition: pg_inherits.c:355
#define list_make1(x1)
Definition: pg_list.h:212
static int list_cell_number(const List *l, const ListCell *c)
Definition: pg_list.h:333
#define EXPRKIND_TABLEFUNC_LATERAL
Definition: planner.c:91
#define EXPRKIND_TARGET
Definition: planner.c:80
#define EXPRKIND_APPINFO
Definition: planner.c:86
static void preprocess_rowmarks(PlannerInfo *root)
Definition: planner.c:2316
#define EXPRKIND_TABLESAMPLE
Definition: planner.c:88
#define EXPRKIND_GROUPEXPR
Definition: planner.c:92
static void preprocess_qual_conditions(PlannerInfo *root, Node *jtnode)
Definition: planner.c:1279
#define EXPRKIND_RTFUNC_LATERAL
Definition: planner.c:82
#define EXPRKIND_VALUES_LATERAL
Definition: planner.c:84
#define EXPRKIND_LIMIT
Definition: planner.c:85
#define EXPRKIND_VALUES
Definition: planner.c:83
#define EXPRKIND_QUAL
Definition: planner.c:79
static void grouping_planner(PlannerInfo *root, double tuple_fraction, SetOperationStmt *setops)
Definition: planner.c:1356
#define EXPRKIND_TABLEFUNC
Definition: planner.c:90
#define EXPRKIND_RTFUNC
Definition: planner.c:81
#define EXPRKIND_ARBITER_ELEM
Definition: planner.c:89
void preprocess_function_rtes(PlannerInfo *root)
Definition: prepjointree.c:871
void flatten_simple_union_all(PlannerInfo *root)
void transform_MERGE_to_join(Query *parse)
Definition: prepjointree.c:152
void remove_useless_result_rtes(PlannerInfo *root)
void pull_up_sublinks(PlannerInfo *root)
Definition: prepjointree.c:437
void replace_empty_jointree(Query *parse)
Definition: prepjointree.c:379
void pull_up_subqueries(PlannerInfo *root)
Definition: prepjointree.c:912
void reduce_outer_joins(PlannerInfo *root)
Definition: pg_list.h:54
Index query_level
Definition: pathnodes.h:208
TableFunc * tablefunc
Definition: parsenodes.h:1184
struct TableSampleClause * tablesample
Definition: parsenodes.h:1098
Query * subquery
Definition: parsenodes.h:1104
List * values_lists
Definition: parsenodes.h:1190
JoinType jointype
Definition: parsenodes.h:1151
List * functions
Definition: parsenodes.h:1177
Node * startOffset
Definition: parsenodes.h:1547
Node * endOffset
Definition: parsenodes.h:1548
void SS_process_ctes(PlannerInfo *root)
Definition: subselect.c:880
void SS_identify_outer_params(PlannerInfo *root)
Definition: subselect.c:2096
void SS_charge_for_initplans(PlannerInfo *root, RelOptInfo *final_rel)
Definition: subselect.c:2158
Relids pull_varnos(PlannerInfo *root, Node *node)
Definition: var.c:113
Node * flatten_join_alias_vars(PlannerInfo *root, Query *query, Node *node)
Definition: var.c:749
Node * flatten_group_exprs(PlannerInfo *root, Query *query, Node *node)
Definition: var.c:929

References generate_unaccent_rules::action, Assert, assign_special_exec_param(), bms_is_member(), bms_make_singleton(), contain_agg_clause(), contain_subplans(), contain_volatile_functions(), copyObject, CurrentMemoryContext, WindowClause::endOffset, expression_returns_set(), EXPRKIND_APPINFO, EXPRKIND_ARBITER_ELEM, EXPRKIND_GROUPEXPR, 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_group_exprs(), flatten_join_alias_vars(), flatten_simple_union_all(), RangeTblEntry::functions, grouping_planner(), has_subclass(), RangeTblEntry::inh, IS_OUTER_JOIN, RangeTblEntry::jointype, lappend(), lfirst, lfirst_node, list_cell_number(), list_concat(), list_length(), list_make1, makeNode, Max, NIL, parse(), preprocess_expression(), preprocess_function_rtes(), preprocess_qual_conditions(), preprocess_rowmarks(), pull_up_sublinks(), pull_up_subqueries(), pull_varnos(), WithCheckOption::qual, PlannerInfo::query_level, reduce_outer_joins(), RangeTblEntry::relid, remove_useless_result_rtes(), replace_empty_jointree(), root, rt_fetch, RTE_FUNCTION, RTE_GROUP, RTE_JOIN, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, set_cheapest(), SS_charge_for_initplans(), SS_identify_outer_params(), SS_process_ctes(), WindowClause::startOffset, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, transform_MERGE_to_join(), UPPERREL_FINAL, and RangeTblEntry::values_lists.

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

Variable Documentation

◆ create_upper_paths_hook

◆ planner_hook

PGDLLIMPORT planner_hook_type planner_hook
extern

Definition at line 72 of file planner.c.

Referenced by _PG_init(), and planner().