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)
 
Listpreprocess_targetlist (PlannerInfo *root)
 
PlanRowMarkget_plan_rowmark (List *rowmarks, Index rtindex)
 
RelOptInfoplan_set_operations (PlannerInfo *root)
 

Function Documentation

◆ flatten_simple_union_all()

void flatten_simple_union_all ( PlannerInfo root)

Definition at line 2433 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().

2434 {
2435  Query *parse = root->parse;
2436  SetOperationStmt *topop;
2437  Node *leftmostjtnode;
2438  int leftmostRTI;
2439  RangeTblEntry *leftmostRTE;
2440  int childRTI;
2441  RangeTblEntry *childRTE;
2442  RangeTblRef *rtr;
2443 
2444  /* Shouldn't be called unless query has setops */
2445  topop = castNode(SetOperationStmt, parse->setOperations);
2446  Assert(topop);
2447 
2448  /* Can't optimize away a recursive UNION */
2449  if (root->hasRecursion)
2450  return;
2451 
2452  /*
2453  * Recursively check the tree of set operations. If not all UNION ALL
2454  * with identical column types, punt.
2455  */
2456  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2457  return;
2458 
2459  /*
2460  * Locate the leftmost leaf query in the setops tree. The upper query's
2461  * Vars all refer to this RTE (see transformSetOperationStmt).
2462  */
2463  leftmostjtnode = topop->larg;
2464  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2465  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2466  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2467  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2468  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2469  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2470 
2471  /*
2472  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2473  * will represent the leftmost leaf query in its capacity as a member of
2474  * the appendrel. The original will represent the appendrel as a whole.
2475  * (We must do things this way because the upper query's Vars have to be
2476  * seen as referring to the whole appendrel.)
2477  */
2478  childRTE = copyObject(leftmostRTE);
2479  parse->rtable = lappend(parse->rtable, childRTE);
2480  childRTI = list_length(parse->rtable);
2481 
2482  /* Modify the setops tree to reference the child copy */
2483  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2484 
2485  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2486  leftmostRTE->inh = true;
2487 
2488  /*
2489  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2490  * Query of a setops tree should have had an empty FromClause initially.
2491  */
2492  rtr = makeNode(RangeTblRef);
2493  rtr->rtindex = leftmostRTI;
2494  Assert(parse->jointree->fromlist == NIL);
2495  parse->jointree->fromlist = list_make1(rtr);
2496 
2497  /*
2498  * Now pretend the query has no setops. We must do this before trying to
2499  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2500  */
2501  parse->setOperations = NULL;
2502 
2503  /*
2504  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2505  * leaf queries of the UNION ALL. (We must do that now because they
2506  * weren't previously referenced by the jointree, and so were missed by
2507  * the main invocation of pull_up_subqueries.)
2508  */
2509  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2510 }
#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:576
Query * parse
Definition: pathnodes.h:177
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
Definition: nodes.h:525
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1496
bool hasRecursion
Definition: pathnodes.h:348
#define list_make1(x1)
Definition: pg_list.h:227
List * rtable
Definition: parsenodes.h:137
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:322
#define makeNode(_type_)
Definition: nodes.h:573
#define Assert(condition)
Definition: c.h:732
static int list_length(const List *l)
Definition: pg_list.h:169
RTEKind rtekind
Definition: parsenodes.h:974
Node * setOperations
Definition: parsenodes.h:165
#define copyObject(obj)
Definition: nodes.h:641
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ get_plan_rowmark()

PlanRowMark* get_plan_rowmark ( List rowmarks,
Index  rtindex 
)

Definition at line 426 of file preptlist.c.

References lfirst, and PlanRowMark::rti.

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

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

◆ get_relids_for_join()

Relids get_relids_for_join ( Query query,
int  joinrelid 
)

Definition at line 3478 of file prepjointree.c.

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

Referenced by alias_relid_set().

3479 {
3480  Node *jtnode;
3481 
3482  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3483  joinrelid);
3484  if (!jtnode)
3485  elog(ERROR, "could not find join node %d", joinrelid);
3486  return get_relids_in_jointree(jtnode, false);
3487 }
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:525
static Node * find_jointree_node_for_rel(Node *jtnode, int relid)
#define ERROR
Definition: elog.h:43
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
#define elog(elevel,...)
Definition: elog.h:226

◆ get_relids_in_jointree()

Relids get_relids_in_jointree ( Node jtnode,
bool  include_joins 
)

Definition at line 3434 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(), get_relids_for_join(), get_relids_in_jointree(), is_simple_subquery(), preprocess_rowmarks(), pull_up_simple_subquery(), and remove_result_refs().

3435 {
3436  Relids result = NULL;
3437 
3438  if (jtnode == NULL)
3439  return result;
3440  if (IsA(jtnode, RangeTblRef))
3441  {
3442  int varno = ((RangeTblRef *) jtnode)->rtindex;
3443 
3444  result = bms_make_singleton(varno);
3445  }
3446  else if (IsA(jtnode, FromExpr))
3447  {
3448  FromExpr *f = (FromExpr *) jtnode;
3449  ListCell *l;
3450 
3451  foreach(l, f->fromlist)
3452  {
3453  result = bms_join(result,
3455  include_joins));
3456  }
3457  }
3458  else if (IsA(jtnode, JoinExpr))
3459  {
3460  JoinExpr *j = (JoinExpr *) jtnode;
3461 
3462  result = get_relids_in_jointree(j->larg, include_joins);
3463  result = bms_join(result,
3464  get_relids_in_jointree(j->rarg, include_joins));
3465  if (include_joins && j->rtindex)
3466  result = bms_add_member(result, j->rtindex);
3467  }
3468  else
3469  elog(ERROR, "unrecognized node type: %d",
3470  (int) nodeTag(jtnode));
3471  return result;
3472 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
List * fromlist
Definition: primnodes.h:1496
Node * larg
Definition: primnodes.h:1476
#define ERROR
Definition: elog.h:43
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:1477
#define lfirst(lc)
Definition: pg_list.h:190
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
#define nodeTag(nodeptr)
Definition: nodes.h:530
#define elog(elevel,...)
Definition: elog.h:226
int rtindex
Definition: primnodes.h:1481

◆ 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:433
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:177
bool ec_merging_done
Definition: pathnodes.h:266
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:594
Definition: nodes.h:525
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:1496
bool hasRecursion
Definition: pathnodes.h:348
Node * quals
Definition: primnodes.h:1497
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * distinctClause
Definition: parsenodes.h:156
RangeTblEntry ** simple_rte_array
Definition: pathnodes.h:209
#define Assert(condition)
Definition: c.h:732
List * eq_classes
Definition: pathnodes.h:264
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:74
Node * setOperations
Definition: parsenodes.h:165
Query * subquery
Definition: parsenodes.h:1009
List * groupClause
Definition: parsenodes.h:148
Node * havingQual
Definition: parsenodes.h:152
List * processed_tlist
Definition: pathnodes.h:323
Definition: pg_list.h:50
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ preprocess_function_rtes()

void preprocess_function_rtes ( PlannerInfo root)

Definition at line 635 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().

636 {
637  ListCell *rt;
638 
639  foreach(rt, root->parse->rtable)
640  {
641  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
642 
643  if (rte->rtekind == RTE_FUNCTION)
644  {
645  Query *funcquery;
646 
647  /* Apply const-simplification */
648  rte->functions = (List *)
649  eval_const_expressions(root, (Node *) rte->functions);
650 
651  /* Check safety of expansion, and expand if possible */
652  funcquery = inline_set_returning_function(root, rte);
653  if (funcquery)
654  {
655  /* Successful expansion, convert the RTE to a subquery */
656  rte->rtekind = RTE_SUBQUERY;
657  rte->subquery = funcquery;
658  rte->security_barrier = false;
659  /* Clear fields that should not be set in a subquery RTE */
660  rte->functions = NIL;
661  rte->funcordinality = false;
662  }
663  }
664  }
665 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:177
Definition: nodes.h:525
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4870
Node * eval_const_expressions(PlannerInfo *root, Node *node)
Definition: clauses.c:2253
bool funcordinality
Definition: parsenodes.h:1041
List * rtable
Definition: parsenodes.h:137
bool security_barrier
Definition: parsenodes.h:1010
#define lfirst(lc)
Definition: pg_list.h:190
List * functions
Definition: parsenodes.h:1040
RTEKind rtekind
Definition: parsenodes.h:974
Query * subquery
Definition: parsenodes.h:1009
Definition: pg_list.h:50

◆ preprocess_targetlist()

List* preprocess_targetlist ( PlannerInfo root)

Definition at line 70 of file preptlist.c.

References PlanRowMark::allMarkTypes, Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, elog, ERROR, expand_targetlist(), InvalidOid, IsA, PlanRowMark::isParent, lappend(), lfirst, list_free(), list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NoLock, Query::onConflict, OnConflictExpr::onConflictSet, parse(), PlannerInfo::parse, PlanRowMark::prti, pstrdup(), pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, RangeTblEntry::relid, Query::resultRelation, Query::returningList, rewriteTargetListUD(), 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(), and Var::varno.

Referenced by grouping_planner(), and inheritance_planner().

71 {
72  Query *parse = root->parse;
73  int result_relation = parse->resultRelation;
74  List *range_table = parse->rtable;
75  CmdType command_type = parse->commandType;
76  RangeTblEntry *target_rte = NULL;
77  Relation target_relation = NULL;
78  List *tlist;
79  ListCell *lc;
80 
81  /*
82  * If there is a result relation, open it so we can look for missing
83  * columns and so on. We assume that previous code already acquired at
84  * least AccessShareLock on the relation, so we need no lock here.
85  */
86  if (result_relation)
87  {
88  target_rte = rt_fetch(result_relation, range_table);
89 
90  /*
91  * Sanity check: it'd better be a real relation not, say, a subquery.
92  * Else parser or rewriter messed up.
93  */
94  if (target_rte->rtekind != RTE_RELATION)
95  elog(ERROR, "result relation must be a regular relation");
96 
97  target_relation = table_open(target_rte->relid, NoLock);
98  }
99  else
100  Assert(command_type == CMD_SELECT);
101 
102  /*
103  * For UPDATE/DELETE, add any junk column(s) needed to allow the executor
104  * to identify the rows to be updated or deleted. Note that this step
105  * scribbles on parse->targetList, which is not very desirable, but we
106  * keep it that way to avoid changing APIs used by FDWs.
107  */
108  if (command_type == CMD_UPDATE || command_type == CMD_DELETE)
109  rewriteTargetListUD(parse, target_rte, target_relation);
110 
111  /*
112  * for heap_form_tuple to work, the targetlist must match the exact order
113  * of the attributes. We also need to fill in any missing attributes. -ay
114  * 10/94
115  */
116  tlist = parse->targetList;
117  if (command_type == CMD_INSERT || command_type == CMD_UPDATE)
118  tlist = expand_targetlist(tlist, command_type,
119  result_relation, target_relation);
120 
121  /*
122  * Add necessary junk columns for rowmarked rels. These values are needed
123  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
124  * rechecking. See comments for PlanRowMark in plannodes.h. If you
125  * change this stanza, see also expand_inherited_rtentry(), which has to
126  * be able to add on junk columns equivalent to these.
127  */
128  foreach(lc, root->rowMarks)
129  {
130  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
131  Var *var;
132  char resname[32];
133  TargetEntry *tle;
134 
135  /* child rels use the same junk attrs as their parents */
136  if (rc->rti != rc->prti)
137  continue;
138 
139  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
140  {
141  /* Need to fetch TID */
142  var = makeVar(rc->rti,
144  TIDOID,
145  -1,
146  InvalidOid,
147  0);
148  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
149  tle = makeTargetEntry((Expr *) var,
150  list_length(tlist) + 1,
151  pstrdup(resname),
152  true);
153  tlist = lappend(tlist, tle);
154  }
155  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
156  {
157  /* Need the whole row as a junk var */
158  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
159  rc->rti,
160  0,
161  false);
162  snprintf(resname, sizeof(resname), "wholerow%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 
170  /* If parent of inheritance tree, always fetch the tableoid too. */
171  if (rc->isParent)
172  {
173  var = makeVar(rc->rti,
175  OIDOID,
176  -1,
177  InvalidOid,
178  0);
179  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
180  tle = makeTargetEntry((Expr *) var,
181  list_length(tlist) + 1,
182  pstrdup(resname),
183  true);
184  tlist = lappend(tlist, tle);
185  }
186  }
187 
188  /*
189  * If the query has a RETURNING list, add resjunk entries for any Vars
190  * used in RETURNING that belong to other relations. We need to do this
191  * to make these Vars available for the RETURNING calculation. Vars that
192  * belong to the result rel don't need to be added, because they will be
193  * made to refer to the actual heap tuple.
194  */
195  if (parse->returningList && list_length(parse->rtable) > 1)
196  {
197  List *vars;
198  ListCell *l;
199 
200  vars = pull_var_clause((Node *) parse->returningList,
204  foreach(l, vars)
205  {
206  Var *var = (Var *) lfirst(l);
207  TargetEntry *tle;
208 
209  if (IsA(var, Var) &&
210  var->varno == result_relation)
211  continue; /* don't need it */
212 
213  if (tlist_member((Expr *) var, tlist))
214  continue; /* already got it */
215 
216  tle = makeTargetEntry((Expr *) var,
217  list_length(tlist) + 1,
218  NULL,
219  true);
220 
221  tlist = lappend(tlist, tle);
222  }
223  list_free(vars);
224  }
225 
226  /*
227  * If there's an ON CONFLICT UPDATE clause, preprocess its targetlist too
228  * while we have the relation open.
229  */
230  if (parse->onConflict)
231  parse->onConflict->onConflictSet =
233  CMD_UPDATE,
234  result_relation,
235  target_relation);
236 
237  if (target_relation)
238  table_close(target_relation, NoLock);
239 
240  return tlist;
241 }
List * rowMarks
Definition: pathnodes.h:290
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:177
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:133
OnConflictExpr * onConflict
Definition: parsenodes.h:144
char * pstrdup(const char *in)
Definition: mcxt.c:1186
int resultRelation
Definition: parsenodes.h:122
Definition: nodes.h:525
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:133
Index prti
Definition: plannodes.h:1058
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
Definition: primnodes.h:167
Index rowmarkId
Definition: plannodes.h:1059
List * targetList
Definition: parsenodes.h:140
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define TableOidAttributeNumber
Definition: sysattr.h:26
int allMarkTypes
Definition: plannodes.h:1061
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:236
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:322
Index varno
Definition: primnodes.h:170
#define PVC_INCLUDE_PLACEHOLDERS
Definition: optimizer.h:174
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:73
static List * expand_targetlist(List *tlist, int command_type, Index result_relation, Relation rel)
Definition: preptlist.c:257
#define InvalidOid
Definition: postgres_ext.h:36
CmdType commandType
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
static int list_length(const List *l)
Definition: pg_list.h:169
RTEKind rtekind
Definition: parsenodes.h:974
#define PVC_RECURSE_WINDOWFUNCS
Definition: optimizer.h:173
void list_free(List *list)
Definition: list.c:1377
#define elog(elevel,...)
Definition: elog.h:226
List * onConflictSet
Definition: primnodes.h:1521
bool isParent
Definition: plannodes.h:1064
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
Definition: regcomp.c:224
Definition: pg_list.h:50
#define snprintf
Definition: port.h:192
void rewriteTargetListUD(Query *parsetree, RangeTblEntry *target_rte, Relation target_relation)
#define PVC_RECURSE_AGGREGATES
Definition: optimizer.h:171
CmdType
Definition: nodes.h:668
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:648

◆ pull_up_sublinks()

void pull_up_sublinks ( PlannerInfo root)

Definition at line 204 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().

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

◆ pull_up_subqueries()

void pull_up_subqueries ( PlannerInfo root)

Definition at line 676 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().

677 {
678  /* Top level of jointree must always be a FromExpr */
679  Assert(IsA(root->parse->jointree, FromExpr));
680  /* Recursion starts with no containing join nor appendrel */
681  root->parse->jointree = (FromExpr *)
683  NULL, NULL, NULL);
684  /* We should still have a FromExpr */
685  Assert(IsA(root->parse->jointree, FromExpr));
686 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:177
FromExpr * jointree
Definition: parsenodes.h:138
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:726
Definition: nodes.h:525
#define Assert(condition)
Definition: c.h:732

◆ reduce_outer_joins()

void reduce_outer_joins ( PlannerInfo root)

Definition at line 2551 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().

2552 {
2554 
2555  /*
2556  * To avoid doing strictness checks on more quals than necessary, we want
2557  * to stop descending the jointree as soon as there are no outer joins
2558  * below our current point. This consideration forces a two-pass process.
2559  * The first pass gathers information about which base rels appear below
2560  * each side of each join clause, and about whether there are outer
2561  * join(s) below each side of each join clause. The second pass examines
2562  * qual clauses and changes join types as it descends the tree.
2563  */
2564  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2565 
2566  /* planner.c shouldn't have called me if no outer joins */
2567  if (state == NULL || !state->contains_outer)
2568  elog(ERROR, "so where are the outer joins?");
2569 
2571  state, root, NULL, NIL, NIL);
2572 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:177
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:525
#define ERROR
Definition: elog.h:43
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
Definition: regguts.h:298
#define elog(elevel,...)
Definition: elog.h:226
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 2961 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().

2962 {
2963  ListCell *cell;
2964 
2965  /* Top level of jointree must always be a FromExpr */
2966  Assert(IsA(root->parse->jointree, FromExpr));
2967  /* Recurse ... */
2968  root->parse->jointree = (FromExpr *)
2970  /* We should still have a FromExpr */
2971  Assert(IsA(root->parse->jointree, FromExpr));
2972 
2973  /*
2974  * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
2975  * must do that for any RTE_RESULT that we just removed. But one for a
2976  * RTE that we did not remove can be dropped anyway: since the RTE has
2977  * only one possible output row, there is no need for EPQ to mark and
2978  * restore that row.
2979  *
2980  * It's necessary, not optional, to remove the PlanRowMark for a surviving
2981  * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
2982  * RTE_RESULT, which the executor has no support for.
2983  */
2984  foreach(cell, root->rowMarks)
2985  {
2986  PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
2987 
2988  if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
2989  root->rowMarks = foreach_delete_current(root->rowMarks, cell);
2990  }
2991 }
List * rowMarks
Definition: pathnodes.h:290
#define IsA(nodeptr, _type_)
Definition: nodes.h:576
Query * parse
Definition: pathnodes.h:177
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:525
#define foreach_delete_current(lst, cell)
Definition: pg_list.h:368
List * rtable
Definition: parsenodes.h:137
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
#define Assert(condition)
Definition: c.h:732
#define lfirst(lc)
Definition: pg_list.h:190
static Node * remove_useless_results_recurse(PlannerInfo *root, Node *jtnode)

◆ replace_empty_jointree()

void replace_empty_jointree ( Query parse)

Definition at line 146 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().

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