PostgreSQL Source Code  git master
prep.h File Reference
#include "nodes/pathnodes.h"
#include "nodes/plannodes.h"
Include dependency graph for prep.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void replace_empty_jointree (Query *parse)
 
void pull_up_sublinks (PlannerInfo *root)
 
void preprocess_function_rtes (PlannerInfo *root)
 
void pull_up_subqueries (PlannerInfo *root)
 
void flatten_simple_union_all (PlannerInfo *root)
 
void reduce_outer_joins (PlannerInfo *root)
 
void remove_useless_result_rtes (PlannerInfo *root)
 
Relids get_relids_in_jointree (Node *jtnode, bool include_joins)
 
Relids get_relids_for_join (Query *query, int joinrelid)
 
void preprocess_targetlist (PlannerInfo *root)
 
Listextract_update_targetlist_colnos (List *tlist)
 
PlanRowMarkget_plan_rowmark (List *rowmarks, Index rtindex)
 
void get_agg_clause_costs (PlannerInfo *root, AggSplit aggsplit, AggClauseCosts *agg_costs)
 
void preprocess_aggrefs (PlannerInfo *root, Node *clause)
 
RelOptInfoplan_set_operations (PlannerInfo *root)
 

Function Documentation

◆ extract_update_targetlist_colnos()

List* extract_update_targetlist_colnos ( List tlist)

Definition at line 261 of file preptlist.c.

References lappend_int(), lfirst, NIL, TargetEntry::resjunk, and TargetEntry::resno.

Referenced by make_modifytable(), and preprocess_targetlist().

262 {
263  List *update_colnos = NIL;
264  AttrNumber nextresno = 1;
265  ListCell *lc;
266 
267  foreach(lc, tlist)
268  {
269  TargetEntry *tle = (TargetEntry *) lfirst(lc);
270 
271  if (!tle->resjunk)
272  update_colnos = lappend_int(update_colnos, tle->resno);
273  tle->resno = nextresno++;
274  }
275  return update_colnos;
276 }
#define NIL
Definition: pg_list.h:65
bool resjunk
Definition: primnodes.h:1451
AttrNumber resno
Definition: primnodes.h:1445
List * lappend_int(List *list, int datum)
Definition: list.c:354
#define lfirst(lc)
Definition: pg_list.h:169
Definition: pg_list.h:50
int16 AttrNumber
Definition: attnum.h:21

◆ flatten_simple_union_all()

void flatten_simple_union_all ( PlannerInfo root)

Definition at line 2456 of file prepjointree.c.

References Assert, castNode, copyObject, FromExpr::fromlist, PlannerInfo::hasRecursion, RangeTblEntry::inh, is_simple_union_all_recurse(), IsA, Query::jointree, lappend(), list_length(), list_make1, makeNode, NIL, parse(), PlannerInfo::parse, pull_up_union_leaf_queries(), rt_fetch, Query::rtable, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblRef::rtindex, and Query::setOperations.

Referenced by subquery_planner().

2457 {
2458  Query *parse = root->parse;
2459  SetOperationStmt *topop;
2460  Node *leftmostjtnode;
2461  int leftmostRTI;
2462  RangeTblEntry *leftmostRTE;
2463  int childRTI;
2464  RangeTblEntry *childRTE;
2465  RangeTblRef *rtr;
2466 
2467  /* Shouldn't be called unless query has setops */
2468  topop = castNode(SetOperationStmt, parse->setOperations);
2469  Assert(topop);
2470 
2471  /* Can't optimize away a recursive UNION */
2472  if (root->hasRecursion)
2473  return;
2474 
2475  /*
2476  * Recursively check the tree of set operations. If not all UNION ALL
2477  * with identical column types, punt.
2478  */
2479  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2480  return;
2481 
2482  /*
2483  * Locate the leftmost leaf query in the setops tree. The upper query's
2484  * Vars all refer to this RTE (see transformSetOperationStmt).
2485  */
2486  leftmostjtnode = topop->larg;
2487  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2488  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2489  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2490  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2491  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2492  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2493 
2494  /*
2495  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2496  * will represent the leftmost leaf query in its capacity as a member of
2497  * the appendrel. The original will represent the appendrel as a whole.
2498  * (We must do things this way because the upper query's Vars have to be
2499  * seen as referring to the whole appendrel.)
2500  */
2501  childRTE = copyObject(leftmostRTE);
2502  parse->rtable = lappend(parse->rtable, childRTE);
2503  childRTI = list_length(parse->rtable);
2504 
2505  /* Modify the setops tree to reference the child copy */
2506  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2507 
2508  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2509  leftmostRTE->inh = true;
2510 
2511  /*
2512  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2513  * Query of a setops tree should have had an empty FromClause initially.
2514  */
2515  rtr = makeNode(RangeTblRef);
2516  rtr->rtindex = leftmostRTI;
2517  Assert(parse->jointree->fromlist == NIL);
2518  parse->jointree->fromlist = list_make1(rtr);
2519 
2520  /*
2521  * Now pretend the query has no setops. We must do this before trying to
2522  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2523  */
2524  parse->setOperations = NULL;
2525 
2526  /*
2527  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2528  * leaf queries of the UNION ALL. (We must do that now because they
2529  * weren't previously referenced by the jointree, and so were missed by
2530  * the main invocation of pull_up_subqueries.)
2531  */
2532  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2533 }
#define NIL
Definition: pg_list.h:65
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, Query *setOpQuery, int childRToffset)
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
FromExpr * jointree
Definition: parsenodes.h:148
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
Definition: nodes.h:539
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1553
bool hasRecursion
Definition: pathnodes.h:351
#define list_make1(x1)
Definition: pg_list.h:206
List * rtable
Definition: parsenodes.h:147
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:336
#define makeNode(_type_)
Definition: nodes.h:587
#define Assert(condition)
Definition: c.h:804
static int list_length(const List *l)
Definition: pg_list.h:149
RTEKind rtekind
Definition: parsenodes.h:995
Node * setOperations
Definition: parsenodes.h:177
#define copyObject(obj)
Definition: nodes.h:655
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:665

◆ get_agg_clause_costs()

void get_agg_clause_costs ( PlannerInfo root,
AggSplit  aggsplit,
AggClauseCosts agg_costs 
)

Definition at line 542 of file prepagg.c.

References add_function_cost(), Aggref::aggdirectargs, AggTransInfo::aggfilter, PlannerInfo::agginfos, PlannerInfo::aggtransinfos, AggTransInfo::aggtransspace, AggTransInfo::aggtranstype, AggTransInfo::aggtranstypmod, ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_SMALL_INITSIZE, AggTransInfo::args, AggTransInfo::combinefn_oid, cost_qual_eval_node(), AggTransInfo::deserialfn_oid, DO_AGGSPLIT_COMBINE, DO_AGGSPLIT_DESERIALIZE, DO_AGGSPLIT_SERIALIZE, DO_AGGSPLIT_SKIPFINAL, AggClauseCosts::finalCost, AggInfo::finalfn_oid, get_typavgwidth(), lfirst, MAXALIGN, OidIsValid, QualCost::per_tuple, AggInfo::representative_aggref, AggTransInfo::serialfn_oid, QualCost::startup, AggClauseCosts::transCost, AggTransInfo::transfn_oid, AggClauseCosts::transitionSpace, and AggTransInfo::transtypeByVal.

Referenced by create_grouping_paths(), create_partial_grouping_paths(), and estimate_path_cost_size().

543 {
544  ListCell *lc;
545 
546  foreach(lc, root->aggtransinfos)
547  {
548  AggTransInfo *transinfo = (AggTransInfo *) lfirst(lc);
549 
550  /*
551  * Add the appropriate component function execution costs to
552  * appropriate totals.
553  */
554  if (DO_AGGSPLIT_COMBINE(aggsplit))
555  {
556  /* charge for combining previously aggregated states */
557  add_function_cost(root, transinfo->combinefn_oid, NULL,
558  &costs->transCost);
559  }
560  else
561  add_function_cost(root, transinfo->transfn_oid, NULL,
562  &costs->transCost);
563  if (DO_AGGSPLIT_DESERIALIZE(aggsplit) &&
564  OidIsValid(transinfo->deserialfn_oid))
565  add_function_cost(root, transinfo->deserialfn_oid, NULL,
566  &costs->transCost);
567  if (DO_AGGSPLIT_SERIALIZE(aggsplit) &&
568  OidIsValid(transinfo->serialfn_oid))
569  add_function_cost(root, transinfo->serialfn_oid, NULL,
570  &costs->finalCost);
571 
572  /*
573  * These costs are incurred only by the initial aggregate node, so we
574  * mustn't include them again at upper levels.
575  */
576  if (!DO_AGGSPLIT_COMBINE(aggsplit))
577  {
578  /* add the input expressions' cost to per-input-row costs */
579  QualCost argcosts;
580 
581  cost_qual_eval_node(&argcosts, (Node *) transinfo->args, root);
582  costs->transCost.startup += argcosts.startup;
583  costs->transCost.per_tuple += argcosts.per_tuple;
584 
585  /*
586  * Add any filter's cost to per-input-row costs.
587  *
588  * XXX Ideally we should reduce input expression costs according
589  * to filter selectivity, but it's not clear it's worth the
590  * trouble.
591  */
592  if (transinfo->aggfilter)
593  {
594  cost_qual_eval_node(&argcosts, (Node *) transinfo->aggfilter,
595  root);
596  costs->transCost.startup += argcosts.startup;
597  costs->transCost.per_tuple += argcosts.per_tuple;
598  }
599  }
600 
601  /*
602  * If the transition type is pass-by-value then it doesn't add
603  * anything to the required size of the hashtable. If it is
604  * pass-by-reference then we have to add the estimated size of the
605  * value itself, plus palloc overhead.
606  */
607  if (!transinfo->transtypeByVal)
608  {
609  int32 avgwidth;
610 
611  /* Use average width if aggregate definition gave one */
612  if (transinfo->aggtransspace > 0)
613  avgwidth = transinfo->aggtransspace;
614  else if (transinfo->transfn_oid == F_ARRAY_APPEND)
615  {
616  /*
617  * If the transition function is array_append(), it'll use an
618  * expanded array as transvalue, which will occupy at least
619  * ALLOCSET_SMALL_INITSIZE and possibly more. Use that as the
620  * estimate for lack of a better idea.
621  */
622  avgwidth = ALLOCSET_SMALL_INITSIZE;
623  }
624  else
625  {
626  avgwidth = get_typavgwidth(transinfo->aggtranstype, transinfo->aggtranstypmod);
627  }
628 
629  avgwidth = MAXALIGN(avgwidth);
630  costs->transitionSpace += avgwidth + 2 * sizeof(void *);
631  }
632  else if (transinfo->aggtranstype == INTERNALOID)
633  {
634  /*
635  * INTERNAL transition type is a special case: although INTERNAL
636  * is pass-by-value, it's almost certainly being used as a pointer
637  * to some large data structure. The aggregate definition can
638  * provide an estimate of the size. If it doesn't, then we assume
639  * ALLOCSET_DEFAULT_INITSIZE, which is a good guess if the data is
640  * being kept in a private memory context, as is done by
641  * array_agg() for instance.
642  */
643  if (transinfo->aggtransspace > 0)
644  costs->transitionSpace += transinfo->aggtransspace;
645  else
646  costs->transitionSpace += ALLOCSET_DEFAULT_INITSIZE;
647  }
648  }
649 
650  foreach(lc, root->agginfos)
651  {
652  AggInfo *agginfo = (AggInfo *) lfirst(lc);
653  Aggref *aggref = agginfo->representative_aggref;
654 
655  /*
656  * Add the appropriate component function execution costs to
657  * appropriate totals.
658  */
659  if (!DO_AGGSPLIT_SKIPFINAL(aggsplit) &&
660  OidIsValid(agginfo->finalfn_oid))
661  add_function_cost(root, agginfo->finalfn_oid, NULL,
662  &costs->finalCost);
663 
664  /*
665  * If there are direct arguments, treat their evaluation cost like the
666  * cost of the finalfn.
667  */
668  if (aggref->aggdirectargs)
669  {
670  QualCost argcosts;
671 
672  cost_qual_eval_node(&argcosts, (Node *) aggref->aggdirectargs,
673  root);
674  costs->finalCost.startup += argcosts.startup;
675  costs->finalCost.per_tuple += argcosts.per_tuple;
676  }
677  }
678 }
Oid serialfn_oid
Definition: pathnodes.h:2690
void cost_qual_eval_node(QualCost *cost, Node *qual, PlannerInfo *root)
Definition: costsize.c:4337
Oid finalfn_oid
Definition: pathnodes.h:2670
Definition: nodes.h:539
void add_function_cost(PlannerInfo *root, Oid funcid, Node *node, QualCost *cost)
Definition: plancat.c:1967
bool transtypeByVal
Definition: pathnodes.h:2702
Expr * aggfilter
Definition: pathnodes.h:2684
List * agginfos
Definition: pathnodes.h:356
Oid combinefn_oid
Definition: pathnodes.h:2696
#define OidIsValid(objectId)
Definition: c.h:710
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:801
Cost startup
Definition: pathnodes.h:45
signed int int32
Definition: c.h:429
Cost per_tuple
Definition: pathnodes.h:46
#define DO_AGGSPLIT_SERIALIZE(as)
Definition: nodes.h:803
List * aggtransinfos
Definition: pathnodes.h:357
int32 aggtransspace
Definition: pathnodes.h:2703
List * aggdirectargs
Definition: primnodes.h:329
Oid aggtranstype
Definition: pathnodes.h:2699
int32 aggtranstypmod
Definition: pathnodes.h:2700
#define ALLOCSET_SMALL_INITSIZE
Definition: memutils.h:203
int32 get_typavgwidth(Oid typid, int32 typmod)
Definition: lsyscache.c:2525
List * args
Definition: pathnodes.h:2683
#define lfirst(lc)
Definition: pg_list.h:169
#define DO_AGGSPLIT_SKIPFINAL(as)
Definition: nodes.h:802
#define MAXALIGN(LEN)
Definition: c.h:757
Oid deserialfn_oid
Definition: pathnodes.h:2693
#define DO_AGGSPLIT_DESERIALIZE(as)
Definition: nodes.h:804
#define ALLOCSET_DEFAULT_INITSIZE
Definition: memutils.h:193
Aggref * representative_aggref
Definition: pathnodes.h:2659

◆ get_plan_rowmark()

PlanRowMark* get_plan_rowmark ( List rowmarks,
Index  rtindex 
)

Definition at line 425 of file preptlist.c.

References lfirst, and PlanRowMark::rti.

Referenced by check_index_predicates(), deparseLockingClause(), and expand_inherited_rtentry().

426 {
427  ListCell *l;
428 
429  foreach(l, rowmarks)
430  {
431  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
432 
433  if (rc->rti == rtindex)
434  return rc;
435  }
436  return NULL;
437 }
#define lfirst(lc)
Definition: pg_list.h:169

◆ get_relids_for_join()

Relids get_relids_for_join ( Query query,
int  joinrelid 
)

Definition at line 3573 of file prepjointree.c.

References elog, ERROR, find_jointree_node_for_rel(), get_relids_in_jointree(), and Query::jointree.

Referenced by alias_relid_set().

3574 {
3575  Node *jtnode;
3576 
3577  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3578  joinrelid);
3579  if (!jtnode)
3580  elog(ERROR, "could not find join node %d", joinrelid);
3581  return get_relids_in_jointree(jtnode, false);
3582 }
FromExpr * jointree
Definition: parsenodes.h:148
Definition: nodes.h:539
static Node * find_jointree_node_for_rel(Node *jtnode, int relid)
#define ERROR
Definition: elog.h:46
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
#define elog(elevel,...)
Definition: elog.h:232

◆ get_relids_in_jointree()

Relids get_relids_in_jointree ( Node jtnode,
bool  include_joins 
)

Definition at line 3529 of file prepjointree.c.

References bms_add_member(), bms_join(), bms_make_singleton(), elog, ERROR, FromExpr::fromlist, get_relids_in_jointree(), IsA, JoinExpr::larg, lfirst, nodeTag, JoinExpr::rarg, JoinExpr::rtindex, and pullup_replace_vars_context::varno.

Referenced by distribute_qual_to_rels(), find_dependent_phvs_in_jointree(), get_relids_for_join(), get_relids_in_jointree(), is_simple_subquery(), preprocess_rowmarks(), process_implied_equality(), pull_up_simple_subquery(), and remove_result_refs().

3530 {
3531  Relids result = NULL;
3532 
3533  if (jtnode == NULL)
3534  return result;
3535  if (IsA(jtnode, RangeTblRef))
3536  {
3537  int varno = ((RangeTblRef *) jtnode)->rtindex;
3538 
3539  result = bms_make_singleton(varno);
3540  }
3541  else if (IsA(jtnode, FromExpr))
3542  {
3543  FromExpr *f = (FromExpr *) jtnode;
3544  ListCell *l;
3545 
3546  foreach(l, f->fromlist)
3547  {
3548  result = bms_join(result,
3550  include_joins));
3551  }
3552  }
3553  else if (IsA(jtnode, JoinExpr))
3554  {
3555  JoinExpr *j = (JoinExpr *) jtnode;
3556 
3557  result = get_relids_in_jointree(j->larg, include_joins);
3558  result = bms_join(result,
3559  get_relids_in_jointree(j->rarg, include_joins));
3560  if (include_joins && j->rtindex)
3561  result = bms_add_member(result, j->rtindex);
3562  }
3563  else
3564  elog(ERROR, "unrecognized node type: %d",
3565  (int) nodeTag(jtnode));
3566  return result;
3567 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
List * fromlist
Definition: primnodes.h:1553
Node * larg
Definition: primnodes.h:1532
#define ERROR
Definition: elog.h:46
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:949
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Node * rarg
Definition: primnodes.h:1533
#define lfirst(lc)
Definition: pg_list.h:169
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define nodeTag(nodeptr)
Definition: nodes.h:544
#define elog(elevel,...)
Definition: elog.h:232
int rtindex
Definition: primnodes.h:1538

◆ plan_set_operations()

RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 103 of file prepunion.c.

References Assert, castNode, Query::distinctClause, PlannerInfo::ec_merging_done, PlannerInfo::eq_classes, FromExpr::fromlist, generate_recursion_path(), Query::groupClause, PlannerInfo::hasRecursion, Query::havingQual, IsA, Query::jointree, SetOperationStmt::larg, NIL, parse(), PlannerInfo::parse, PlannerInfo::processed_tlist, FromExpr::quals, recurse_set_operations(), Query::setOperations, setup_simple_rel_arrays(), PlannerInfo::simple_rte_array, RangeTblEntry::subquery, Query::targetList, and Query::windowClause.

Referenced by grouping_planner().

104 {
105  Query *parse = root->parse;
107  Node *node;
108  RangeTblEntry *leftmostRTE;
109  Query *leftmostQuery;
110  RelOptInfo *setop_rel;
111  List *top_tlist;
112 
113  Assert(topop);
114 
115  /* check for unsupported stuff */
116  Assert(parse->jointree->fromlist == NIL);
117  Assert(parse->jointree->quals == NULL);
118  Assert(parse->groupClause == NIL);
119  Assert(parse->havingQual == NULL);
120  Assert(parse->windowClause == NIL);
121  Assert(parse->distinctClause == NIL);
122 
123  /*
124  * In the outer query level, we won't have any true equivalences to deal
125  * with; but we do want to be able to make pathkeys, which will require
126  * single-member EquivalenceClasses. Indicate that EC merging is complete
127  * so that pathkeys.c won't complain.
128  */
129  Assert(root->eq_classes == NIL);
130  root->ec_merging_done = true;
131 
132  /*
133  * We'll need to build RelOptInfos for each of the leaf subqueries, which
134  * are RTE_SUBQUERY rangetable entries in this Query. Prepare the index
135  * arrays for those, and for AppendRelInfos in case they're needed.
136  */
138 
139  /*
140  * Find the leftmost component Query. We need to use its column names for
141  * all generated tlists (else SELECT INTO won't work right).
142  */
143  node = topop->larg;
144  while (node && IsA(node, SetOperationStmt))
145  node = ((SetOperationStmt *) node)->larg;
146  Assert(node && IsA(node, RangeTblRef));
147  leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
148  leftmostQuery = leftmostRTE->subquery;
149  Assert(leftmostQuery != NULL);
150 
151  /*
152  * If the topmost node is a recursive union, it needs special processing.
153  */
154  if (root->hasRecursion)
155  {
156  setop_rel = generate_recursion_path(topop, root,
157  leftmostQuery->targetList,
158  &top_tlist);
159  }
160  else
161  {
162  /*
163  * Recurse on setOperations tree to generate paths for set ops. The
164  * final output paths should have just the column types shown as the
165  * output from the top-level node, plus possibly resjunk working
166  * columns (we can rely on upper-level nodes to deal with that).
167  */
168  setop_rel = recurse_set_operations((Node *) topop, root,
169  topop->colTypes, topop->colCollations,
170  true, -1,
171  leftmostQuery->targetList,
172  &top_tlist,
173  NULL);
174  }
175 
176  /* Must return the built tlist into root->processed_tlist. */
177  root->processed_tlist = top_tlist;
178 
179  return setop_rel;
180 }
static RelOptInfo * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
Definition: prepunion.c:434
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
bool ec_merging_done
Definition: pathnodes.h:250
FromExpr * jointree
Definition: parsenodes.h:148
#define castNode(_type_, nodeptr)
Definition: nodes.h:608
Definition: nodes.h:539
static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, List *colTypes, List *colCollations, bool junkOK, int flag, List *refnames_tlist, List **pTargetList, double *pNumGroups)
Definition: prepunion.c:207
List * fromlist
Definition: primnodes.h:1553
bool hasRecursion
Definition: pathnodes.h:351
Node * quals
Definition: primnodes.h:1554
List * windowClause
Definition: parsenodes.h:165
List * targetList
Definition: parsenodes.h:150
List * distinctClause
Definition: parsenodes.h:167
RangeTblEntry ** simple_rte_array
Definition: pathnodes.h:193
#define Assert(condition)
Definition: c.h:804
List * eq_classes
Definition: pathnodes.h:248
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:83
Node * setOperations
Definition: parsenodes.h:177
Query * subquery
Definition: parsenodes.h:1030
List * groupClause
Definition: parsenodes.h:158
Node * havingQual
Definition: parsenodes.h:163
List * processed_tlist
Definition: pathnodes.h:320
Definition: pg_list.h:50
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:665

◆ preprocess_aggrefs()

void preprocess_aggrefs ( PlannerInfo root,
Node clause 
)

Definition at line 111 of file prepagg.c.

References preprocess_aggrefs_walker().

Referenced by grouping_planner().

112 {
113  (void) preprocess_aggrefs_walker(clause, root);
114 }
static bool preprocess_aggrefs_walker(Node *node, PlannerInfo *root)
Definition: prepagg.c:324

◆ preprocess_function_rtes()

void preprocess_function_rtes ( PlannerInfo root)

Definition at line 639 of file prepjointree.c.

References eval_const_expressions(), RangeTblEntry::funcordinality, RangeTblEntry::functions, inline_set_returning_function(), lfirst, NIL, PlannerInfo::parse, Query::rtable, RTE_FUNCTION, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblEntry::security_barrier, and RangeTblEntry::subquery.

Referenced by pull_up_simple_subquery(), and subquery_planner().

640 {
641  ListCell *rt;
642 
643  foreach(rt, root->parse->rtable)
644  {
645  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
646 
647  if (rte->rtekind == RTE_FUNCTION)
648  {
649  Query *funcquery;
650 
651  /* Apply const-simplification */
652  rte->functions = (List *)
653  eval_const_expressions(root, (Node *) rte->functions);
654 
655  /* Check safety of expansion, and expand if possible */
656  funcquery = inline_set_returning_function(root, rte);
657  if (funcquery)
658  {
659  /* Successful expansion, convert the RTE to a subquery */
660  rte->rtekind = RTE_SUBQUERY;
661  rte->subquery = funcquery;
662  rte->security_barrier = false;
663  /* Clear fields that should not be set in a subquery RTE */
664  rte->functions = NIL;
665  rte->funcordinality = false;
666  }
667  }
668  }
669 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:161
Definition: nodes.h:539
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4772
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2090
bool funcordinality
Definition: parsenodes.h:1090
List * rtable
Definition: parsenodes.h:147
bool security_barrier
Definition: parsenodes.h:1031
#define lfirst(lc)
Definition: pg_list.h:169
List * functions
Definition: parsenodes.h:1089
RTEKind rtekind
Definition: parsenodes.h:995
Query * subquery
Definition: parsenodes.h:1030
Definition: pg_list.h:50

◆ preprocess_targetlist()

void preprocess_targetlist ( PlannerInfo root)

Definition at line 62 of file preptlist.c.

References add_row_identity_columns(), PlanRowMark::allMarkTypes, Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, elog, ERROR, expand_insert_targetlist(), extract_update_targetlist_colnos(), RangeTblEntry::inh, InvalidOid, IsA, PlanRowMark::isParent, lappend(), lfirst, list_free(), list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NoLock, parse(), PlannerInfo::parse, PlannerInfo::processed_tlist, PlanRowMark::prti, pstrdup(), pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, RangeTblEntry::relid, Query::resultRelation, Query::returningList, ROW_MARK_COPY, PlanRowMark::rowmarkId, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, PlanRowMark::rti, SelfItemPointerAttributeNumber, snprintf, table_close(), table_open(), TableOidAttributeNumber, Query::targetList, tlist_member(), PlannerInfo::update_colnos, and Var::varno.

Referenced by grouping_planner().

63 {
64  Query *parse = root->parse;
65  int result_relation = parse->resultRelation;
66  List *range_table = parse->rtable;
67  CmdType command_type = parse->commandType;
68  RangeTblEntry *target_rte = NULL;
69  Relation target_relation = NULL;
70  List *tlist;
71  ListCell *lc;
72 
73  /*
74  * If there is a result relation, open it so we can look for missing
75  * columns and so on. We assume that previous code already acquired at
76  * least AccessShareLock on the relation, so we need no lock here.
77  */
78  if (result_relation)
79  {
80  target_rte = rt_fetch(result_relation, range_table);
81 
82  /*
83  * Sanity check: it'd better be a real relation not, say, a subquery.
84  * Else parser or rewriter messed up.
85  */
86  if (target_rte->rtekind != RTE_RELATION)
87  elog(ERROR, "result relation must be a regular relation");
88 
89  target_relation = table_open(target_rte->relid, NoLock);
90  }
91  else
92  Assert(command_type == CMD_SELECT);
93 
94  /*
95  * In an INSERT, the executor expects the targetlist to match the exact
96  * order of the target table's attributes, including entries for
97  * attributes not mentioned in the source query.
98  *
99  * In an UPDATE, we don't rearrange the tlist order, but we need to make a
100  * separate list of the target attribute numbers, in tlist order, and then
101  * renumber the processed_tlist entries to be consecutive.
102  */
103  tlist = parse->targetList;
104  if (command_type == CMD_INSERT)
105  tlist = expand_insert_targetlist(tlist, target_relation);
106  else if (command_type == CMD_UPDATE)
108 
109  /*
110  * For non-inherited UPDATE/DELETE, register any junk column(s) needed to
111  * allow the executor to identify the rows to be updated or deleted. In
112  * the inheritance case, we do nothing now, leaving this to be dealt with
113  * when expand_inherited_rtentry() makes the leaf target relations. (But
114  * there might not be any leaf target relations, in which case we must do
115  * this in distribute_row_identity_vars().)
116  */
117  if ((command_type == CMD_UPDATE || command_type == CMD_DELETE) &&
118  !target_rte->inh)
119  {
120  /* row-identity logic expects to add stuff to processed_tlist */
121  root->processed_tlist = tlist;
122  add_row_identity_columns(root, result_relation,
123  target_rte, target_relation);
124  tlist = root->processed_tlist;
125  }
126 
127  /*
128  * Add necessary junk columns for rowmarked rels. These values are needed
129  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
130  * rechecking. See comments for PlanRowMark in plannodes.h. If you
131  * change this stanza, see also expand_inherited_rtentry(), which has to
132  * be able to add on junk columns equivalent to these.
133  *
134  * (Someday it might be useful to fold these resjunk columns into the
135  * row-identity-column management used for UPDATE/DELETE. Today is not
136  * that day, however. One notable issue is that it seems important that
137  * the whole-row Vars made here use the real table rowtype, not RECORD, so
138  * that conversion to/from child relations' rowtypes will happen. Also,
139  * since these entries don't potentially bloat with more and more child
140  * relations, there's not really much need for column sharing.)
141  */
142  foreach(lc, root->rowMarks)
143  {
144  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
145  Var *var;
146  char resname[32];
147  TargetEntry *tle;
148 
149  /* child rels use the same junk attrs as their parents */
150  if (rc->rti != rc->prti)
151  continue;
152 
153  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
154  {
155  /* Need to fetch TID */
156  var = makeVar(rc->rti,
158  TIDOID,
159  -1,
160  InvalidOid,
161  0);
162  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
163  tle = makeTargetEntry((Expr *) var,
164  list_length(tlist) + 1,
165  pstrdup(resname),
166  true);
167  tlist = lappend(tlist, tle);
168  }
169  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
170  {
171  /* Need the whole row as a junk var */
172  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
173  rc->rti,
174  0,
175  false);
176  snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
177  tle = makeTargetEntry((Expr *) var,
178  list_length(tlist) + 1,
179  pstrdup(resname),
180  true);
181  tlist = lappend(tlist, tle);
182  }
183 
184  /* If parent of inheritance tree, always fetch the tableoid too. */
185  if (rc->isParent)
186  {
187  var = makeVar(rc->rti,
189  OIDOID,
190  -1,
191  InvalidOid,
192  0);
193  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
194  tle = makeTargetEntry((Expr *) var,
195  list_length(tlist) + 1,
196  pstrdup(resname),
197  true);
198  tlist = lappend(tlist, tle);
199  }
200  }
201 
202  /*
203  * If the query has a RETURNING list, add resjunk entries for any Vars
204  * used in RETURNING that belong to other relations. We need to do this
205  * to make these Vars available for the RETURNING calculation. Vars that
206  * belong to the result rel don't need to be added, because they will be
207  * made to refer to the actual heap tuple.
208  */
209  if (parse->returningList && list_length(parse->rtable) > 1)
210  {
211  List *vars;
212  ListCell *l;
213 
214  vars = pull_var_clause((Node *) parse->returningList,
218  foreach(l, vars)
219  {
220  Var *var = (Var *) lfirst(l);
221  TargetEntry *tle;
222 
223  if (IsA(var, Var) &&
224  var->varno == result_relation)
225  continue; /* don't need it */
226 
227  if (tlist_member((Expr *) var, tlist))
228  continue; /* already got it */
229 
230  tle = makeTargetEntry((Expr *) var,
231  list_length(tlist) + 1,
232  NULL,
233  true);
234 
235  tlist = lappend(tlist, tle);
236  }
237  list_free(vars);
238  }
239 
240  root->processed_tlist = tlist;
241 
242  if (target_relation)
243  table_close(target_relation, NoLock);
244 }
List * rowMarks
Definition: pathnodes.h:287
List * extract_update_targetlist_colnos(List *tlist)
Definition: preptlist.c:261
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
char * pstrdup(const char *in)
Definition: mcxt.c:1299
int resultRelation
Definition: parsenodes.h:130
Definition: nodes.h:539
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
Index prti
Definition: plannodes.h:1119
List * pull_var_clause(Node *node, int flags)
Definition: var.c:562
Definition: primnodes.h:186
Index rowmarkId
Definition: plannodes.h:1120
List * targetList
Definition: parsenodes.h:150
List * rtable
Definition: parsenodes.h:147
#define ERROR
Definition: elog.h:46
static List * expand_insert_targetlist(List *tlist, Relation rel)
Definition: preptlist.c:295
#define NoLock
Definition: lockdefs.h:34
#define TableOidAttributeNumber
Definition: sysattr.h:26
int allMarkTypes
Definition: plannodes.h:1122
List * returningList
Definition: parsenodes.h:156
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend(List *list, void *datum)
Definition: list.c:336
Index varno
Definition: primnodes.h:189
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:189
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
#define InvalidOid
Definition: postgres_ext.h:36
CmdType commandType
Definition: parsenodes.h:120
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
RTEKind rtekind
Definition: parsenodes.h:995
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:188
void list_free(List *list)
Definition: list.c:1391
#define elog(elevel,...)
Definition: elog.h:232
bool isParent
Definition: plannodes.h:1125
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
List * processed_tlist
Definition: pathnodes.h:320
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: regcomp.c:237
Definition: pg_list.h:50
#define snprintf
Definition: port.h:216
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:186
CmdType
Definition: nodes.h:682
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition: appendinfo.c:857
List * update_colnos
Definition: pathnodes.h:328
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:665

◆ pull_up_sublinks()

void pull_up_sublinks ( PlannerInfo root)

Definition at line 208 of file prepjointree.c.

References IsA, Query::jointree, list_make1, makeFromExpr(), PlannerInfo::parse, pull_up_sublinks_jointree_recurse(), and pullup_replace_vars_context::relids.

Referenced by pull_up_simple_subquery(), and subquery_planner().

209 {
210  Node *jtnode;
211  Relids relids;
212 
213  /* Begin recursion through the jointree */
214  jtnode = pull_up_sublinks_jointree_recurse(root,
215  (Node *) root->parse->jointree,
216  &relids);
217 
218  /*
219  * root->parse->jointree must always be a FromExpr, so insert a dummy one
220  * if we got a bare RangeTblRef or JoinExpr out of the recursion.
221  */
222  if (IsA(jtnode, FromExpr))
223  root->parse->jointree = (FromExpr *) jtnode;
224  else
225  root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
226 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
FromExpr * jointree
Definition: parsenodes.h:148
Definition: nodes.h:539
#define list_make1(x1)
Definition: pg_list.h:206
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:235

◆ pull_up_subqueries()

void pull_up_subqueries ( PlannerInfo root)

Definition at line 680 of file prepjointree.c.

References Assert, IsA, Query::jointree, PlannerInfo::parse, and pull_up_subqueries_recurse().

Referenced by pull_up_simple_subquery(), and subquery_planner().

681 {
682  /* Top level of jointree must always be a FromExpr */
683  Assert(IsA(root->parse->jointree, FromExpr));
684  /* Recursion starts with no containing join nor appendrel */
685  root->parse->jointree = (FromExpr *)
687  NULL, NULL, NULL);
688  /* We should still have a FromExpr */
689  Assert(IsA(root->parse->jointree, FromExpr));
690 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
FromExpr * jointree
Definition: parsenodes.h:148
static Node * pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode, JoinExpr *lowest_outer_join, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel)
Definition: prepjointree.c:730
Definition: nodes.h:539
#define Assert(condition)
Definition: c.h:804

◆ reduce_outer_joins()

void reduce_outer_joins ( PlannerInfo root)

Definition at line 2574 of file prepjointree.c.

References reduce_outer_joins_state::contains_outer, elog, ERROR, Query::jointree, NIL, PlannerInfo::parse, reduce_outer_joins_pass1(), and reduce_outer_joins_pass2().

Referenced by subquery_planner().

2575 {
2577 
2578  /*
2579  * To avoid doing strictness checks on more quals than necessary, we want
2580  * to stop descending the jointree as soon as there are no outer joins
2581  * below our current point. This consideration forces a two-pass process.
2582  * The first pass gathers information about which base rels appear below
2583  * each side of each join clause, and about whether there are outer
2584  * join(s) below each side of each join clause. The second pass examines
2585  * qual clauses and changes join types as it descends the tree.
2586  */
2587  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2588 
2589  /* planner.c shouldn't have called me if no outer joins */
2590  if (state == NULL || !state->contains_outer)
2591  elog(ERROR, "so where are the outer joins?");
2592 
2594  state, root, NULL, NIL, NIL);
2595 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:161
FromExpr * jointree
Definition: parsenodes.h:148
Definition: nodes.h:539
#define ERROR
Definition: elog.h:46
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
Definition: regguts.h:317
#define elog(elevel,...)
Definition: elog.h:232
static void reduce_outer_joins_pass2(Node *jtnode, reduce_outer_joins_state *state, PlannerInfo *root, Relids nonnullable_rels, List *nonnullable_vars, List *forced_null_vars)

◆ remove_useless_result_rtes()

void remove_useless_result_rtes ( PlannerInfo root)

Definition at line 2987 of file prepjointree.c.

References Assert, foreach_delete_current, IsA, Query::jointree, lfirst, PlannerInfo::parse, remove_useless_results_recurse(), PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_RESULT, and PlanRowMark::rti.

Referenced by subquery_planner().

2988 {
2989  ListCell *cell;
2990 
2991  /* Top level of jointree must always be a FromExpr */
2992  Assert(IsA(root->parse->jointree, FromExpr));
2993  /* Recurse ... */
2994  root->parse->jointree = (FromExpr *)
2996  /* We should still have a FromExpr */
2997  Assert(IsA(root->parse->jointree, FromExpr));
2998 
2999  /*
3000  * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3001  * must do that for any RTE_RESULT that we just removed. But one for a
3002  * RTE that we did not remove can be dropped anyway: since the RTE has
3003  * only one possible output row, there is no need for EPQ to mark and
3004  * restore that row.
3005  *
3006  * It's necessary, not optional, to remove the PlanRowMark for a surviving
3007  * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3008  * RTE_RESULT, which the executor has no support for.
3009  */
3010  foreach(cell, root->rowMarks)
3011  {
3012  PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3013 
3014  if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3015  root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3016  }
3017 }
List * rowMarks
Definition: pathnodes.h:287
#define IsA(nodeptr, _type_)
Definition: nodes.h:590
Query * parse
Definition: pathnodes.h:161
FromExpr * jointree
Definition: parsenodes.h:148
Definition: nodes.h:539
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:369
List * rtable
Definition: parsenodes.h:147
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static Node * remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)

◆ replace_empty_jointree()

void replace_empty_jointree ( Query parse)

Definition at line 150 of file prepjointree.c.

References RangeTblEntry::eref, FromExpr::fromlist, Query::jointree, lappend(), list_length(), list_make1, makeAlias(), makeNode, NIL, Query::rtable, RTE_RESULT, RangeTblEntry::rtekind, RangeTblRef::rtindex, and Query::setOperations.

Referenced by convert_EXISTS_sublink_to_join(), pull_up_simple_subquery(), and subquery_planner().

151 {
152  RangeTblEntry *rte;
153  Index rti;
154  RangeTblRef *rtr;
155 
156  /* Nothing to do if jointree is already nonempty */
157  if (parse->jointree->fromlist != NIL)
158  return;
159 
160  /* We mustn't change it in the top level of a setop tree, either */
161  if (parse->setOperations)
162  return;
163 
164  /* Create suitable RTE */
165  rte = makeNode(RangeTblEntry);
166  rte->rtekind = RTE_RESULT;
167  rte->eref = makeAlias("*RESULT*", NIL);
168 
169  /* Add it to rangetable */
170  parse->rtable = lappend(parse->rtable, rte);
171  rti = list_length(parse->rtable);
172 
173  /* And jam a reference into the jointree */
174  rtr = makeNode(RangeTblRef);
175  rtr->rtindex = rti;
176  parse->jointree->fromlist = list_make1(rtr);
177 }
#define NIL
Definition: pg_list.h:65
FromExpr * jointree
Definition: parsenodes.h:148
List * fromlist
Definition: primnodes.h:1553
#define list_make1(x1)
Definition: pg_list.h:206
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:387
List * rtable
Definition: parsenodes.h:147
List * lappend(List *list, void *datum)
Definition: list.c:336
unsigned int Index
Definition: c.h:549
#define makeNode(_type_)
Definition: nodes.h:587
static int list_length(const List *l)
Definition: pg_list.h:149
RTEKind rtekind
Definition: parsenodes.h:995
Node * setOperations
Definition: parsenodes.h:177
Alias * eref
Definition: parsenodes.h:1141