PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
prep.h File Reference
#include "nodes/plannodes.h"
#include "nodes/relation.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 pull_up_sublinks (PlannerInfo *root)
 
void inline_set_returning_functions (PlannerInfo *root)
 
void pull_up_subqueries (PlannerInfo *root)
 
void flatten_simple_union_all (PlannerInfo *root)
 
void reduce_outer_joins (PlannerInfo *root)
 
Relids get_relids_in_jointree (Node *jtnode, bool include_joins)
 
Relids get_relids_for_join (PlannerInfo *root, int joinrelid)
 
Nodenegate_clause (Node *node)
 
Exprcanonicalize_qual (Expr *qual)
 
Listpreprocess_targetlist (PlannerInfo *root, List *tlist)
 
Listpreprocess_onconflict_targetlist (List *tlist, int result_relation, List *range_table)
 
PlanRowMarkget_plan_rowmark (List *rowmarks, Index rtindex)
 
RelOptInfoplan_set_operations (PlannerInfo *root)
 
void expand_inherited_tables (PlannerInfo *root)
 
Nodeadjust_appendrel_attrs (PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
 
Nodeadjust_appendrel_attrs_multilevel (PlannerInfo *root, Node *node, RelOptInfo *child_rel)
 

Function Documentation

Node* adjust_appendrel_attrs ( PlannerInfo root,
Node node,
AppendRelInfo appinfo 
)

Definition at line 1734 of file prepunion.c.

References adjust_appendrel_attrs_mutator(), adjust_inherited_tlist(), adjust_appendrel_attrs_context::appinfo, AppendRelInfo::child_relid, CMD_UPDATE, Query::commandType, IsA, AppendRelInfo::parent_relid, QTW_IGNORE_RC_SUBQUERIES, query_tree_mutator(), Query::resultRelation, adjust_appendrel_attrs_context::root, and Query::targetList.

Referenced by add_child_rel_equivalences(), adjust_appendrel_attrs_multilevel(), inheritance_planner(), and set_append_rel_size().

1735 {
1736  Node *result;
1738 
1739  context.root = root;
1740  context.appinfo = appinfo;
1741 
1742  /*
1743  * Must be prepared to start with a Query or a bare expression tree.
1744  */
1745  if (node && IsA(node, Query))
1746  {
1747  Query *newnode;
1748 
1749  newnode = query_tree_mutator((Query *) node,
1751  (void *) &context,
1753  if (newnode->resultRelation == appinfo->parent_relid)
1754  {
1755  newnode->resultRelation = appinfo->child_relid;
1756  /* Fix tlist resnos too, if it's inherited UPDATE */
1757  if (newnode->commandType == CMD_UPDATE)
1758  newnode->targetList =
1760  appinfo);
1761  }
1762  result = (Node *) newnode;
1763  }
1764  else
1765  result = adjust_appendrel_attrs_mutator(node, &context);
1766 
1767  return result;
1768 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
int resultRelation
Definition: parsenodes.h:113
Definition: nodes.h:508
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: prepunion.c:2013
List * targetList
Definition: parsenodes.h:131
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
CmdType commandType
Definition: parsenodes.h:103
static Node * adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context)
Definition: prepunion.c:1771
Index child_relid
Definition: relation.h:1866
Index parent_relid
Definition: relation.h:1865
Query * query_tree_mutator(Query *query, Node *(*mutator)(), void *context, int flags)
Definition: nodeFuncs.c:3046
Node* adjust_appendrel_attrs_multilevel ( PlannerInfo root,
Node node,
RelOptInfo child_rel 
)

Definition at line 2101 of file prepunion.c.

References adjust_appendrel_attrs(), adjust_appendrel_attrs_multilevel(), Assert, find_base_rel(), find_childrel_appendrelinfo(), AppendRelInfo::parent_relid, RELOPT_BASEREL, RELOPT_OTHER_MEMBER_REL, and RelOptInfo::reloptkind.

Referenced by adjust_appendrel_attrs_multilevel(), and generate_join_implied_equalities_broken().

2103 {
2104  AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, child_rel);
2105  RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid);
2106 
2107  /* If parent is also a child, first recurse to apply its translations */
2108  if (parent_rel->reloptkind == RELOPT_OTHER_MEMBER_REL)
2109  node = adjust_appendrel_attrs_multilevel(root, node, parent_rel);
2110  else
2111  Assert(parent_rel->reloptkind == RELOPT_BASEREL);
2112  /* Now translate for this child */
2113  return adjust_appendrel_attrs(root, node, appinfo);
2114 }
RelOptKind reloptkind
Definition: relation.h:487
AppendRelInfo * find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:921
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
Definition: prepunion.c:1734
#define Assert(condition)
Definition: c.h:670
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *child_rel)
Definition: prepunion.c:2101
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:219
Index parent_relid
Definition: relation.h:1865
Expr* canonicalize_qual ( Expr qual)

Definition at line 286 of file prepqual.c.

References find_duplicate_ors(), and NULL.

Referenced by ATExecAttachPartition(), convert_EXISTS_to_ANY(), get_relation_constraints(), preprocess_expression(), RelationGetIndexExpressions(), and RelationGetIndexPredicate().

287 {
288  Expr *newqual;
289 
290  /* Quick exit for empty qual */
291  if (qual == NULL)
292  return NULL;
293 
294  /*
295  * Pull up redundant subclauses in OR-of-AND trees. We do this only
296  * within the top-level AND/OR structure; there's no point in looking
297  * deeper. Also remove any NULL constants in the top-level structure.
298  */
299  newqual = find_duplicate_ors(qual);
300 
301  return newqual;
302 }
#define NULL
Definition: c.h:226
static Expr * find_duplicate_ors(Expr *qual)
Definition: prepqual.c:407
void expand_inherited_tables ( PlannerInfo root)

Definition at line 1318 of file prepunion.c.

References expand_inherited_rtentry(), lfirst, list_head(), list_length(), lnext, PlannerInfo::parse, and Query::rtable.

Referenced by subquery_planner().

1319 {
1320  Index nrtes;
1321  Index rti;
1322  ListCell *rl;
1323 
1324  /*
1325  * expand_inherited_rtentry may add RTEs to parse->rtable; there is no
1326  * need to scan them since they can't have inh=true. So just scan as far
1327  * as the original end of the rtable list.
1328  */
1329  nrtes = list_length(root->parse->rtable);
1330  rl = list_head(root->parse->rtable);
1331  for (rti = 1; rti <= nrtes; rti++)
1332  {
1333  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1334 
1335  expand_inherited_rtentry(root, rte, rti);
1336  rl = lnext(rl);
1337  }
1338 }
Query * parse
Definition: relation.h:152
List * rtable
Definition: parsenodes.h:128
static ListCell * list_head(const List *l)
Definition: pg_list.h:77
#define lnext(lc)
Definition: pg_list.h:105
static void expand_inherited_rtentry(PlannerInfo *root, RangeTblEntry *rte, Index rti)
Definition: prepunion.c:1357
unsigned int Index
Definition: c.h:361
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
void flatten_simple_union_all ( PlannerInfo root)

Definition at line 2314 of file prepjointree.c.

References Assert, SetOperationStmt::colTypes, copyObject(), FromExpr::fromlist, PlannerInfo::hasRecursion, RangeTblEntry::inh, is_simple_union_all_recurse(), IsA, Query::jointree, lappend(), SetOperationStmt::larg, list_length(), list_make1, makeNode, NIL, NULL, 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().

2315 {
2316  Query *parse = root->parse;
2317  SetOperationStmt *topop;
2318  Node *leftmostjtnode;
2319  int leftmostRTI;
2320  RangeTblEntry *leftmostRTE;
2321  int childRTI;
2322  RangeTblEntry *childRTE;
2323  RangeTblRef *rtr;
2324 
2325  /* Shouldn't be called unless query has setops */
2326  topop = (SetOperationStmt *) parse->setOperations;
2327  Assert(topop && IsA(topop, SetOperationStmt));
2328 
2329  /* Can't optimize away a recursive UNION */
2330  if (root->hasRecursion)
2331  return;
2332 
2333  /*
2334  * Recursively check the tree of set operations. If not all UNION ALL
2335  * with identical column types, punt.
2336  */
2337  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2338  return;
2339 
2340  /*
2341  * Locate the leftmost leaf query in the setops tree. The upper query's
2342  * Vars all refer to this RTE (see transformSetOperationStmt).
2343  */
2344  leftmostjtnode = topop->larg;
2345  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2346  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2347  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2348  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2349  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2350  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2351 
2352  /*
2353  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2354  * will represent the leftmost leaf query in its capacity as a member of
2355  * the appendrel. The original will represent the appendrel as a whole.
2356  * (We must do things this way because the upper query's Vars have to be
2357  * seen as referring to the whole appendrel.)
2358  */
2359  childRTE = copyObject(leftmostRTE);
2360  parse->rtable = lappend(parse->rtable, childRTE);
2361  childRTI = list_length(parse->rtable);
2362 
2363  /* Modify the setops tree to reference the child copy */
2364  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2365 
2366  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2367  leftmostRTE->inh = true;
2368 
2369  /*
2370  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2371  * Query of a setops tree should have had an empty FromClause initially.
2372  */
2373  rtr = makeNode(RangeTblRef);
2374  rtr->rtindex = leftmostRTI;
2375  Assert(parse->jointree->fromlist == NIL);
2376  parse->jointree->fromlist = list_make1(rtr);
2377 
2378  /*
2379  * Now pretend the query has no setops. We must do this before trying to
2380  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2381  */
2382  parse->setOperations = NULL;
2383 
2384  /*
2385  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2386  * leaf queries of the UNION ALL. (We must do that now because they
2387  * weren't previously referenced by the jointree, and so were missed by
2388  * the main invocation of pull_up_subqueries.)
2389  */
2390  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2391 }
#define NIL
Definition: pg_list.h:69
static void pull_up_union_leaf_queries(Node *setOp, PlannerInfo *root, int parentRTindex, Query *setOpQuery, int childRToffset)
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
FromExpr * jointree
Definition: parsenodes.h:129
Definition: nodes.h:508
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1433
bool hasRecursion
Definition: relation.h:300
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
#define list_make1(x1)
Definition: pg_list.h:133
List * rtable
Definition: parsenodes.h:128
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:128
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:882
Node * setOperations
Definition: parsenodes.h:154
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
PlanRowMark* get_plan_rowmark ( List rowmarks,
Index  rtindex 
)

Definition at line 401 of file preptlist.c.

References lfirst, NULL, and PlanRowMark::rti.

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

402 {
403  ListCell *l;
404 
405  foreach(l, rowmarks)
406  {
407  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
408 
409  if (rc->rti == rtindex)
410  return rc;
411  }
412  return NULL;
413 }
Index rti
Definition: plannodes.h:940
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Relids get_relids_for_join ( PlannerInfo root,
int  joinrelid 
)

Definition at line 2980 of file prepjointree.c.

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

Referenced by alias_relid_set().

2981 {
2982  Node *jtnode;
2983 
2984  jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
2985  joinrelid);
2986  if (!jtnode)
2987  elog(ERROR, "could not find join node %d", joinrelid);
2988  return get_relids_in_jointree(jtnode, false);
2989 }
Query * parse
Definition: relation.h:152
FromExpr * jointree
Definition: parsenodes.h:129
Definition: nodes.h:508
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
Definition: elog.h:219
Relids get_relids_in_jointree ( Node jtnode,
bool  include_joins 
)

Definition at line 2936 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, NULL, JoinExpr::rarg, and JoinExpr::rtindex.

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

2937 {
2938  Relids result = NULL;
2939 
2940  if (jtnode == NULL)
2941  return result;
2942  if (IsA(jtnode, RangeTblRef))
2943  {
2944  int varno = ((RangeTblRef *) jtnode)->rtindex;
2945 
2946  result = bms_make_singleton(varno);
2947  }
2948  else if (IsA(jtnode, FromExpr))
2949  {
2950  FromExpr *f = (FromExpr *) jtnode;
2951  ListCell *l;
2952 
2953  foreach(l, f->fromlist)
2954  {
2955  result = bms_join(result,
2957  include_joins));
2958  }
2959  }
2960  else if (IsA(jtnode, JoinExpr))
2961  {
2962  JoinExpr *j = (JoinExpr *) jtnode;
2963 
2964  result = get_relids_in_jointree(j->larg, include_joins);
2965  result = bms_join(result,
2966  get_relids_in_jointree(j->rarg, include_joins));
2967  if (include_joins && j->rtindex)
2968  result = bms_add_member(result, j->rtindex);
2969  }
2970  else
2971  elog(ERROR, "unrecognized node type: %d",
2972  (int) nodeTag(jtnode));
2973  return result;
2974 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
List * fromlist
Definition: primnodes.h:1433
Node * larg
Definition: primnodes.h:1413
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:808
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:178
Node * rarg
Definition: primnodes.h:1414
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
#define nodeTag(nodeptr)
Definition: nodes.h:513
#define elog
Definition: elog.h:219
int rtindex
Definition: primnodes.h:1418
void inline_set_returning_functions ( PlannerInfo root)

Definition at line 573 of file prepjointree.c.

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

574 {
575  ListCell *rt;
576 
577  foreach(rt, root->parse->rtable)
578  {
579  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
580 
581  if (rte->rtekind == RTE_FUNCTION)
582  {
583  Query *funcquery;
584 
585  /* Check safety of expansion, and expand if possible */
586  funcquery = inline_set_returning_function(root, rte);
587  if (funcquery)
588  {
589  /* Successful expansion, replace the rtable entry */
590  rte->rtekind = RTE_SUBQUERY;
591  rte->subquery = funcquery;
592  rte->functions = NIL;
593  }
594  }
595  }
596 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4736
List * rtable
Definition: parsenodes.h:128
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:931
RTEKind rtekind
Definition: parsenodes.h:882
Query * subquery
Definition: parsenodes.h:900
Node* negate_clause ( Node node)

Definition at line 73 of file prepqual.c.

References AND_EXPR, NullTest::arg, BooleanTest::arg, NullTest::argisrow, OpExpr::args, ScalarArrayOpExpr::args, BoolExpr::args, BoolExpr::boolop, BooleanTest::booltesttype, Const::constisnull, Const::constvalue, DatumGetBool, elog, ERROR, get_negator(), OpExpr::inputcollid, ScalarArrayOpExpr::inputcollid, InvalidOid, IS_FALSE, IS_NOT_FALSE, IS_NOT_NULL, IS_NOT_TRUE, IS_NOT_UNKNOWN, IS_NULL, IS_TRUE, IS_UNKNOWN, lappend(), lfirst, linitial, OpExpr::location, ScalarArrayOpExpr::location, NullTest::location, BooleanTest::location, make_andclause(), make_notclause(), make_orclause(), makeBoolConst(), makeNode, negate_clause(), NIL, nodeTag, NOT_EXPR, NULL, NullTest::nulltesttype, OpExpr::opcollid, OpExpr::opfuncid, ScalarArrayOpExpr::opfuncid, OpExpr::opno, ScalarArrayOpExpr::opno, OpExpr::opresulttype, OpExpr::opretset, OR_EXPR, T_BooleanTest, T_BoolExpr, T_Const, T_NullTest, T_OpExpr, T_ScalarArrayOpExpr, and ScalarArrayOpExpr::useOr.

Referenced by eval_const_expressions_mutator(), negate_clause(), and simplify_boolean_equality().

74 {
75  if (node == NULL) /* should not happen */
76  elog(ERROR, "can't negate an empty subexpression");
77  switch (nodeTag(node))
78  {
79  case T_Const:
80  {
81  Const *c = (Const *) node;
82 
83  /* NOT NULL is still NULL */
84  if (c->constisnull)
85  return makeBoolConst(false, true);
86  /* otherwise pretty easy */
87  return makeBoolConst(!DatumGetBool(c->constvalue), false);
88  }
89  break;
90  case T_OpExpr:
91  {
92  /*
93  * Negate operator if possible: (NOT (< A B)) => (>= A B)
94  */
95  OpExpr *opexpr = (OpExpr *) node;
96  Oid negator = get_negator(opexpr->opno);
97 
98  if (negator)
99  {
100  OpExpr *newopexpr = makeNode(OpExpr);
101 
102  newopexpr->opno = negator;
103  newopexpr->opfuncid = InvalidOid;
104  newopexpr->opresulttype = opexpr->opresulttype;
105  newopexpr->opretset = opexpr->opretset;
106  newopexpr->opcollid = opexpr->opcollid;
107  newopexpr->inputcollid = opexpr->inputcollid;
108  newopexpr->args = opexpr->args;
109  newopexpr->location = opexpr->location;
110  return (Node *) newopexpr;
111  }
112  }
113  break;
114  case T_ScalarArrayOpExpr:
115  {
116  /*
117  * Negate a ScalarArrayOpExpr if its operator has a negator;
118  * for example x = ANY (list) becomes x <> ALL (list)
119  */
120  ScalarArrayOpExpr *saopexpr = (ScalarArrayOpExpr *) node;
121  Oid negator = get_negator(saopexpr->opno);
122 
123  if (negator)
124  {
126 
127  newopexpr->opno = negator;
128  newopexpr->opfuncid = InvalidOid;
129  newopexpr->useOr = !saopexpr->useOr;
130  newopexpr->inputcollid = saopexpr->inputcollid;
131  newopexpr->args = saopexpr->args;
132  newopexpr->location = saopexpr->location;
133  return (Node *) newopexpr;
134  }
135  }
136  break;
137  case T_BoolExpr:
138  {
139  BoolExpr *expr = (BoolExpr *) node;
140 
141  switch (expr->boolop)
142  {
143  /*--------------------
144  * Apply DeMorgan's Laws:
145  * (NOT (AND A B)) => (OR (NOT A) (NOT B))
146  * (NOT (OR A B)) => (AND (NOT A) (NOT B))
147  * i.e., swap AND for OR and negate each subclause.
148  *
149  * If the input is already AND/OR flat and has no NOT
150  * directly above AND or OR, this transformation preserves
151  * those properties. For example, if no direct child of
152  * the given AND clause is an AND or a NOT-above-OR, then
153  * the recursive calls of negate_clause() can't return any
154  * OR clauses. So we needn't call pull_ors() before
155  * building a new OR clause. Similarly for the OR case.
156  *--------------------
157  */
158  case AND_EXPR:
159  {
160  List *nargs = NIL;
161  ListCell *lc;
162 
163  foreach(lc, expr->args)
164  {
165  nargs = lappend(nargs,
166  negate_clause(lfirst(lc)));
167  }
168  return (Node *) make_orclause(nargs);
169  }
170  break;
171  case OR_EXPR:
172  {
173  List *nargs = NIL;
174  ListCell *lc;
175 
176  foreach(lc, expr->args)
177  {
178  nargs = lappend(nargs,
179  negate_clause(lfirst(lc)));
180  }
181  return (Node *) make_andclause(nargs);
182  }
183  break;
184  case NOT_EXPR:
185 
186  /*
187  * NOT underneath NOT: they cancel. We assume the
188  * input is already simplified, so no need to recurse.
189  */
190  return (Node *) linitial(expr->args);
191  default:
192  elog(ERROR, "unrecognized boolop: %d",
193  (int) expr->boolop);
194  break;
195  }
196  }
197  break;
198  case T_NullTest:
199  {
200  NullTest *expr = (NullTest *) node;
201 
202  /*
203  * In the rowtype case, the two flavors of NullTest are *not*
204  * logical inverses, so we can't simplify. But it does work
205  * for scalar datatypes.
206  */
207  if (!expr->argisrow)
208  {
209  NullTest *newexpr = makeNode(NullTest);
210 
211  newexpr->arg = expr->arg;
212  newexpr->nulltesttype = (expr->nulltesttype == IS_NULL ?
213  IS_NOT_NULL : IS_NULL);
214  newexpr->argisrow = expr->argisrow;
215  newexpr->location = expr->location;
216  return (Node *) newexpr;
217  }
218  }
219  break;
220  case T_BooleanTest:
221  {
222  BooleanTest *expr = (BooleanTest *) node;
223  BooleanTest *newexpr = makeNode(BooleanTest);
224 
225  newexpr->arg = expr->arg;
226  switch (expr->booltesttype)
227  {
228  case IS_TRUE:
229  newexpr->booltesttype = IS_NOT_TRUE;
230  break;
231  case IS_NOT_TRUE:
232  newexpr->booltesttype = IS_TRUE;
233  break;
234  case IS_FALSE:
235  newexpr->booltesttype = IS_NOT_FALSE;
236  break;
237  case IS_NOT_FALSE:
238  newexpr->booltesttype = IS_FALSE;
239  break;
240  case IS_UNKNOWN:
241  newexpr->booltesttype = IS_NOT_UNKNOWN;
242  break;
243  case IS_NOT_UNKNOWN:
244  newexpr->booltesttype = IS_UNKNOWN;
245  break;
246  default:
247  elog(ERROR, "unrecognized booltesttype: %d",
248  (int) expr->booltesttype);
249  break;
250  }
251  newexpr->location = expr->location;
252  return (Node *) newexpr;
253  }
254  break;
255  default:
256  /* else fall through */
257  break;
258  }
259 
260  /*
261  * Otherwise we don't know how to simplify this, so just tack on an
262  * explicit NOT node.
263  */
264  return (Node *) make_notclause((Expr *) node);
265 }
Datum constvalue
Definition: primnodes.h:174
#define NIL
Definition: pg_list.h:69
Node * negate_clause(Node *node)
Definition: prepqual.c:73
Definition: nodes.h:508
unsigned int Oid
Definition: postgres_ext.h:31
Oid opresulttype
Definition: primnodes.h:475
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:539
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:354
Expr * arg
Definition: primnodes.h:1156
char * c
int location
Definition: primnodes.h:480
Expr * arg
Definition: primnodes.h:1179
#define DatumGetBool(X)
Definition: postgres.h:401
Oid opcollid
Definition: primnodes.h:477
Definition: nodes.h:140
List * lappend(List *list, void *datum)
Definition: list.c:128
BoolTestType booltesttype
Definition: primnodes.h:1180
Expr * make_notclause(Expr *notclause)
Definition: clauses.c:248
Oid opfuncid
Definition: primnodes.h:474
NullTestType nulltesttype
Definition: primnodes.h:1157
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
int location
Definition: primnodes.h:1159
Oid inputcollid
Definition: primnodes.h:478
List * args
Definition: primnodes.h:540
#define nodeTag(nodeptr)
Definition: nodes.h:513
bool argisrow
Definition: primnodes.h:1158
Expr * make_andclause(List *andclauses)
Definition: clauses.c:326
Oid opno
Definition: primnodes.h:473
#define elog
Definition: elog.h:219
Oid get_negator(Oid opno)
Definition: lsyscache.c:1305
List * args
Definition: primnodes.h:479
Definition: pg_list.h:45
Expr * make_orclause(List *orclauses)
Definition: clauses.c:292
bool constisnull
Definition: primnodes.h:175
bool opretset
Definition: primnodes.h:476
RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 129 of file prepunion.c.

References add_path(), Assert, SetOperationStmt::colCollations, SetOperationStmt::colTypes, create_upper_paths_hook, Query::distinctClause, fetch_upper_rel(), FromExpr::fromlist, generate_recursion_path(), Query::groupClause, PlannerInfo::hasRecursion, Query::havingQual, IsA, Query::jointree, SetOperationStmt::larg, NIL, NULL, parse(), PlannerInfo::parse, PlannerInfo::processed_tlist, FromExpr::quals, recurse_set_operations(), set_cheapest(), Query::setOperations, setup_simple_rel_arrays(), PlannerInfo::simple_rte_array, RangeTblEntry::subquery, UPPERREL_SETOP, and Query::windowClause.

Referenced by grouping_planner().

130 {
131  Query *parse = root->parse;
132  SetOperationStmt *topop = (SetOperationStmt *) parse->setOperations;
133  Node *node;
134  RangeTblEntry *leftmostRTE;
135  Query *leftmostQuery;
136  RelOptInfo *setop_rel;
137  Path *path;
138  List *top_tlist;
139 
140  Assert(topop && IsA(topop, SetOperationStmt));
141 
142  /* check for unsupported stuff */
143  Assert(parse->jointree->fromlist == NIL);
144  Assert(parse->jointree->quals == NULL);
145  Assert(parse->groupClause == NIL);
146  Assert(parse->havingQual == NULL);
147  Assert(parse->windowClause == NIL);
148  Assert(parse->distinctClause == NIL);
149 
150  /*
151  * We'll need to build RelOptInfos for each of the leaf subqueries, which
152  * are RTE_SUBQUERY rangetable entries in this Query. Prepare the index
153  * arrays for that.
154  */
156 
157  /*
158  * Find the leftmost component Query. We need to use its column names for
159  * all generated tlists (else SELECT INTO won't work right).
160  */
161  node = topop->larg;
162  while (node && IsA(node, SetOperationStmt))
163  node = ((SetOperationStmt *) node)->larg;
164  Assert(node && IsA(node, RangeTblRef));
165  leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
166  leftmostQuery = leftmostRTE->subquery;
167  Assert(leftmostQuery != NULL);
168 
169  /*
170  * We return our results in the (SETOP, NULL) upperrel. For the moment,
171  * this is also the parent rel of all Paths in the setop tree; we may well
172  * change that in future.
173  */
174  setop_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
175 
176  /*
177  * We don't currently worry about setting setop_rel's consider_parallel
178  * flag, nor about allowing FDWs to contribute paths to it.
179  */
180 
181  /*
182  * If the topmost node is a recursive union, it needs special processing.
183  */
184  if (root->hasRecursion)
185  {
186  path = generate_recursion_path(topop, root,
187  leftmostQuery->targetList,
188  &top_tlist);
189  }
190  else
191  {
192  /*
193  * Recurse on setOperations tree to generate paths for set ops. The
194  * final output path should have just the column types shown as the
195  * output from the top-level node, plus possibly resjunk working
196  * columns (we can rely on upper-level nodes to deal with that).
197  */
198  path = recurse_set_operations((Node *) topop, root,
199  topop->colTypes, topop->colCollations,
200  true, -1,
201  leftmostQuery->targetList,
202  &top_tlist,
203  NULL);
204  }
205 
206  /* Must return the built tlist into root->processed_tlist. */
207  root->processed_tlist = top_tlist;
208 
209  /* Add only the final path to the SETOP upperrel. */
210  add_path(setop_rel, path);
211 
212  /* Let extensions possibly add some more paths */
214  (*create_upper_paths_hook) (root, UPPERREL_SETOP,
215  NULL, setop_rel);
216 
217  /* Select cheapest path */
218  set_cheapest(setop_rel);
219 
220  return setop_rel;
221 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
FromExpr * jointree
Definition: parsenodes.h:129
static Path * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
Definition: prepunion.c:417
Definition: nodes.h:508
List * fromlist
Definition: primnodes.h:1433
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:68
bool hasRecursion
Definition: relation.h:300
Node * quals
Definition: primnodes.h:1434
List * windowClause
Definition: parsenodes.h:143
List * distinctClause
Definition: parsenodes.h:145
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:870
static Path * 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:248
RangeTblEntry ** simple_rte_array
Definition: relation.h:185
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
List * colCollations
Definition: parsenodes.h:1494
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:59
Node * setOperations
Definition: parsenodes.h:154
Query * subquery
Definition: parsenodes.h:900
List * groupClause
Definition: parsenodes.h:137
Node * havingQual
Definition: parsenodes.h:141
List * processed_tlist
Definition: relation.h:276
Definition: pg_list.h:45
Definition: relation.h:888
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
List* preprocess_onconflict_targetlist ( List tlist,
int  result_relation,
List range_table 
)

Definition at line 206 of file preptlist.c.

References CMD_UPDATE, and expand_targetlist().

Referenced by grouping_planner().

207 {
208  return expand_targetlist(tlist, CMD_UPDATE, result_relation, range_table);
209 }
static List * expand_targetlist(List *tlist, int command_type, Index result_relation, List *range_table)
Definition: preptlist.c:225
List* preprocess_targetlist ( PlannerInfo root,
List tlist 
)

Definition at line 64 of file preptlist.c.

References PlanRowMark::allMarkTypes, CMD_INSERT, CMD_UPDATE, Query::commandType, elog, ERROR, expand_targetlist(), InvalidOid, IsA, PlanRowMark::isParent, lappend(), lfirst, list_free(), list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NULL, OIDOID, parse(), PlannerInfo::parse, PlanRowMark::prti, pstrdup(), pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, RangeTblEntry::relid, Query::resultRelation, Query::returningList, ROW_MARK_COPY, PlanRowMark::rowmarkId, PlannerInfo::rowMarks, rt_fetch, Query::rtable, PlanRowMark::rti, SelfItemPointerAttributeNumber, snprintf(), RangeTblEntry::subquery, TableOidAttributeNumber, TIDOID, tlist_member(), and Var::varno.

Referenced by grouping_planner().

65 {
66  Query *parse = root->parse;
67  int result_relation = parse->resultRelation;
68  List *range_table = parse->rtable;
69  CmdType command_type = parse->commandType;
70  ListCell *lc;
71 
72  /*
73  * Sanity check: if there is a result relation, it'd better be a real
74  * relation not a subquery. Else parser or rewriter messed up.
75  */
76  if (result_relation)
77  {
78  RangeTblEntry *rte = rt_fetch(result_relation, range_table);
79 
80  if (rte->subquery != NULL || rte->relid == InvalidOid)
81  elog(ERROR, "subquery cannot be result relation");
82  }
83 
84  /*
85  * for heap_form_tuple to work, the targetlist must match the exact order
86  * of the attributes. We also need to fill in any missing attributes. -ay
87  * 10/94
88  */
89  if (command_type == CMD_INSERT || command_type == CMD_UPDATE)
90  tlist = expand_targetlist(tlist, command_type,
91  result_relation, range_table);
92 
93  /*
94  * Add necessary junk columns for rowmarked rels. These values are needed
95  * for locking of rels selected FOR UPDATE/SHARE, and to do EvalPlanQual
96  * rechecking. See comments for PlanRowMark in plannodes.h.
97  */
98  foreach(lc, root->rowMarks)
99  {
100  PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
101  Var *var;
102  char resname[32];
103  TargetEntry *tle;
104 
105  /* child rels use the same junk attrs as their parents */
106  if (rc->rti != rc->prti)
107  continue;
108 
109  if (rc->allMarkTypes & ~(1 << ROW_MARK_COPY))
110  {
111  /* Need to fetch TID */
112  var = makeVar(rc->rti,
114  TIDOID,
115  -1,
116  InvalidOid,
117  0);
118  snprintf(resname, sizeof(resname), "ctid%u", rc->rowmarkId);
119  tle = makeTargetEntry((Expr *) var,
120  list_length(tlist) + 1,
121  pstrdup(resname),
122  true);
123  tlist = lappend(tlist, tle);
124  }
125  if (rc->allMarkTypes & (1 << ROW_MARK_COPY))
126  {
127  /* Need the whole row as a junk var */
128  var = makeWholeRowVar(rt_fetch(rc->rti, range_table),
129  rc->rti,
130  0,
131  false);
132  snprintf(resname, sizeof(resname), "wholerow%u", rc->rowmarkId);
133  tle = makeTargetEntry((Expr *) var,
134  list_length(tlist) + 1,
135  pstrdup(resname),
136  true);
137  tlist = lappend(tlist, tle);
138  }
139 
140  /* If parent of inheritance tree, always fetch the tableoid too. */
141  if (rc->isParent)
142  {
143  var = makeVar(rc->rti,
145  OIDOID,
146  -1,
147  InvalidOid,
148  0);
149  snprintf(resname, sizeof(resname), "tableoid%u", rc->rowmarkId);
150  tle = makeTargetEntry((Expr *) var,
151  list_length(tlist) + 1,
152  pstrdup(resname),
153  true);
154  tlist = lappend(tlist, tle);
155  }
156  }
157 
158  /*
159  * If the query has a RETURNING list, add resjunk entries for any Vars
160  * used in RETURNING that belong to other relations. We need to do this
161  * to make these Vars available for the RETURNING calculation. Vars that
162  * belong to the result rel don't need to be added, because they will be
163  * made to refer to the actual heap tuple.
164  */
165  if (parse->returningList && list_length(parse->rtable) > 1)
166  {
167  List *vars;
168  ListCell *l;
169 
170  vars = pull_var_clause((Node *) parse->returningList,
174  foreach(l, vars)
175  {
176  Var *var = (Var *) lfirst(l);
177  TargetEntry *tle;
178 
179  if (IsA(var, Var) &&
180  var->varno == result_relation)
181  continue; /* don't need it */
182 
183  if (tlist_member((Node *) var, tlist))
184  continue; /* already got it */
185 
186  tle = makeTargetEntry((Expr *) var,
187  list_length(tlist) + 1,
188  NULL,
189  true);
190 
191  tlist = lappend(tlist, tle);
192  }
193  list_free(vars);
194  }
195 
196  return tlist;
197 }
List * rowMarks
Definition: relation.h:251
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
static List * expand_targetlist(List *tlist, int command_type, Index result_relation, List *range_table)
Definition: preptlist.c:225
#define OIDOID
Definition: pg_type.h:328
char * pstrdup(const char *in)
Definition: mcxt.c:1165
int resultRelation
Definition: parsenodes.h:113
Definition: nodes.h:508
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:132
Index prti
Definition: plannodes.h:941
int snprintf(char *str, size_t count, const char *fmt,...) pg_attribute_printf(3
List * pull_var_clause(Node *node, int flags)
Definition: var.c:535
Definition: primnodes.h:141
Index rowmarkId
Definition: plannodes.h:942
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
TargetEntry * tlist_member(Node *node, List *targetlist)
Definition: tlist.c:54
#define TIDOID
Definition: pg_type.h:332
List * rtable
Definition: parsenodes.h:128
#define ERROR
Definition: elog.h:43
#define TableOidAttributeNumber
Definition: sysattr.h:27
int allMarkTypes
Definition: plannodes.h:944
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
List * returningList
Definition: parsenodes.h:135
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
List * lappend(List *list, void *datum)
Definition: list.c:128
Index varno
Definition: primnodes.h:144
#define InvalidOid
Definition: postgres_ext.h:36
CmdType commandType
Definition: parsenodes.h:103
Index rti
Definition: plannodes.h:940
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
Query * subquery
Definition: parsenodes.h:900
void list_free(List *list)
Definition: list.c:1133
bool isParent
Definition: plannodes.h:947
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define elog
Definition: elog.h:219
Definition: regcomp.c:226
Definition: pg_list.h:45
CmdType
Definition: nodes.h:641
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:651
void pull_up_sublinks ( PlannerInfo root)

Definition at line 150 of file prepjointree.c.

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

151 {
152  Node *jtnode;
153  Relids relids;
154 
155  /* Begin recursion through the jointree */
156  jtnode = pull_up_sublinks_jointree_recurse(root,
157  (Node *) root->parse->jointree,
158  &relids);
159 
160  /*
161  * root->parse->jointree must always be a FromExpr, so insert a dummy one
162  * if we got a bare RangeTblRef or JoinExpr out of the recursion.
163  */
164  if (IsA(jtnode, FromExpr))
165  root->parse->jointree = (FromExpr *) jtnode;
166  else
167  root->parse->jointree = makeFromExpr(list_make1(jtnode), NULL);
168 }
FromExpr * makeFromExpr(List *fromlist, Node *quals)
Definition: makefuncs.c:282
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
FromExpr * jointree
Definition: parsenodes.h:129
Definition: nodes.h:508
#define list_make1(x1)
Definition: pg_list.h:133
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:177
#define NULL
Definition: c.h:226
void pull_up_subqueries ( PlannerInfo root)

Definition at line 607 of file prepjointree.c.

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

608 {
609  /* Top level of jointree must always be a FromExpr */
610  Assert(IsA(root->parse->jointree, FromExpr));
611  /* Reset flag saying we need a deletion cleanup pass */
612  root->hasDeletedRTEs = false;
613  /* Recursion starts with no containing join nor appendrel */
614  root->parse->jointree = (FromExpr *)
616  NULL, NULL, NULL, false);
617  /* Apply cleanup phase if necessary */
618  if (root->hasDeletedRTEs)
619  root->parse->jointree = (FromExpr *)
621  Assert(IsA(root->parse->jointree, FromExpr));
622 }
static Node * pull_up_subqueries_recurse(PlannerInfo *root, Node *jtnode, JoinExpr *lowest_outer_join, JoinExpr *lowest_nulling_outer_join, AppendRelInfo *containing_appendrel, bool deletion_ok)
Definition: prepjointree.c:673
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Query * parse
Definition: relation.h:152
FromExpr * jointree
Definition: parsenodes.h:129
Definition: nodes.h:508
bool hasDeletedRTEs
Definition: relation.h:296
static Node * pull_up_subqueries_cleanup(Node *jtnode)
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
void reduce_outer_joins ( PlannerInfo root)

Definition at line 2432 of file prepjointree.c.

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

Referenced by subquery_planner().

2433 {
2435 
2436  /*
2437  * To avoid doing strictness checks on more quals than necessary, we want
2438  * to stop descending the jointree as soon as there are no outer joins
2439  * below our current point. This consideration forces a two-pass process.
2440  * The first pass gathers information about which base rels appear below
2441  * each side of each join clause, and about whether there are outer
2442  * join(s) below each side of each join clause. The second pass examines
2443  * qual clauses and changes join types as it descends the tree.
2444  */
2445  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2446 
2447  /* planner.c shouldn't have called me if no outer joins */
2448  if (state == NULL || !state->contains_outer)
2449  elog(ERROR, "so where are the outer joins?");
2450 
2452  state, root, NULL, NIL, NIL);
2453 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:152
FromExpr * jointree
Definition: parsenodes.h:129
Definition: nodes.h:508
#define ERROR
Definition: elog.h:43
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
#define NULL
Definition: c.h:226
Definition: regguts.h:298
#define elog
Definition: elog.h:219
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)