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 5992 of file planner.c.

5993 {
5994  Path *best_path = rel->cheapest_total_path;
5995  ListCell *l;
5996 
5997  /* If all tuples will be retrieved, just return the cheapest-total path */
5998  if (tuple_fraction <= 0.0)
5999  return best_path;
6000 
6001  /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
6002  if (tuple_fraction >= 1.0 && best_path->rows > 0)
6003  tuple_fraction /= best_path->rows;
6004 
6005  foreach(l, rel->pathlist)
6006  {
6007  Path *path = (Path *) lfirst(l);
6008 
6009  if (path == rel->cheapest_total_path ||
6010  compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
6011  continue;
6012 
6013  best_path = path;
6014  }
6015 
6016  return best_path;
6017 }
int compare_fractional_path_costs(Path *path1, Path *path2, double fraction)
Definition: pathnode.c:117
#define lfirst(lc)
Definition: pg_list.h:170
Cardinality rows
Definition: pathnodes.h:1547
List * pathlist
Definition: pathnodes.h:851
struct Path * cheapest_total_path
Definition: pathnodes.h:855

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().

◆ limit_needed()

bool limit_needed ( Query parse)

Definition at line 2558 of file planner.c.

2559 {
2560  Node *node;
2561 
2562  node = parse->limitCount;
2563  if (node)
2564  {
2565  if (IsA(node, Const))
2566  {
2567  /* NULL indicates LIMIT ALL, ie, no limit */
2568  if (!((Const *) node)->constisnull)
2569  return true; /* LIMIT with a constant value */
2570  }
2571  else
2572  return true; /* non-constant LIMIT */
2573  }
2574 
2575  node = parse->limitOffset;
2576  if (node)
2577  {
2578  if (IsA(node, Const))
2579  {
2580  /* Treat NULL as no offset; the executor would too */
2581  if (!((Const *) node)->constisnull)
2582  {
2583  int64 offset = DatumGetInt64(((Const *) node)->constvalue);
2584 
2585  if (offset != 0)
2586  return true; /* OFFSET with a nonzero value */
2587  }
2588  }
2589  else
2590  return true; /* non-constant OFFSET */
2591  }
2592 
2593  return false; /* don't need a Limit plan node */
2594 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:168
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:733
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
Definition: nodes.h:118

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 5392 of file planner.c.

5393 {
5394  /* aggtranstype should be computed by this point */
5395  Assert(OidIsValid(agg->aggtranstype));
5396  /* ... but aggsplit should still be as the parser left it */
5397  Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
5398 
5399  /* Mark the Aggref with the intended partial-aggregation mode */
5400  agg->aggsplit = aggsplit;
5401 
5402  /*
5403  * Adjust result type if needed. Normally, a partial aggregate returns
5404  * the aggregate's transition type; but if that's INTERNAL and we're
5405  * serializing, it returns BYTEA instead.
5406  */
5407  if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
5408  {
5409  if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
5410  agg->aggtype = BYTEAOID;
5411  else
5412  agg->aggtype = agg->aggtranstype;
5413  }
5414 }
#define OidIsValid(objectId)
Definition: c.h:711
Assert(fmt[strlen(fmt) - 1] !='\n')
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:383
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:384
@ AGGSPLIT_SIMPLE
Definition: nodes.h:374
Oid aggtype
Definition: primnodes.h:376
AggSplit aggsplit
Definition: primnodes.h:427

References Aggref::aggsplit, AGGSPLIT_SIMPLE, Aggref::aggtype, 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 1231 of file planner.c.

1232 {
1233  return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1234 }
#define EXPRKIND_PHV
Definition: planner.c:91
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1085

References EXPRKIND_PHV, and preprocess_expression().

Referenced by extract_lateral_references().

◆ select_rowmark_type()

RowMarkType select_rowmark_type ( RangeTblEntry rte,
LockClauseStrength  strength 
)

Definition at line 2307 of file planner.c.

2308 {
2309  if (rte->rtekind != RTE_RELATION)
2310  {
2311  /* If it's not a table at all, use ROW_MARK_COPY */
2312  return ROW_MARK_COPY;
2313  }
2314  else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2315  {
2316  /* Let the FDW select the rowmark type, if it wants to */
2317  FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2318 
2319  if (fdwroutine->GetForeignRowMarkType != NULL)
2320  return fdwroutine->GetForeignRowMarkType(rte, strength);
2321  /* Otherwise, use ROW_MARK_COPY by default */
2322  return ROW_MARK_COPY;
2323  }
2324  else
2325  {
2326  /* Regular table, apply the appropriate lock type */
2327  switch (strength)
2328  {
2329  case LCS_NONE:
2330 
2331  /*
2332  * We don't need a tuple lock, only the ability to re-fetch
2333  * the row.
2334  */
2335  return ROW_MARK_REFERENCE;
2336  break;
2337  case LCS_FORKEYSHARE:
2338  return ROW_MARK_KEYSHARE;
2339  break;
2340  case LCS_FORSHARE:
2341  return ROW_MARK_SHARE;
2342  break;
2343  case LCS_FORNOKEYUPDATE:
2344  return ROW_MARK_NOKEYEXCLUSIVE;
2345  break;
2346  case LCS_FORUPDATE:
2347  return ROW_MARK_EXCLUSIVE;
2348  break;
2349  }
2350  elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2351  return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2352  }
2353 }
#define ERROR
Definition: elog.h:35
FdwRoutine * GetFdwRoutineByRelId(Oid relid)
Definition: foreign.c:406
@ 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:982
@ ROW_MARK_COPY
Definition: plannodes.h:1333
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1332
@ ROW_MARK_SHARE
Definition: plannodes.h:1330
@ ROW_MARK_EXCLUSIVE
Definition: plannodes.h:1328
@ ROW_MARK_NOKEYEXCLUSIVE
Definition: plannodes.h:1329
@ ROW_MARK_KEYSHARE
Definition: plannodes.h:1331
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:247
RTEKind rtekind
Definition: parsenodes.h:1001

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().

◆ standard_planner()

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

Definition at line 284 of file planner.c.

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

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, PlannerGlobal::dependsOnRole, PlannedStmt::dependsOnRole, DestroyPartitionDirectory(), ExecSupportsBackwardScan(), fetch_upper_rel(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerGlobal::finalrteperminfos, forboth, force_parallel_mode, FORCE_PARALLEL_OFF, FORCE_PARALLEL_REGRESS, get_cheapest_fractional_path(), PlannerInfo::glob, 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(), PlannerGlobal::partPruneInfos, PlannedStmt::partPruneInfos, 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, PlannedStmt::rowMarks, PlannedStmt::rtable, set_plan_references(), Gather::single_copy, SS_finalize_plan(), Plan::startup_cost, PlannedStmt::stmt_len, PlannedStmt::stmt_location, 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 
)

Definition at line 602 of file planner.c.

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

References generate_unaccent_rules::action, PlannerInfo::all_result_relids, PlannerInfo::append_rel_list, assign_special_exec_param(), bms_make_singleton(), contain_agg_clause(), contain_subplans(), contain_volatile_functions(), copyObject, PlannerInfo::cte_plan_ids, 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, grouping_planner(), has_subclass(), PlannerInfo::hasAlternativeSubPlans, PlannerInfo::hasHavingQual, PlannerInfo::hasJoinRTEs, PlannerInfo::hasLateralRTEs, PlannerInfo::hasPseudoConstantQuals, PlannerInfo::hasRecursion, RangeTblEntry::inh, PlannerInfo::init_plans, IS_OUTER_JOIN, RangeTblEntry::joinaliasvars, RangeTblEntry::jointype, lappend(), RangeTblEntry::lateral, PlannerInfo::leaf_result_relids, lfirst, lfirst_node, list_length(), makeNode, Max, PlannerInfo::minmax_aggs, PlannerInfo::multiexpr_params, NIL, PlannerInfo::non_recursive_path, PlannerInfo::outer_params, parse(), PlannerInfo::parse, PlannerInfo::partColsUpdated, PlannerInfo::placeholdersFrozen, PlannerInfo::plan_params, 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, PlannerInfo::query_level, reduce_outer_joins(), RangeTblEntry::relid, remove_useless_groupby_columns(), remove_useless_result_rtes(), replace_empty_jointree(), PlannerInfo::row_identity_vars, PlannerInfo::rowMarks, rt_fetch, RTE_FUNCTION, RTE_JOIN, RTE_RELATION, RTE_RESULT, RTE_SUBQUERY, RTE_TABLEFUNC, RTE_VALUES, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, 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(), PlannerInfo::update_colnos, UPPERREL_FINAL, RangeTblEntry::values_lists, and PlannerInfo::wt_param_id.

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 76 of file planner.c.

Referenced by _PG_init(), and planner().