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 1783 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(), result, 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().

1784 {
1785  Node *result;
1787 
1788  context.root = root;
1789  context.appinfo = appinfo;
1790 
1791  /*
1792  * Must be prepared to start with a Query or a bare expression tree.
1793  */
1794  if (node && IsA(node, Query))
1795  {
1796  Query *newnode;
1797 
1798  newnode = query_tree_mutator((Query *) node,
1800  (void *) &context,
1802  if (newnode->resultRelation == appinfo->parent_relid)
1803  {
1804  newnode->resultRelation = appinfo->child_relid;
1805  /* Fix tlist resnos too, if it's inherited UPDATE */
1806  if (newnode->commandType == CMD_UPDATE)
1807  newnode->targetList =
1809  appinfo);
1810  }
1811  result = (Node *) newnode;
1812  }
1813  else
1814  result = adjust_appendrel_attrs_mutator(node, &context);
1815 
1816  return result;
1817 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
int resultRelation
Definition: parsenodes.h:120
Definition: nodes.h:509
return result
Definition: formatting.c:1633
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: prepunion.c:2062
List * targetList
Definition: parsenodes.h:138
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
CmdType commandType
Definition: parsenodes.h:110
static Node * adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context)
Definition: prepunion.c:1820
Index child_relid
Definition: relation.h:1976
Index parent_relid
Definition: relation.h:1975
Query * query_tree_mutator(Query *query, Node *(*mutator)(), void *context, int flags)
Definition: nodeFuncs.c:3068
Node* adjust_appendrel_attrs_multilevel ( PlannerInfo root,
Node node,
RelOptInfo child_rel 
)

Definition at line 2150 of file prepunion.c.

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

Referenced by adjust_appendrel_attrs_multilevel(), and generate_join_implied_equalities_broken().

2152 {
2153  AppendRelInfo *appinfo = find_childrel_appendrelinfo(root, child_rel);
2154  RelOptInfo *parent_rel = find_base_rel(root, appinfo->parent_relid);
2155 
2156  /* If parent is also a child, first recurse to apply its translations */
2157  if (IS_OTHER_REL(parent_rel))
2158  node = adjust_appendrel_attrs_multilevel(root, node, parent_rel);
2159  else
2160  Assert(parent_rel->reloptkind == RELOPT_BASEREL);
2161  /* Now translate for this child */
2162  return adjust_appendrel_attrs(root, node, appinfo);
2163 }
RelOptKind reloptkind
Definition: relation.h:522
#define IS_OTHER_REL(rel)
Definition: relation.h:516
AppendRelInfo * find_childrel_appendrelinfo(PlannerInfo *root, RelOptInfo *rel)
Definition: relnode.c:970
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, AppendRelInfo *appinfo)
Definition: prepunion.c:1783
#define Assert(condition)
Definition: c.h:675
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *child_rel)
Definition: prepunion.c:2150
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:243
Index parent_relid
Definition: relation.h:1975
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:229
static Expr * find_duplicate_ors(Expr *qual)
Definition: prepqual.c:407
void expand_inherited_tables ( PlannerInfo root)

Definition at line 1328 of file prepunion.c.

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

Referenced by subquery_planner().

1329 {
1330  Index nrtes;
1331  Index rti;
1332  ListCell *rl;
1333 
1334  /*
1335  * expand_inherited_rtentry may add RTEs to parse->rtable; there is no
1336  * need to scan them since they can't have inh=true. So just scan as far
1337  * as the original end of the rtable list.
1338  */
1339  nrtes = list_length(root->parse->rtable);
1340  rl = list_head(root->parse->rtable);
1341  for (rti = 1; rti <= nrtes; rti++)
1342  {
1343  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1344 
1345  expand_inherited_rtentry(root, rte, rti);
1346  rl = lnext(rl);
1347  }
1348 }
Query * parse
Definition: relation.h:155
List * rtable
Definition: parsenodes.h:135
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:1367
unsigned int Index
Definition: c.h:365
#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 2321 of file prepjointree.c.

References Assert, castNode, 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().

2322 {
2323  Query *parse = root->parse;
2324  SetOperationStmt *topop;
2325  Node *leftmostjtnode;
2326  int leftmostRTI;
2327  RangeTblEntry *leftmostRTE;
2328  int childRTI;
2329  RangeTblEntry *childRTE;
2330  RangeTblRef *rtr;
2331 
2332  /* Shouldn't be called unless query has setops */
2333  topop = castNode(SetOperationStmt, parse->setOperations);
2334  Assert(topop);
2335 
2336  /* Can't optimize away a recursive UNION */
2337  if (root->hasRecursion)
2338  return;
2339 
2340  /*
2341  * Recursively check the tree of set operations. If not all UNION ALL
2342  * with identical column types, punt.
2343  */
2344  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2345  return;
2346 
2347  /*
2348  * Locate the leftmost leaf query in the setops tree. The upper query's
2349  * Vars all refer to this RTE (see transformSetOperationStmt).
2350  */
2351  leftmostjtnode = topop->larg;
2352  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2353  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2354  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2355  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2356  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2357  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2358 
2359  /*
2360  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2361  * will represent the leftmost leaf query in its capacity as a member of
2362  * the appendrel. The original will represent the appendrel as a whole.
2363  * (We must do things this way because the upper query's Vars have to be
2364  * seen as referring to the whole appendrel.)
2365  */
2366  childRTE = copyObject(leftmostRTE);
2367  parse->rtable = lappend(parse->rtable, childRTE);
2368  childRTI = list_length(parse->rtable);
2369 
2370  /* Modify the setops tree to reference the child copy */
2371  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2372 
2373  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2374  leftmostRTE->inh = true;
2375 
2376  /*
2377  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2378  * Query of a setops tree should have had an empty FromClause initially.
2379  */
2380  rtr = makeNode(RangeTblRef);
2381  rtr->rtindex = leftmostRTI;
2382  Assert(parse->jointree->fromlist == NIL);
2383  parse->jointree->fromlist = list_make1(rtr);
2384 
2385  /*
2386  * Now pretend the query has no setops. We must do this before trying to
2387  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2388  */
2389  parse->setOperations = NULL;
2390 
2391  /*
2392  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2393  * leaf queries of the UNION ALL. (We must do that now because they
2394  * weren't previously referenced by the jointree, and so were missed by
2395  * the main invocation of pull_up_subqueries.)
2396  */
2397  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2398 }
#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:560
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
Definition: nodes.h:509
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1471
bool hasRecursion
Definition: relation.h:305
#define list_make1(x1)
Definition: pg_list.h:139
List * rtable
Definition: parsenodes.h:135
#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:557
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:936
Node * setOperations
Definition: parsenodes.h:163
#define copyObject(obj)
Definition: nodes.h:622
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649
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 }
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Relids get_relids_for_join ( PlannerInfo root,
int  joinrelid 
)

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

2988 {
2989  Node *jtnode;
2990 
2991  jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
2992  joinrelid);
2993  if (!jtnode)
2994  elog(ERROR, "could not find join node %d", joinrelid);
2995  return get_relids_in_jointree(jtnode, false);
2996 }
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:509
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 2943 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, result, 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().

2944 {
2945  Relids result = NULL;
2946 
2947  if (jtnode == NULL)
2948  return result;
2949  if (IsA(jtnode, RangeTblRef))
2950  {
2951  int varno = ((RangeTblRef *) jtnode)->rtindex;
2952 
2953  result = bms_make_singleton(varno);
2954  }
2955  else if (IsA(jtnode, FromExpr))
2956  {
2957  FromExpr *f = (FromExpr *) jtnode;
2958  ListCell *l;
2959 
2960  foreach(l, f->fromlist)
2961  {
2962  result = bms_join(result,
2964  include_joins));
2965  }
2966  }
2967  else if (IsA(jtnode, JoinExpr))
2968  {
2969  JoinExpr *j = (JoinExpr *) jtnode;
2970 
2971  result = get_relids_in_jointree(j->larg, include_joins);
2972  result = bms_join(result,
2973  get_relids_in_jointree(j->rarg, include_joins));
2974  if (include_joins && j->rtindex)
2975  result = bms_add_member(result, j->rtindex);
2976  }
2977  else
2978  elog(ERROR, "unrecognized node type: %d",
2979  (int) nodeTag(jtnode));
2980  return result;
2981 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
return result
Definition: formatting.c:1633
List * fromlist
Definition: primnodes.h:1471
Node * larg
Definition: primnodes.h:1451
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:838
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:179
Node * rarg
Definition: primnodes.h:1452
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
#define nodeTag(nodeptr)
Definition: nodes.h:514
#define elog
Definition: elog.h:219
int rtindex
Definition: primnodes.h:1456
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:155
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4766
List * rtable
Definition: parsenodes.h:135
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:990
RTEKind rtekind
Definition: parsenodes.h:936
Query * subquery
Definition: parsenodes.h:959
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:196
#define NIL
Definition: pg_list.h:69
Node * negate_clause(Node *node)
Definition: prepqual.c:73
Definition: nodes.h:509
unsigned int Oid
Definition: postgres_ext.h:31
Oid opresulttype
Definition: primnodes.h:498
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
BoolExprType boolop
Definition: primnodes.h:562
Node * makeBoolConst(bool value, bool isnull)
Definition: makefuncs.c:354
Expr * arg
Definition: primnodes.h:1180
char * c
int location
Definition: primnodes.h:503
Expr * arg
Definition: primnodes.h:1203
#define DatumGetBool(X)
Definition: postgres.h:399
Oid opcollid
Definition: primnodes.h:500
Definition: nodes.h:147
List * lappend(List *list, void *datum)
Definition: list.c:128
BoolTestType booltesttype
Definition: primnodes.h:1204
Expr * make_notclause(Expr *notclause)
Definition: clauses.c:249
Oid opfuncid
Definition: primnodes.h:497
NullTestType nulltesttype
Definition: primnodes.h:1181
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define lfirst(lc)
Definition: pg_list.h:106
int location
Definition: primnodes.h:1183
Oid inputcollid
Definition: primnodes.h:501
List * args
Definition: primnodes.h:563
#define nodeTag(nodeptr)
Definition: nodes.h:514
bool argisrow
Definition: primnodes.h:1182
Expr * make_andclause(List *andclauses)
Definition: clauses.c:327
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
Oid get_negator(Oid opno)
Definition: lsyscache.c:1337
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
Expr * make_orclause(List *orclauses)
Definition: clauses.c:293
bool constisnull
Definition: primnodes.h:197
bool opretset
Definition: primnodes.h:499
RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 129 of file prepunion.c.

References add_path(), Assert, castNode, 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, Query::targetList, UPPERREL_SETOP, and Query::windowClause.

Referenced by grouping_planner().

130 {
131  Query *parse = root->parse;
133  Node *node;
134  RangeTblEntry *leftmostRTE;
135  Query *leftmostQuery;
136  RelOptInfo *setop_rel;
137  Path *path;
138  List *top_tlist;
139 
140  Assert(topop);
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:560
Query * parse
Definition: relation.h:155
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:412
FromExpr * jointree
Definition: parsenodes.h:136
static Path * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
Definition: prepunion.c:427
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
Definition: nodes.h:509
List * fromlist
Definition: primnodes.h:1471
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:69
bool hasRecursion
Definition: relation.h:305
Node * quals
Definition: primnodes.h:1472
List * windowClause
Definition: parsenodes.h:152
List * targetList
Definition: parsenodes.h:138
List * distinctClause
Definition: parsenodes.h:154
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:919
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:188
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:234
List * colCollations
Definition: parsenodes.h:1569
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:62
Node * setOperations
Definition: parsenodes.h:163
Query * subquery
Definition: parsenodes.h:959
List * groupClause
Definition: parsenodes.h:146
Node * havingQual
Definition: parsenodes.h:150
List * processed_tlist
Definition: relation.h:281
Definition: pg_list.h:45
Definition: relation.h:948
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649
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((Expr *) 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:256
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
Query * parse
Definition: relation.h:155
#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:1077
int resultRelation
Definition: parsenodes.h:120
Definition: nodes.h:509
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:132
Index prti
Definition: plannodes.h:1005
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:163
Index rowmarkId
Definition: plannodes.h:1006
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
#define TIDOID
Definition: pg_type.h:332
List * rtable
Definition: parsenodes.h:135
#define ERROR
Definition: elog.h:43
#define TableOidAttributeNumber
Definition: sysattr.h:27
int allMarkTypes
Definition: plannodes.h:1008
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
List * returningList
Definition: parsenodes.h:144
#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:166
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:54
#define InvalidOid
Definition: postgres_ext.h:36
CmdType commandType
Definition: parsenodes.h:110
#define NULL
Definition: c.h:229
#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:959
void list_free(List *list)
Definition: list.c:1133
bool isParent
Definition: plannodes.h:1011
#define SelfItemPointerAttributeNumber
Definition: sysattr.h:21
#define elog
Definition: elog.h:219
Definition: regcomp.c:224
Definition: pg_list.h:45
CmdType
Definition: nodes.h:649
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649
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:560
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:509
#define list_make1(x1)
Definition: pg_list.h:139
static Node * pull_up_sublinks_jointree_recurse(PlannerInfo *root, Node *jtnode, Relids *relids)
Definition: prepjointree.c:177
#define NULL
Definition: c.h:229
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:560
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:509
bool hasDeletedRTEs
Definition: relation.h:301
static Node * pull_up_subqueries_cleanup(Node *jtnode)
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:675
void reduce_outer_joins ( PlannerInfo root)

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

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