PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
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 6483 of file planner.c.

6484{
6485 Path *best_path = rel->cheapest_total_path;
6486 ListCell *l;
6487
6488 /* If all tuples will be retrieved, just return the cheapest-total path */
6489 if (tuple_fraction <= 0.0)
6490 return best_path;
6491
6492 /* Convert absolute # of tuples to a fraction; no need to clamp to 0..1 */
6493 if (tuple_fraction >= 1.0 && best_path->rows > 0)
6494 tuple_fraction /= best_path->rows;
6495
6496 foreach(l, rel->pathlist)
6497 {
6498 Path *path = (Path *) lfirst(l);
6499
6500 if (path->param_info)
6501 continue;
6502
6503 if (path == rel->cheapest_total_path ||
6504 compare_fractional_path_costs(best_path, path, tuple_fraction) <= 0)
6505 continue;
6506
6507 best_path = path;
6508 }
6509
6510 return best_path;
6511}
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:1796
List * pathlist
Definition: pathnodes.h:925
struct Path * cheapest_total_path
Definition: pathnodes.h:929

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

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

◆ limit_needed()

bool limit_needed ( Query parse)

Definition at line 2706 of file planner.c.

2707{
2708 Node *node;
2709
2710 node = parse->limitCount;
2711 if (node)
2712 {
2713 if (IsA(node, Const))
2714 {
2715 /* NULL indicates LIMIT ALL, ie, no limit */
2716 if (!((Const *) node)->constisnull)
2717 return true; /* LIMIT with a constant value */
2718 }
2719 else
2720 return true; /* non-constant LIMIT */
2721 }
2722
2723 node = parse->limitOffset;
2724 if (node)
2725 {
2726 if (IsA(node, Const))
2727 {
2728 /* Treat NULL as no offset; the executor would too */
2729 if (!((Const *) node)->constisnull)
2730 {
2731 int64 offset = DatumGetInt64(((Const *) node)->constvalue);
2732
2733 if (offset != 0)
2734 return true; /* OFFSET with a nonzero value */
2735 }
2736 }
2737 else
2738 return true; /* non-constant OFFSET */
2739 }
2740
2741 return false; /* don't need a Limit plan node */
2742}
int64_t int64
Definition: c.h:499
#define IsA(nodeptr, _type_)
Definition: nodes.h:164
static int64 DatumGetInt64(Datum X)
Definition: postgres.h:390
static struct subre * parse(struct vars *v, int stopper, int type, struct state *init, struct state *final)
Definition: regcomp.c:717
Definition: nodes.h:135

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

5645{
5646 /* aggtranstype should be computed by this point */
5647 Assert(OidIsValid(agg->aggtranstype));
5648 /* ... but aggsplit should still be as the parser left it */
5649 Assert(agg->aggsplit == AGGSPLIT_SIMPLE);
5650
5651 /* Mark the Aggref with the intended partial-aggregation mode */
5652 agg->aggsplit = aggsplit;
5653
5654 /*
5655 * Adjust result type if needed. Normally, a partial aggregate returns
5656 * the aggregate's transition type; but if that's INTERNAL and we're
5657 * serializing, it returns BYTEA instead.
5658 */
5659 if (DO_AGGSPLIT_SKIPFINAL(aggsplit))
5660 {
5661 if (agg->aggtranstype == INTERNALOID && DO_AGGSPLIT_SERIALIZE(aggsplit))
5662 agg->aggtype = BYTEAOID;
5663 else
5664 agg->aggtype = agg->aggtranstype;
5665 }
5666}
#define OidIsValid(objectId)
Definition: c.h:746
Assert(PointerIsAligned(start, uint64))
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:392
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:393
@ AGGSPLIT_SIMPLE
Definition: nodes.h:383

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

1349{
1350 return (Expr *) preprocess_expression(root, (Node *) expr, EXPRKIND_PHV);
1351}
#define EXPRKIND_PHV
Definition: planner.c:88
static Node * preprocess_expression(PlannerInfo *root, Node *expr, int kind)
Definition: planner.c:1202
tree ctl root
Definition: radixtree.h:1857

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

2456{
2457 if (rte->rtekind != RTE_RELATION)
2458 {
2459 /* If it's not a table at all, use ROW_MARK_COPY */
2460 return ROW_MARK_COPY;
2461 }
2462 else if (rte->relkind == RELKIND_FOREIGN_TABLE)
2463 {
2464 /* Let the FDW select the rowmark type, if it wants to */
2465 FdwRoutine *fdwroutine = GetFdwRoutineByRelId(rte->relid);
2466
2467 if (fdwroutine->GetForeignRowMarkType != NULL)
2468 return fdwroutine->GetForeignRowMarkType(rte, strength);
2469 /* Otherwise, use ROW_MARK_COPY by default */
2470 return ROW_MARK_COPY;
2471 }
2472 else
2473 {
2474 /* Regular table, apply the appropriate lock type */
2475 switch (strength)
2476 {
2477 case LCS_NONE:
2478
2479 /*
2480 * We don't need a tuple lock, only the ability to re-fetch
2481 * the row.
2482 */
2483 return ROW_MARK_REFERENCE;
2484 break;
2485 case LCS_FORKEYSHARE:
2486 return ROW_MARK_KEYSHARE;
2487 break;
2488 case LCS_FORSHARE:
2489 return ROW_MARK_SHARE;
2490 break;
2491 case LCS_FORNOKEYUPDATE:
2493 break;
2494 case LCS_FORUPDATE:
2495 return ROW_MARK_EXCLUSIVE;
2496 break;
2497 }
2498 elog(ERROR, "unrecognized LockClauseStrength %d", (int) strength);
2499 return ROW_MARK_EXCLUSIVE; /* keep compiler quiet */
2500 }
2501}
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
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:1026
@ ROW_MARK_COPY
Definition: plannodes.h:1491
@ ROW_MARK_REFERENCE
Definition: plannodes.h:1490
@ ROW_MARK_SHARE
Definition: plannodes.h:1488
@ ROW_MARK_EXCLUSIVE
Definition: plannodes.h:1486
@ ROW_MARK_NOKEYEXCLUSIVE
Definition: plannodes.h:1487
@ ROW_MARK_KEYSHARE
Definition: plannodes.h:1489
GetForeignRowMarkType_function GetForeignRowMarkType
Definition: fdwapi.h:247
RTEKind rtekind
Definition: parsenodes.h:1061

References elog, ERROR, GetFdwRoutineByRelId(), FdwRoutine::GetForeignRowMarkType, LCS_FORKEYSHARE, LCS_FORNOKEYUPDATE, LCS_FORSHARE, LCS_FORUPDATE, LCS_NONE, 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 302 of file planner.c.

304{
305 PlannedStmt *result;
306 PlannerGlobal *glob;
307 double tuple_fraction;
309 RelOptInfo *final_rel;
310 Path *best_path;
311 Plan *top_plan;
312 ListCell *lp,
313 *lr;
314
315 /*
316 * Set up global state for this planner invocation. This data is needed
317 * across all levels of sub-Query that might exist in the given command,
318 * so we keep it in a separate struct that's linked to by each per-Query
319 * PlannerInfo.
320 */
321 glob = makeNode(PlannerGlobal);
322
323 glob->boundParams = boundParams;
324 glob->subplans = NIL;
325 glob->subpaths = NIL;
326 glob->subroots = NIL;
327 glob->rewindPlanIDs = NULL;
328 glob->finalrtable = NIL;
329 glob->finalrteperminfos = NIL;
330 glob->finalrowmarks = NIL;
331 glob->resultRelations = NIL;
332 glob->appendRelations = NIL;
333 glob->relationOids = NIL;
334 glob->invalItems = NIL;
335 glob->paramExecTypes = NIL;
336 glob->lastPHId = 0;
337 glob->lastRowMarkId = 0;
338 glob->lastPlanNodeId = 0;
339 glob->transientPlan = false;
340 glob->dependsOnRole = false;
341
342 /*
343 * Assess whether it's feasible to use parallel mode for this query. We
344 * can't do this in a standalone backend, or if the command will try to
345 * modify any data, or if this is a cursor operation, or if GUCs are set
346 * to values that don't permit parallelism, or if parallel-unsafe
347 * functions are present in the query tree.
348 *
349 * (Note that we do allow CREATE TABLE AS, SELECT INTO, and CREATE
350 * MATERIALIZED VIEW to use parallel plans, but this is safe only because
351 * the command is writing into a completely new table which workers won't
352 * be able to see. If the workers could see the table, the fact that
353 * group locking would cause them to ignore the leader's heavyweight GIN
354 * page locks would make this unsafe. We'll have to fix that somehow if
355 * we want to allow parallel inserts in general; updates and deletes have
356 * additional problems especially around combo CIDs.)
357 *
358 * For now, we don't try to use parallel mode if we're running inside a
359 * parallel worker. We might eventually be able to relax this
360 * restriction, but for now it seems best not to have parallel workers
361 * trying to create their own parallel workers.
362 */
363 if ((cursorOptions & CURSOR_OPT_PARALLEL_OK) != 0 &&
365 parse->commandType == CMD_SELECT &&
366 !parse->hasModifyingCTE &&
369 {
370 /* all the cheap tests pass, so scan the query tree */
372 glob->parallelModeOK = (glob->maxParallelHazard != PROPARALLEL_UNSAFE);
373 }
374 else
375 {
376 /* skip the query tree scan, just assume it's unsafe */
377 glob->maxParallelHazard = PROPARALLEL_UNSAFE;
378 glob->parallelModeOK = false;
379 }
380
381 /*
382 * glob->parallelModeNeeded is normally set to false here and changed to
383 * true during plan creation if a Gather or Gather Merge plan is actually
384 * created (cf. create_gather_plan, create_gather_merge_plan).
385 *
386 * However, if debug_parallel_query = on or debug_parallel_query =
387 * regress, then we impose parallel mode whenever it's safe to do so, even
388 * if the final plan doesn't use parallelism. It's not safe to do so if
389 * the query contains anything parallel-unsafe; parallelModeOK will be
390 * false in that case. Note that parallelModeOK can't change after this
391 * point. Otherwise, everything in the query is either parallel-safe or
392 * parallel-restricted, and in either case it should be OK to impose
393 * parallel-mode restrictions. If that ends up breaking something, then
394 * either some function the user included in the query is incorrectly
395 * labeled as parallel-safe or parallel-restricted when in reality it's
396 * parallel-unsafe, or else the query planner itself has a bug.
397 */
398 glob->parallelModeNeeded = glob->parallelModeOK &&
400
401 /* Determine what fraction of the plan is likely to be scanned */
402 if (cursorOptions & CURSOR_OPT_FAST_PLAN)
403 {
404 /*
405 * We have no real idea how many tuples the user will ultimately FETCH
406 * from a cursor, but it is often the case that he doesn't want 'em
407 * all, or would prefer a fast-start plan anyway so that he can
408 * process some of the tuples sooner. Use a GUC parameter to decide
409 * what fraction to optimize for.
410 */
411 tuple_fraction = cursor_tuple_fraction;
412
413 /*
414 * We document cursor_tuple_fraction as simply being a fraction, which
415 * means the edge cases 0 and 1 have to be treated specially here. We
416 * convert 1 to 0 ("all the tuples") and 0 to a very small fraction.
417 */
418 if (tuple_fraction >= 1.0)
419 tuple_fraction = 0.0;
420 else if (tuple_fraction <= 0.0)
421 tuple_fraction = 1e-10;
422 }
423 else
424 {
425 /* Default assumption is we need all the tuples */
426 tuple_fraction = 0.0;
427 }
428
429 /* primary planning entry point (may recurse for subqueries) */
430 root = subquery_planner(glob, parse, NULL, false, tuple_fraction, NULL);
431
432 /* Select best Path and turn it into a Plan */
433 final_rel = fetch_upper_rel(root, UPPERREL_FINAL, NULL);
434 best_path = get_cheapest_fractional_path(final_rel, tuple_fraction);
435
436 top_plan = create_plan(root, best_path);
437
438 /*
439 * If creating a plan for a scrollable cursor, make sure it can run
440 * backwards on demand. Add a Material node at the top at need.
441 */
442 if (cursorOptions & CURSOR_OPT_SCROLL)
443 {
444 if (!ExecSupportsBackwardScan(top_plan))
445 top_plan = materialize_finished_plan(top_plan);
446 }
447
448 /*
449 * Optionally add a Gather node for testing purposes, provided this is
450 * actually a safe thing to do.
451 *
452 * We can add Gather even when top_plan has parallel-safe initPlans, but
453 * then we have to move the initPlans to the Gather node because of
454 * SS_finalize_plan's limitations. That would cause cosmetic breakage of
455 * regression tests when debug_parallel_query = regress, because initPlans
456 * that would normally appear on the top_plan move to the Gather, causing
457 * them to disappear from EXPLAIN output. That doesn't seem worth kluging
458 * EXPLAIN to hide, so skip it when debug_parallel_query = regress.
459 */
461 top_plan->parallel_safe &&
462 (top_plan->initPlan == NIL ||
464 {
465 Gather *gather = makeNode(Gather);
466 Cost initplan_cost;
467 bool unsafe_initplans;
468
469 gather->plan.targetlist = top_plan->targetlist;
470 gather->plan.qual = NIL;
471 gather->plan.lefttree = top_plan;
472 gather->plan.righttree = NULL;
473 gather->num_workers = 1;
474 gather->single_copy = true;
476
477 /* Transfer any initPlans to the new top node */
478 gather->plan.initPlan = top_plan->initPlan;
479 top_plan->initPlan = NIL;
480
481 /*
482 * Since this Gather has no parallel-aware descendants to signal to,
483 * we don't need a rescan Param.
484 */
485 gather->rescan_param = -1;
486
487 /*
488 * Ideally we'd use cost_gather here, but setting up dummy path data
489 * to satisfy it doesn't seem much cleaner than knowing what it does.
490 */
491 gather->plan.startup_cost = top_plan->startup_cost +
493 gather->plan.total_cost = top_plan->total_cost +
495 gather->plan.plan_rows = top_plan->plan_rows;
496 gather->plan.plan_width = top_plan->plan_width;
497 gather->plan.parallel_aware = false;
498 gather->plan.parallel_safe = false;
499
500 /*
501 * Delete the initplans' cost from top_plan. We needn't add it to the
502 * Gather node, since the above coding already included it there.
503 */
505 &initplan_cost, &unsafe_initplans);
506 top_plan->startup_cost -= initplan_cost;
507 top_plan->total_cost -= initplan_cost;
508
509 /* use parallel mode for parallel plans. */
510 root->glob->parallelModeNeeded = true;
511
512 top_plan = &gather->plan;
513 }
514
515 /*
516 * If any Params were generated, run through the plan tree and compute
517 * each plan node's extParam/allParam sets. Ideally we'd merge this into
518 * set_plan_references' tree traversal, but for now it has to be separate
519 * because we need to visit subplans before not after main plan.
520 */
521 if (glob->paramExecTypes != NIL)
522 {
523 Assert(list_length(glob->subplans) == list_length(glob->subroots));
524 forboth(lp, glob->subplans, lr, glob->subroots)
525 {
526 Plan *subplan = (Plan *) lfirst(lp);
527 PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
528
529 SS_finalize_plan(subroot, subplan);
530 }
531 SS_finalize_plan(root, top_plan);
532 }
533
534 /* final cleanup of the plan */
535 Assert(glob->finalrtable == NIL);
536 Assert(glob->finalrteperminfos == NIL);
537 Assert(glob->finalrowmarks == NIL);
538 Assert(glob->resultRelations == NIL);
539 Assert(glob->appendRelations == NIL);
540 top_plan = set_plan_references(root, top_plan);
541 /* ... and the subplans (both regular subplans and initplans) */
542 Assert(list_length(glob->subplans) == list_length(glob->subroots));
543 forboth(lp, glob->subplans, lr, glob->subroots)
544 {
545 Plan *subplan = (Plan *) lfirst(lp);
546 PlannerInfo *subroot = lfirst_node(PlannerInfo, lr);
547
548 lfirst(lp) = set_plan_references(subroot, subplan);
549 }
550
551 /* build the PlannedStmt result */
552 result = makeNode(PlannedStmt);
553
554 result->commandType = parse->commandType;
555 result->queryId = parse->queryId;
556 result->hasReturning = (parse->returningList != NIL);
557 result->hasModifyingCTE = parse->hasModifyingCTE;
558 result->canSetTag = parse->canSetTag;
559 result->transientPlan = glob->transientPlan;
560 result->dependsOnRole = glob->dependsOnRole;
562 result->planTree = top_plan;
563 result->partPruneInfos = glob->partPruneInfos;
564 result->rtable = glob->finalrtable;
566 glob->prunableRelids);
567 result->permInfos = glob->finalrteperminfos;
568 result->resultRelations = glob->resultRelations;
569 result->firstResultRels = glob->firstResultRels;
570 result->appendRelations = glob->appendRelations;
571 result->subplans = glob->subplans;
572 result->rewindPlanIDs = glob->rewindPlanIDs;
573 result->rowMarks = glob->finalrowmarks;
574 result->relationOids = glob->relationOids;
575 result->invalItems = glob->invalItems;
576 result->paramExecTypes = glob->paramExecTypes;
577 /* utilityStmt should be null, but we might as well copy it */
578 result->utilityStmt = parse->utilityStmt;
579 result->stmt_location = parse->stmt_location;
580 result->stmt_len = parse->stmt_len;
581
582 result->jitFlags = PGJIT_NONE;
583 if (jit_enabled && jit_above_cost >= 0 &&
584 top_plan->total_cost > jit_above_cost)
585 {
586 result->jitFlags |= PGJIT_PERFORM;
587
588 /*
589 * Decide how much effort should be put into generating better code.
590 */
591 if (jit_optimize_above_cost >= 0 &&
593 result->jitFlags |= PGJIT_OPT3;
594 if (jit_inline_above_cost >= 0 &&
596 result->jitFlags |= PGJIT_INLINE;
597
598 /*
599 * Decide which operations should be JITed.
600 */
601 if (jit_expressions)
602 result->jitFlags |= PGJIT_EXPR;
604 result->jitFlags |= PGJIT_DEFORM;
605 }
606
607 if (glob->partition_directory != NULL)
608 DestroyPartitionDirectory(glob->partition_directory);
609
610 return result;
611}
Bitmapset * bms_difference(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:346
char max_parallel_hazard(Query *parse)
Definition: clauses.c:735
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 * materialize_finished_plan(Plan *subplan)
Definition: createplan.c:6594
Plan * create_plan(PlannerInfo *root, Path *best_path)
Definition: createplan.c:337
bool ExecSupportsBackwardScan(Plan *node)
Definition: execAmi.c:511
bool IsUnderPostmaster
Definition: globals.c:121
#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:257
@ CMD_SELECT
Definition: nodes.h:271
#define makeNode(_type_)
Definition: nodes.h:161
@ DEBUG_PARALLEL_REGRESS
Definition: optimizer.h:108
@ DEBUG_PARALLEL_OFF
Definition: optimizer.h:106
#define CURSOR_OPT_SCROLL
Definition: parsenodes.h:3376
#define CURSOR_OPT_FAST_PLAN
Definition: parsenodes.h:3382
#define CURSOR_OPT_PARALLEL_OK
Definition: parsenodes.h:3385
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
double cursor_tuple_fraction
Definition: planner.c:67
Path * get_cheapest_fractional_path(RelOptInfo *rel, double tuple_fraction)
Definition: planner.c:6483
PlannerInfo * subquery_planner(PlannerGlobal *glob, Query *parse, PlannerInfo *parent_root, bool hasRecursion, double tuple_fraction, SetOperationStmt *setops)
Definition: planner.c:647
int debug_parallel_query
Definition: planner.c:68
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:1289
bool invisible
Definition: plannodes.h:1295
bool single_copy
Definition: plannodes.h:1293
Plan plan
Definition: plannodes.h:1287
int rescan_param
Definition: plannodes.h:1291
struct Plan * lefttree
Definition: plannodes.h:213
Cost total_cost
Definition: plannodes.h:179
struct Plan * righttree
Definition: plannodes.h:214
bool parallel_aware
Definition: plannodes.h:193
Cost startup_cost
Definition: plannodes.h:177
List * qual
Definition: plannodes.h:211
int plan_width
Definition: plannodes.h:187
bool parallel_safe
Definition: plannodes.h:195
Cardinality plan_rows
Definition: plannodes.h:185
List * targetlist
Definition: plannodes.h:209
List * initPlan
Definition: plannodes.h:216
struct Plan * planTree
Definition: plannodes.h:83
List * firstResultRels
Definition: plannodes.h:113
bool hasModifyingCTE
Definition: plannodes.h:65
List * appendRelations
Definition: plannodes.h:116
List * permInfos
Definition: plannodes.h:102
bool canSetTag
Definition: plannodes.h:68
List * rowMarks
Definition: plannodes.h:127
int jitFlags
Definition: plannodes.h:80
Bitmapset * rewindPlanIDs
Definition: plannodes.h:124
ParseLoc stmt_len
Definition: plannodes.h:145
bool hasReturning
Definition: plannodes.h:62
ParseLoc stmt_location
Definition: plannodes.h:143
List * invalItems
Definition: plannodes.h:133
bool transientPlan
Definition: plannodes.h:71
List * resultRelations
Definition: plannodes.h:106
List * subplans
Definition: plannodes.h:121
List * relationOids
Definition: plannodes.h:130
bool dependsOnRole
Definition: plannodes.h:74
Bitmapset * unprunableRelids
Definition: plannodes.h:97
CmdType commandType
Definition: plannodes.h:53
Node * utilityStmt
Definition: plannodes.h:139
List * rtable
Definition: plannodes.h:91
List * partPruneInfos
Definition: plannodes.h:88
List * paramExecTypes
Definition: plannodes.h:136
bool parallelModeNeeded
Definition: plannodes.h:77
uint64 queryId
Definition: plannodes.h:56
Bitmapset * prunableRelids
Definition: pathnodes.h:130
int lastPlanNodeId
Definition: pathnodes.h:166
char maxParallelHazard
Definition: pathnodes.h:181
List * subplans
Definition: pathnodes.h:105
bool dependsOnRole
Definition: pathnodes.h:172
Bitmapset * allRelids
Definition: pathnodes.h:123
List * appendRelations
Definition: pathnodes.h:145
List * finalrowmarks
Definition: pathnodes.h:136
List * invalItems
Definition: pathnodes.h:154
List * relationOids
Definition: pathnodes.h:151
List * paramExecTypes
Definition: pathnodes.h:157
bool parallelModeOK
Definition: pathnodes.h:175
bool transientPlan
Definition: pathnodes.h:169
Bitmapset * rewindPlanIDs
Definition: pathnodes.h:114
List * finalrteperminfos
Definition: pathnodes.h:133
List * subpaths
Definition: pathnodes.h:108
Index lastPHId
Definition: pathnodes.h:160
Index lastRowMarkId
Definition: pathnodes.h:163
List * resultRelations
Definition: pathnodes.h:139
List * partPruneInfos
Definition: pathnodes.h:148
List * finalrtable
Definition: pathnodes.h:117
List * firstResultRels
Definition: pathnodes.h:142
bool parallelModeNeeded
Definition: pathnodes.h:178
void SS_finalize_plan(PlannerInfo *root, Plan *plan)
Definition: subselect.c:2368
void SS_compute_initplan_cost(List *init_plans, Cost *initplan_cost_p, bool *unsafe_initplans_p)
Definition: subselect.c:2312

References PlannerGlobal::allRelids, PlannerGlobal::appendRelations, PlannedStmt::appendRelations, Assert(), bms_difference(), 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, PlannerGlobal::firstResultRels, PlannedStmt::firstResultRels, 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(), 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, PlannerGlobal::prunableRelids, 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, PlannedStmt::unprunableRelids, 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 647 of file planner.c.

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

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, expand_virtual_generated_columns(), 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(), 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 73 of file planner.c.

Referenced by _PG_init(), and planner().