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 transform_MERGE_to_join (Query *parse)
 
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 323 of file preptlist.c.

324 {
325  List *update_colnos = NIL;
326  AttrNumber nextresno = 1;
327  ListCell *lc;
328 
329  foreach(lc, tlist)
330  {
331  TargetEntry *tle = (TargetEntry *) lfirst(lc);
332 
333  if (!tle->resjunk)
334  update_colnos = lappend_int(update_colnos, tle->resno);
335  tle->resno = nextresno++;
336  }
337  return update_colnos;
338 }
int16 AttrNumber
Definition: attnum.h:21
List * lappend_int(List *list, int datum)
Definition: list.c:356
#define lfirst(lc)
Definition: pg_list.h:170
#define NIL
Definition: pg_list.h:66
Definition: pg_list.h:52
AttrNumber resno
Definition: primnodes.h:1829
bool resjunk
Definition: primnodes.h:1835

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

Referenced by make_modifytable(), and preprocess_targetlist().

◆ flatten_simple_union_all()

void flatten_simple_union_all ( PlannerInfo root)

Definition at line 2557 of file prepjointree.c.

2558 {
2559  Query *parse = root->parse;
2560  SetOperationStmt *topop;
2561  Node *leftmostjtnode;
2562  int leftmostRTI;
2563  RangeTblEntry *leftmostRTE;
2564  int childRTI;
2565  RangeTblEntry *childRTE;
2566  RangeTblRef *rtr;
2567 
2568  /* Shouldn't be called unless query has setops */
2569  topop = castNode(SetOperationStmt, parse->setOperations);
2570  Assert(topop);
2571 
2572  /* Can't optimize away a recursive UNION */
2573  if (root->hasRecursion)
2574  return;
2575 
2576  /*
2577  * Recursively check the tree of set operations. If not all UNION ALL
2578  * with identical column types, punt.
2579  */
2580  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2581  return;
2582 
2583  /*
2584  * Locate the leftmost leaf query in the setops tree. The upper query's
2585  * Vars all refer to this RTE (see transformSetOperationStmt).
2586  */
2587  leftmostjtnode = topop->larg;
2588  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2589  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2590  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2591  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2592  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2593  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2594 
2595  /*
2596  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2597  * will represent the leftmost leaf query in its capacity as a member of
2598  * the appendrel. The original will represent the appendrel as a whole.
2599  * (We must do things this way because the upper query's Vars have to be
2600  * seen as referring to the whole appendrel.)
2601  */
2602  childRTE = copyObject(leftmostRTE);
2603  parse->rtable = lappend(parse->rtable, childRTE);
2604  childRTI = list_length(parse->rtable);
2605 
2606  /* Modify the setops tree to reference the child copy */
2607  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2608 
2609  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2610  leftmostRTE->inh = true;
2611 
2612  /*
2613  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2614  * Query of a setops tree should have had an empty FromClause initially.
2615  */
2616  rtr = makeNode(RangeTblRef);
2617  rtr->rtindex = leftmostRTI;
2618  Assert(parse->jointree->fromlist == NIL);
2619  parse->jointree->fromlist = list_make1(rtr);
2620 
2621  /*
2622  * Now pretend the query has no setops. We must do this before trying to
2623  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2624  */
2625  parse->setOperations = NULL;
2626 
2627  /*
2628  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2629  * leaf queries of the UNION ALL. (We must do that now because they
2630  * weren't previously referenced by the jointree, and so were missed by
2631  * the main invocation of pull_up_subqueries.)
2632  */
2633  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2634 }
Assert(fmt[strlen(fmt) - 1] !='\n')
List * lappend(List *list, void *datum)
Definition: list.c:338
#define IsA(nodeptr, _type_)
Definition: nodes.h:625
#define copyObject(obj)
Definition: nodes.h:690
#define makeNode(_type_)
Definition: nodes.h:622
#define castNode(_type_, nodeptr)
Definition: nodes.h:643
@ RTE_SUBQUERY
Definition: parsenodes.h:1000
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
static int list_length(const List *l)
Definition: pg_list.h:150
#define list_make1(x1)
Definition: pg_list.h:210
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, Query *setOpQuery, int childRToffset)
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:673
Definition: nodes.h:575
bool hasRecursion
Definition: pathnodes.h:358
Query * parse
Definition: pathnodes.h:162
RTEKind rtekind
Definition: parsenodes.h:1016

References Assert(), castNode, SetOperationStmt::colTypes, copyObject, PlannerInfo::hasRecursion, RangeTblEntry::inh, is_simple_union_all_recurse(), IsA, lappend(), SetOperationStmt::larg, list_length(), list_make1, makeNode, NIL, parse(), PlannerInfo::parse, pull_up_union_leaf_queries(), rt_fetch, RTE_SUBQUERY, RangeTblEntry::rtekind, and RangeTblRef::rtindex.

Referenced by subquery_planner().

◆ get_agg_clause_costs()

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

Definition at line 538 of file prepagg.c.

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

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

◆ get_plan_rowmark()

PlanRowMark* get_plan_rowmark ( List rowmarks,
Index  rtindex 
)

Definition at line 487 of file preptlist.c.

488 {
489  ListCell *l;
490 
491  foreach(l, rowmarks)
492  {
493  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
494 
495  if (rc->rti == rtindex)
496  return rc;
497  }
498  return NULL;
499 }

References lfirst, and PlanRowMark::rti.

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

◆ get_relids_for_join()

Relids get_relids_for_join ( Query query,
int  joinrelid 
)

Definition at line 3674 of file prepjointree.c.

3675 {
3676  Node *jtnode;
3677 
3678  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3679  joinrelid);
3680  if (!jtnode)
3681  elog(ERROR, "could not find join node %d", joinrelid);
3682  return get_relids_in_jointree(jtnode, false);
3683 }
#define ERROR
Definition: elog.h:33
static Node * find_jointree_node_for_rel(Node *jtnode, int relid)
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
FromExpr * jointree
Definition: parsenodes.h:150

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

Referenced by alias_relid_set().

◆ get_relids_in_jointree()

Relids get_relids_in_jointree ( Node jtnode,
bool  include_joins 
)

Definition at line 3630 of file prepjointree.c.

3631 {
3632  Relids result = NULL;
3633 
3634  if (jtnode == NULL)
3635  return result;
3636  if (IsA(jtnode, RangeTblRef))
3637  {
3638  int varno = ((RangeTblRef *) jtnode)->rtindex;
3639 
3640  result = bms_make_singleton(varno);
3641  }
3642  else if (IsA(jtnode, FromExpr))
3643  {
3644  FromExpr *f = (FromExpr *) jtnode;
3645  ListCell *l;
3646 
3647  foreach(l, f->fromlist)
3648  {
3649  result = bms_join(result,
3651  include_joins));
3652  }
3653  }
3654  else if (IsA(jtnode, JoinExpr))
3655  {
3656  JoinExpr *j = (JoinExpr *) jtnode;
3657 
3658  result = get_relids_in_jointree(j->larg, include_joins);
3659  result = bms_join(result,
3660  get_relids_in_jointree(j->rarg, include_joins));
3661  if (include_joins && j->rtindex)
3662  result = bms_add_member(result, j->rtindex);
3663  }
3664  else
3665  elog(ERROR, "unrecognized node type: %d",
3666  (int) nodeTag(jtnode));
3667  return result;
3668 }
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:951
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:186
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:738
int j
Definition: isn.c:74
#define nodeTag(nodeptr)
Definition: nodes.h:579
List * fromlist
Definition: primnodes.h:1937

References bms_add_member(), bms_join(), bms_make_singleton(), elog(), ERROR, FromExpr::fromlist, IsA, j, lfirst, and nodeTag.

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

◆ plan_set_operations()

RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 103 of file prepunion.c.

104 {
105  Query *parse = root->parse;
106  SetOperationStmt *topop = castNode(SetOperationStmt, parse->setOperations);
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
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
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:83
List * processed_tlist
Definition: pathnodes.h:322
bool ec_merging_done
Definition: pathnodes.h:252
List * eq_classes
Definition: pathnodes.h:250
RangeTblEntry ** simple_rte_array
Definition: pathnodes.h:194
List * targetList
Definition: parsenodes.h:156
Query * subquery
Definition: parsenodes.h:1051

References Assert(), castNode, PlannerInfo::ec_merging_done, PlannerInfo::eq_classes, generate_recursion_path(), PlannerInfo::hasRecursion, IsA, SetOperationStmt::larg, NIL, parse(), PlannerInfo::parse, PlannerInfo::processed_tlist, recurse_set_operations(), setup_simple_rel_arrays(), PlannerInfo::simple_rte_array, RangeTblEntry::subquery, and Query::targetList.

Referenced by grouping_planner().

◆ preprocess_aggrefs()

void preprocess_aggrefs ( PlannerInfo root,
Node clause 
)

Definition at line 111 of file prepagg.c.

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

References preprocess_aggrefs_walker().

Referenced by grouping_planner().

◆ preprocess_function_rtes()

void preprocess_function_rtes ( PlannerInfo root)

Definition at line 719 of file prepjointree.c.

720 {
721  ListCell *rt;
722 
723  foreach(rt, root->parse->rtable)
724  {
725  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
726 
727  if (rte->rtekind == RTE_FUNCTION)
728  {
729  Query *funcquery;
730 
731  /* Apply const-simplification */
732  rte->functions = (List *)
733  eval_const_expressions(root, (Node *) rte->functions);
734 
735  /* Check safety of expansion, and expand if possible */
736  funcquery = inline_set_returning_function(root, rte);
737  if (funcquery)
738  {
739  /* Successful expansion, convert the RTE to a subquery */
740  rte->rtekind = RTE_SUBQUERY;
741  rte->subquery = funcquery;
742  rte->security_barrier = false;
743  /* Clear fields that should not be set in a subquery RTE */
744  rte->functions = NIL;
745  rte->funcordinality = false;
746  }
747  }
748  }
749 }
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4956
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2150
@ RTE_FUNCTION
Definition: parsenodes.h:1002
List * rtable
Definition: parsenodes.h:149
bool security_barrier
Definition: parsenodes.h:1052
bool funcordinality
Definition: parsenodes.h:1111
List * functions
Definition: parsenodes.h:1110

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

◆ preprocess_targetlist()

void preprocess_targetlist ( PlannerInfo root)

Definition at line 62 of file preptlist.c.

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/MERGE, register any junk column(s)
111  * needed to allow the executor to identify the rows to be updated or
112  * deleted. In the inheritance case, we do nothing now, leaving this to
113  * be dealt with when expand_inherited_rtentry() makes the leaf target
114  * relations. (But there might not be any leaf target relations, in which
115  * case we must do this in distribute_row_identity_vars().)
116  */
117  if ((command_type == CMD_UPDATE || command_type == CMD_DELETE ||
118  command_type == CMD_MERGE) &&
119  !target_rte->inh)
120  {
121  /* row-identity logic expects to add stuff to processed_tlist */
122  root->processed_tlist = tlist;
123  add_row_identity_columns(root, result_relation,
124  target_rte, target_relation);
125  tlist = root->processed_tlist;
126  }
127 
128  /*
129  * For MERGE we also need to handle the target list for each INSERT and
130  * UPDATE action separately. In addition, we examine the qual of each
131  * action and add any Vars there (other than those of the target rel) to
132  * the subplan targetlist.
133  */
134  if (command_type == CMD_MERGE)
135  {
136  ListCell *l;
137 
138  /*
139  * For MERGE, handle targetlist of each MergeAction separately. Give
140  * the same treatment to MergeAction->targetList as we would have
141  * given to a regular INSERT. For UPDATE, collect the column numbers
142  * being modified.
143  */
144  foreach(l, parse->mergeActionList)
145  {
147  List *vars;
148  ListCell *l2;
149 
150  if (action->commandType == CMD_INSERT)
151  action->targetList = expand_insert_targetlist(action->targetList,
152  target_relation);
153  else if (action->commandType == CMD_UPDATE)
154  action->updateColnos =
156 
157  /*
158  * Add resjunk entries for any Vars used in each action's
159  * targetlist and WHEN condition that belong to relations other
160  * than target. Note that aggregates, window functions and
161  * placeholder vars are not possible anywhere in MERGE's WHEN
162  * clauses. (PHVs may be added later, but they don't concern us
163  * here.)
164  */
166  list_concat_copy((List *) action->qual,
167  action->targetList),
168  0);
169  foreach(l2, vars)
170  {
171  Var *var = (Var *) lfirst(l2);
172  TargetEntry *tle;
173 
174  if (IsA(var, Var) && var->varno == result_relation)
175  continue; /* don't need it */
176 
177  if (tlist_member((Expr *) var, tlist))
178  continue; /* already got it */
179 
180  tle = makeTargetEntry((Expr *) var,
181  list_length(tlist) + 1,
182  NULL, true);
183  tlist = lappend(tlist, tle);
184  }
185  list_free(vars);
186  }
187  }
188 
189  /*
190  * Add necessary junk columns for rowmarked rels. These values are needed
191  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
192  * rechecking. See comments for PlanRowMark in plannodes.h. If you
193  * change this stanza, see also expand_inherited_rtentry(), which has to
194  * be able to add on junk columns equivalent to these.
195  *
196  * (Someday it might be useful to fold these resjunk columns into the
197  * row-identity-column management used for UPDATE/DELETE. Today is not
198  * that day, however. One notable issue is that it seems important that
199  * the whole-row Vars made here use the real table rowtype, not RECORD, so
200  * that conversion to/from child relations' rowtypes will happen. Also,
201  * since these entries don't potentially bloat with more and more child
202  * relations, there's not really much need for column sharing.)
203  */
204  foreach(lc, root->rowMarks)
205  {
206  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
207  Var *var;
208  char resname[32];
209  TargetEntry *tle;
210 
211  /* child rels use the same junk attrs as their parents */
212  if (rc->rti != rc->prti)
213  continue;
214 
215  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
216  {
217  /* Need to fetch TID */
218  var = makeVar(rc->rti,
220  TIDOID,
221  -1,
222  InvalidOid,
223  0);
224  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
225  tle = makeTargetEntry((Expr *) var,
226  list_length(tlist) + 1,
227  pstrdup(resname),
228  true);
229  tlist = lappend(tlist, tle);
230  }
231  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
232  {
233  /* Need the whole row as a junk var */
234  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
235  rc->rti,
236  0,
237  false);
238  snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
239  tle = makeTargetEntry((Expr *) var,
240  list_length(tlist) + 1,
241  pstrdup(resname),
242  true);
243  tlist = lappend(tlist, tle);
244  }
245 
246  /* If parent of inheritance tree, always fetch the tableoid too. */
247  if (rc->isParent)
248  {
249  var = makeVar(rc->rti,
251  OIDOID,
252  -1,
253  InvalidOid,
254  0);
255  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
256  tle = makeTargetEntry((Expr *) var,
257  list_length(tlist) + 1,
258  pstrdup(resname),
259  true);
260  tlist = lappend(tlist, tle);
261  }
262  }
263 
264  /*
265  * If the query has a RETURNING list, add resjunk entries for any Vars
266  * used in RETURNING that belong to other relations. We need to do this
267  * to make these Vars available for the RETURNING calculation. Vars that
268  * belong to the result rel don't need to be added, because they will be
269  * made to refer to the actual heap tuple.
270  */
271  if (parse->returningList && list_length(parse->rtable) > 1)
272  {
273  List *vars;
274  ListCell *l;
275 
276  vars = pull_var_clause((Node *) parse->returningList,
280  foreach(l, vars)
281  {
282  Var *var = (Var *) lfirst(l);
283  TargetEntry *tle;
284 
285  if (IsA(var, Var) &&
286  var->varno == result_relation)
287  continue; /* don't need it */
288 
289  if (tlist_member((Expr *) var, tlist))
290  continue; /* already got it */
291 
292  tle = makeTargetEntry((Expr *) var,
293  list_length(tlist) + 1,
294  NULL,
295  true);
296 
297  tlist = lappend(tlist, tle);
298  }
299  list_free(vars);
300  }
301 
302  root->processed_tlist = tlist;
303 
304  if (target_relation)
305  table_close(target_relation, NoLock);
306 }
void add_row_identity_columns(PlannerInfo *root, Index rtindex, RangeTblEntry *target_rte, Relation target_relation)
Definition: appendinfo.c:857
void list_free(List *list)
Definition: list.c:1545
List * list_concat_copy(const List *list1, const List *list2)
Definition: list.c:597
#define NoLock
Definition: lockdefs.h:34
Var * makeWholeRowVar(RangeTblEntry *rte, int varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:134
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:239
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
char * pstrdup(const char *in)
Definition: mcxt.c:1305
CmdType
Definition: nodes.h:720
@ CMD_MERGE
Definition: nodes.h:726
@ CMD_INSERT
Definition: nodes.h:724
@ CMD_DELETE
Definition: nodes.h:725
@ CMD_UPDATE
Definition: nodes.h:723
@ CMD_SELECT
Definition: nodes.h:722
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:189
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:191
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:192
@ RTE_RELATION
Definition: parsenodes.h:999
@ ROW_MARK_COPY
Definition: plannodes.h:1303
#define snprintf
Definition: port.h:225
#define InvalidOid
Definition: postgres_ext.h:36
static List * expand_insert_targetlist(List *tlist, Relation rel)
Definition: preptlist.c:357
List * extract_update_targetlist_colnos(List *tlist)
Definition: preptlist.c:323
Index prti
Definition: plannodes.h:1350
bool isParent
Definition: plannodes.h:1356
Index rowmarkId
Definition: plannodes.h:1351
int allMarkTypes
Definition: plannodes.h:1353
List * rowMarks
Definition: pathnodes.h:289
List * update_colnos
Definition: pathnodes.h:330
Definition: primnodes.h:209
int varno
Definition: primnodes.h:216
Definition: regcomp.c:238
#define TableOidAttributeNumber
Definition: sysattr.h:26
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
List * pull_var_clause(Node *node, int flags)
Definition: var.c:604

References generate_unaccent_rules::action, add_row_identity_columns(), PlanRowMark::allMarkTypes, Assert(), CMD_DELETE, CMD_INSERT, CMD_MERGE, CMD_SELECT, CMD_UPDATE, elog(), ERROR, expand_insert_targetlist(), extract_update_targetlist_colnos(), RangeTblEntry::inh, InvalidOid, IsA, PlanRowMark::isParent, lappend(), lfirst, list_concat_copy(), 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, ROW_MARK_COPY, PlanRowMark::rowmarkId, PlannerInfo::rowMarks, rt_fetch, RTE_RELATION, RangeTblEntry::rtekind, PlanRowMark::rti, SelfItemPointerAttributeNumber, snprintf, table_close(), table_open(), TableOidAttributeNumber, tlist_member(), PlannerInfo::update_colnos, and Var::varno.

Referenced by grouping_planner().

◆ pull_up_sublinks()

void pull_up_sublinks ( PlannerInfo root)

Definition at line 288 of file prepjointree.c.

289 {
290  Node *jtnode;
291  Relids relids;
292 
293  /* Begin recursion through the jointree */
294  jtnode = pull_up_sublinks_jointree_recurse(root,
295  (Node *) root->parse->jointree,
296  &relids);
297 
298  /*
299  * root->parse->jointree must always be a FromExpr, so insert a dummy one
300  * if we got a bare RangeTblRef or JoinExpr out of the recursion.
301  */
302  if (IsA(jtnode, FromExpr))
303  root->parse->jointree = (FromExpr *) jtnode;
304  else
305  root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
306 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:286
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:315

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

◆ pull_up_subqueries()

void pull_up_subqueries ( PlannerInfo root)

Definition at line 760 of file prepjointree.c.

761 {
762  /* Top level of jointree must always be a FromExpr */
763  Assert(IsA(root->parse->jointree, FromExpr));
764  /* Recursion starts with no containing join nor appendrel */
765  root->parse->jointree = (FromExpr *)
767  NULL, NULL, NULL);
768  /* We should still have a FromExpr */
769  Assert(IsA(root->parse->jointree, FromExpr));
770 }
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:810

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

◆ reduce_outer_joins()

void reduce_outer_joins ( PlannerInfo root)

Definition at line 2675 of file prepjointree.c.

2676 {
2678 
2679  /*
2680  * To avoid doing strictness checks on more quals than necessary, we want
2681  * to stop descending the jointree as soon as there are no outer joins
2682  * below our current point. This consideration forces a two-pass process.
2683  * The first pass gathers information about which base rels appear below
2684  * each side of each join clause, and about whether there are outer
2685  * join(s) below each side of each join clause. The second pass examines
2686  * qual clauses and changes join types as it descends the tree.
2687  */
2689 
2690  /* planner.c shouldn't have called me if no outer joins */
2691  if (state == NULL || !state->contains_outer)
2692  elog(ERROR, "so where are the outer joins?");
2693 
2695  state, root, NULL, NIL, NIL);
2696 }
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)
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
Definition: regguts.h:318

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

Referenced by subquery_planner().

◆ remove_useless_result_rtes()

void remove_useless_result_rtes ( PlannerInfo root)

Definition at line 3088 of file prepjointree.c.

3089 {
3090  ListCell *cell;
3091 
3092  /* Top level of jointree must always be a FromExpr */
3093  Assert(IsA(root->parse->jointree, FromExpr));
3094  /* Recurse ... */
3095  root->parse->jointree = (FromExpr *)
3097  /* We should still have a FromExpr */
3098  Assert(IsA(root->parse->jointree, FromExpr));
3099 
3100  /*
3101  * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
3102  * must do that for any RTE_RESULT that we just removed. But one for a
3103  * RTE that we did not remove can be dropped anyway: since the RTE has
3104  * only one possible output row, there is no need for EPQ to mark and
3105  * restore that row.
3106  *
3107  * It's necessary, not optional, to remove the PlanRowMark for a surviving
3108  * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
3109  * RTE_RESULT, which the executor has no support for.
3110  */
3111  foreach(cell, root->rowMarks)
3112  {
3113  PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3114 
3115  if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3116  root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3117  }
3118 }
@ RTE_RESULT
Definition: parsenodes.h:1007
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:388
static Node * remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)

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

◆ replace_empty_jointree()

void replace_empty_jointree ( Query parse)

Definition at line 230 of file prepjointree.c.

231 {
232  RangeTblEntry *rte;
233  Index rti;
234  RangeTblRef *rtr;
235 
236  /* Nothing to do if jointree is already nonempty */
237  if (parse->jointree->fromlist != NIL)
238  return;
239 
240  /* We mustn't change it in the top level of a setop tree, either */
241  if (parse->setOperations)
242  return;
243 
244  /* Create suitable RTE */
245  rte = makeNode(RangeTblEntry);
246  rte->rtekind = RTE_RESULT;
247  rte->eref = makeAlias("*RESULT*", NIL);
248 
249  /* Add it to rangetable */
250  parse->rtable = lappend(parse->rtable, rte);
251  rti = list_length(parse->rtable);
252 
253  /* And jam a reference into the jointree */
254  rtr = makeNode(RangeTblRef);
255  rtr->rtindex = rti;
256  parse->jointree->fromlist = list_make1(rtr);
257 }
unsigned int Index
Definition: c.h:560
Alias * makeAlias(const char *aliasname, List *colnames)
Definition: makefuncs.c:388
Alias * eref
Definition: parsenodes.h:1162

References RangeTblEntry::eref, lappend(), list_length(), list_make1, makeAlias(), makeNode, NIL, parse(), RTE_RESULT, RangeTblEntry::rtekind, and RangeTblRef::rtindex.

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

◆ transform_MERGE_to_join()

void transform_MERGE_to_join ( Query parse)

Definition at line 140 of file prepjointree.c.

141 {
142  RangeTblEntry *joinrte;
143  JoinExpr *joinexpr;
144  JoinType jointype;
145  int joinrti;
146  List *vars;
147 
148  if (parse->commandType != CMD_MERGE)
149  return;
150 
151  /* XXX probably bogus */
152  vars = NIL;
153 
154  /*
155  * When any WHEN NOT MATCHED THEN INSERT clauses exist, we need to use an
156  * outer join so that we process all unmatched tuples from the source
157  * relation. If none exist, we can use an inner join.
158  */
159  if (parse->mergeUseOuterJoin)
160  jointype = JOIN_RIGHT;
161  else
162  jointype = JOIN_INNER;
163 
164  /* Manufacture a join RTE to use. */
165  joinrte = makeNode(RangeTblEntry);
166  joinrte->rtekind = RTE_JOIN;
167  joinrte->jointype = jointype;
168  joinrte->joinmergedcols = 0;
169  joinrte->joinaliasvars = vars;
170  joinrte->joinleftcols = NIL; /* MERGE does not allow JOIN USING */
171  joinrte->joinrightcols = NIL; /* ditto */
172  joinrte->join_using_alias = NULL;
173 
174  joinrte->alias = NULL;
175  joinrte->eref = makeAlias("*MERGE*", NIL);
176  joinrte->lateral = false;
177  joinrte->inh = false;
178  joinrte->inFromCl = true;
179  joinrte->requiredPerms = 0;
180  joinrte->checkAsUser = InvalidOid;
181  joinrte->selectedCols = NULL;
182  joinrte->insertedCols = NULL;
183  joinrte->updatedCols = NULL;
184  joinrte->extraUpdatedCols = NULL;
185  joinrte->securityQuals = NIL;
186 
187  /*
188  * Add completed RTE to pstate's range table list, so that we know its
189  * index.
190  */
191  parse->rtable = lappend(parse->rtable, joinrte);
192  joinrti = list_length(parse->rtable);
193 
194  /*
195  * Create a JOIN between the target and the source relation.
196  */
197  joinexpr = makeNode(JoinExpr);
198  joinexpr->jointype = jointype;
199  joinexpr->isNatural = false;
200  joinexpr->larg = (Node *) makeNode(RangeTblRef);
201  ((RangeTblRef *) joinexpr->larg)->rtindex = parse->resultRelation;
202  joinexpr->rarg = linitial(parse->jointree->fromlist); /* original join */
203  joinexpr->usingClause = NIL;
204  joinexpr->join_using_alias = NULL;
205  /* The quals are removed from the jointree and into this specific join */
206  joinexpr->quals = parse->jointree->quals;
207  joinexpr->alias = NULL;
208  joinexpr->rtindex = joinrti;
209 
210  /* Make the new join be the sole entry in the query's jointree */
211  parse->jointree->fromlist = list_make1(joinexpr);
212  parse->jointree->quals = NULL;
213 }
JoinType
Definition: nodes.h:745
@ JOIN_INNER
Definition: nodes.h:750
@ JOIN_RIGHT
Definition: nodes.h:753
@ RTE_JOIN
Definition: parsenodes.h:1001
#define linitial(l)
Definition: pg_list.h:176
Node * quals
Definition: primnodes.h:1920
JoinType jointype
Definition: primnodes.h:1914
Alias * alias
Definition: primnodes.h:1921
int rtindex
Definition: primnodes.h:1922
List * usingClause
Definition: primnodes.h:1918
Alias * join_using_alias
Definition: primnodes.h:1919
Node * larg
Definition: primnodes.h:1916
bool isNatural
Definition: primnodes.h:1915
Node * rarg
Definition: primnodes.h:1917
Bitmapset * extraUpdatedCols
Definition: parsenodes.h:1171
AclMode requiredPerms
Definition: parsenodes.h:1166
Alias * join_using_alias
Definition: parsenodes.h:1100
List * securityQuals
Definition: parsenodes.h:1172
Bitmapset * updatedCols
Definition: parsenodes.h:1170
Bitmapset * selectedCols
Definition: parsenodes.h:1168
List * joinrightcols
Definition: parsenodes.h:1093
List * joinaliasvars
Definition: parsenodes.h:1091
JoinType jointype
Definition: parsenodes.h:1089
Alias * alias
Definition: parsenodes.h:1161
Bitmapset * insertedCols
Definition: parsenodes.h:1169
List * joinleftcols
Definition: parsenodes.h:1092

References RangeTblEntry::alias, JoinExpr::alias, RangeTblEntry::checkAsUser, CMD_MERGE, RangeTblEntry::eref, RangeTblEntry::extraUpdatedCols, RangeTblEntry::inFromCl, RangeTblEntry::inh, RangeTblEntry::insertedCols, InvalidOid, JoinExpr::isNatural, JOIN_INNER, JOIN_RIGHT, RangeTblEntry::join_using_alias, JoinExpr::join_using_alias, RangeTblEntry::joinaliasvars, RangeTblEntry::joinleftcols, RangeTblEntry::joinmergedcols, RangeTblEntry::joinrightcols, RangeTblEntry::jointype, JoinExpr::jointype, lappend(), JoinExpr::larg, RangeTblEntry::lateral, linitial, list_length(), list_make1, makeAlias(), makeNode, NIL, parse(), JoinExpr::quals, JoinExpr::rarg, RangeTblEntry::requiredPerms, RTE_JOIN, RangeTblEntry::rtekind, JoinExpr::rtindex, RangeTblEntry::securityQuals, RangeTblEntry::selectedCols, RangeTblEntry::updatedCols, and JoinExpr::usingClause.

Referenced by subquery_planner().