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

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

◆ get_relids_for_join()

Relids get_relids_for_join ( Query query,
int  joinrelid 
)

Definition at line 3559 of file prepjointree.c.

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

Referenced by alias_relid_set().

3560 {
3561  Node *jtnode;
3562 
3563  jtnode = find_jointree_node_for_rel((Node *) query->jointree,
3564  joinrelid);
3565  if (!jtnode)
3566  elog(ERROR, "could not find join node %d", joinrelid);
3567  return get_relids_in_jointree(jtnode, false);
3568 }
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:529
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:214

◆ get_relids_in_jointree()

Relids get_relids_in_jointree ( Node jtnode,
bool  include_joins 
)

Definition at line 3515 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(), pull_up_simple_subquery(), and remove_result_refs().

3516 {
3517  Relids result = NULL;
3518 
3519  if (jtnode == NULL)
3520  return result;
3521  if (IsA(jtnode, RangeTblRef))
3522  {
3523  int varno = ((RangeTblRef *) jtnode)->rtindex;
3524 
3525  result = bms_make_singleton(varno);
3526  }
3527  else if (IsA(jtnode, FromExpr))
3528  {
3529  FromExpr *f = (FromExpr *) jtnode;
3530  ListCell *l;
3531 
3532  foreach(l, f->fromlist)
3533  {
3534  result = bms_join(result,
3536  include_joins));
3537  }
3538  }
3539  else if (IsA(jtnode, JoinExpr))
3540  {
3541  JoinExpr *j = (JoinExpr *) jtnode;
3542 
3543  result = get_relids_in_jointree(j->larg, include_joins);
3544  result = bms_join(result,
3545  get_relids_in_jointree(j->rarg, include_joins));
3546  if (include_joins && j->rtindex)
3547  result = bms_add_member(result, j->rtindex);
3548  }
3549  else
3550  elog(ERROR, "unrecognized node type: %d",
3551  (int) nodeTag(jtnode));
3552  return result;
3553 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
List * fromlist
Definition: primnodes.h:1510
Node * larg
Definition: primnodes.h:1490
#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:1491
#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:534
#define elog(elevel,...)
Definition: elog.h:214
int rtindex
Definition: primnodes.h:1495

◆ 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:580
Query * parse
Definition: pathnodes.h:179
bool ec_merging_done
Definition: pathnodes.h:268
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:598
Definition: nodes.h:529
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:1510
bool hasRecursion
Definition: pathnodes.h:350
Node * quals
Definition: primnodes.h:1511
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:211
#define Assert(condition)
Definition: c.h:745
List * eq_classes
Definition: pathnodes.h:266
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:83
Node * setOperations
Definition: parsenodes.h:166
Query * subquery
Definition: parsenodes.h:1011
List * groupClause
Definition: parsenodes.h:148
Node * havingQual
Definition: parsenodes.h:152
List * processed_tlist
Definition: pathnodes.h:325
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 637 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().

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

◆ preprocess_targetlist()

List* preprocess_targetlist ( PlannerInfo root)

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

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

207 {
208  Node *jtnode;
209  Relids relids;
210 
211  /* Begin recursion through the jointree */
212  jtnode = pull_up_sublinks_jointree_recurse(root,
213  (Node *) root->parse->jointree,
214  &relids);
215 
216  /*
217  * root->parse->jointree must always be a FromExpr, so insert a dummy one
218  * if we got a bare RangeTblRef or JoinExpr out of the recursion.
219  */
220  if (IsA(jtnode, FromExpr))
221  root->parse->jointree = (FromExpr *) jtnode;
222  else
223  root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
224 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:285
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Query * parse
Definition: pathnodes.h:179
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:529
#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:233

◆ pull_up_subqueries()

void pull_up_subqueries ( PlannerInfo root)

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

679 {
680  /* Top level of jointree must always be a FromExpr */
681  Assert(IsA(root->parse->jointree, FromExpr));
682  /* Recursion starts with no containing join nor appendrel */
683  root->parse->jointree = (FromExpr *)
685  NULL, NULL, NULL);
686  /* We should still have a FromExpr */
687  Assert(IsA(root->parse->jointree, FromExpr));
688 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Query * parse
Definition: pathnodes.h:179
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:728
Definition: nodes.h:529
#define Assert(condition)
Definition: c.h:745

◆ reduce_outer_joins()

void reduce_outer_joins ( PlannerInfo root)

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

2562 {
2564 
2565  /*
2566  * To avoid doing strictness checks on more quals than necessary, we want
2567  * to stop descending the jointree as soon as there are no outer joins
2568  * below our current point. This consideration forces a two-pass process.
2569  * The first pass gathers information about which base rels appear below
2570  * each side of each join clause, and about whether there are outer
2571  * join(s) below each side of each join clause. The second pass examines
2572  * qual clauses and changes join types as it descends the tree.
2573  */
2574  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2575 
2576  /* planner.c shouldn't have called me if no outer joins */
2577  if (state == NULL || !state->contains_outer)
2578  elog(ERROR, "so where are the outer joins?");
2579 
2581  state, root, NULL, NIL, NIL);
2582 }
#define NIL
Definition: pg_list.h:65
Query * parse
Definition: pathnodes.h:179
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:529
#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:214
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 2974 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().

2975 {
2976  ListCell *cell;
2977 
2978  /* Top level of jointree must always be a FromExpr */
2979  Assert(IsA(root->parse->jointree, FromExpr));
2980  /* Recurse ... */
2981  root->parse->jointree = (FromExpr *)
2983  /* We should still have a FromExpr */
2984  Assert(IsA(root->parse->jointree, FromExpr));
2985 
2986  /*
2987  * Remove any PlanRowMark referencing an RTE_RESULT RTE. We obviously
2988  * must do that for any RTE_RESULT that we just removed. But one for a
2989  * RTE that we did not remove can be dropped anyway: since the RTE has
2990  * only one possible output row, there is no need for EPQ to mark and
2991  * restore that row.
2992  *
2993  * It's necessary, not optional, to remove the PlanRowMark for a surviving
2994  * RTE_RESULT RTE; otherwise we'll generate a whole-row Var for the
2995  * RTE_RESULT, which the executor has no support for.
2996  */
2997  foreach(cell, root->rowMarks)
2998  {
2999  PlanRowMark *rc = (PlanRowMark *) lfirst(cell);
3000 
3001  if (rt_fetch(rc->rti, root->parse->rtable)->rtekind == RTE_RESULT)
3002  root->rowMarks = foreach_delete_current(root->rowMarks, cell);
3003  }
3004 }
List * rowMarks
Definition: pathnodes.h:292
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Query * parse
Definition: pathnodes.h:179
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:529
#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:745
#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 148 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().

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