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, int nappinfos, AppendRelInfo **appinfos)
 
Nodeadjust_appendrel_attrs_multilevel (PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
 
AppendRelInfo ** find_appinfos_by_relids (PlannerInfo *root, Relids relids, int *nappinfos)
 
SpecialJoinInfobuild_child_join_sjinfo (PlannerInfo *root, SpecialJoinInfo *parent_sjinfo, Relids left_relids, Relids right_relids)
 
Relids adjust_child_relids_multilevel (PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
 

Function Documentation

Node* adjust_appendrel_attrs ( PlannerInfo root,
Node node,
int  nappinfos,
AppendRelInfo **  appinfos 
)

Definition at line 1943 of file prepunion.c.

References adjust_appendrel_attrs_mutator(), adjust_inherited_tlist(), adjust_appendrel_attrs_context::appinfos, Assert, AppendRelInfo::child_relid, CMD_UPDATE, Query::commandType, IsA, adjust_appendrel_attrs_context::nappinfos, 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(), add_placeholders_to_child_joinrel(), adjust_appendrel_attrs_multilevel(), build_child_join_rel(), build_child_join_sjinfo(), inheritance_planner(), set_append_rel_size(), and try_partition_wise_join().

1945 {
1946  Node *result;
1948 
1949  context.root = root;
1950  context.nappinfos = nappinfos;
1951  context.appinfos = appinfos;
1952 
1953  /* If there's nothing to adjust, don't call this function. */
1954  Assert(nappinfos >= 1 && appinfos != NULL);
1955 
1956  /*
1957  * Must be prepared to start with a Query or a bare expression tree.
1958  */
1959  if (node && IsA(node, Query))
1960  {
1961  Query *newnode;
1962  int cnt;
1963 
1964  newnode = query_tree_mutator((Query *) node,
1966  (void *) &context,
1968  for (cnt = 0; cnt < nappinfos; cnt++)
1969  {
1970  AppendRelInfo *appinfo = appinfos[cnt];
1971 
1972  if (newnode->resultRelation == appinfo->parent_relid)
1973  {
1974  newnode->resultRelation = appinfo->child_relid;
1975  /* Fix tlist resnos too, if it's inherited UPDATE */
1976  if (newnode->commandType == CMD_UPDATE)
1977  newnode->targetList =
1979  appinfo);
1980  break;
1981  }
1982  }
1983 
1984  result = (Node *) newnode;
1985  }
1986  else
1987  result = adjust_appendrel_attrs_mutator(node, &context);
1988 
1989  return result;
1990 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
int resultRelation
Definition: parsenodes.h:120
Definition: nodes.h:510
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: prepunion.c:2342
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:1993
#define Assert(condition)
Definition: c.h:681
AppendRelInfo ** appinfos
Definition: prepunion.c:60
Index child_relid
Definition: relation.h:2066
Index parent_relid
Definition: relation.h:2065
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,
Relids  child_relids,
Relids  top_parent_relids 
)

Definition at line 2430 of file prepunion.c.

References adjust_appendrel_attrs(), adjust_appendrel_attrs_multilevel(), Assert, bms_add_member(), bms_equal(), bms_num_members(), find_appinfos_by_relids(), AppendRelInfo::parent_relid, and pfree().

Referenced by adjust_appendrel_attrs_multilevel(), and generate_join_implied_equalities_broken().

2433 {
2434  AppendRelInfo **appinfos;
2435  Bitmapset *parent_relids = NULL;
2436  int nappinfos;
2437  int cnt;
2438 
2439  Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
2440 
2441  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
2442 
2443  /* Construct relids set for the immediate parent of given child. */
2444  for (cnt = 0; cnt < nappinfos; cnt++)
2445  {
2446  AppendRelInfo *appinfo = appinfos[cnt];
2447 
2448  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
2449  }
2450 
2451  /* Recurse if immediate parent is not the top parent. */
2452  if (!bms_equal(parent_relids, top_parent_relids))
2453  node = adjust_appendrel_attrs_multilevel(root, node, parent_relids,
2454  top_parent_relids);
2455 
2456  /* Now translate for this child */
2457  node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
2458 
2459  pfree(appinfos);
2460 
2461  return node;
2462 }
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
Definition: prepunion.c:2430
void pfree(void *pointer)
Definition: mcxt.c:949
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:605
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:1943
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2514
#define Assert(condition)
Definition: c.h:681
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
Index parent_relid
Definition: relation.h:2065
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:131
Relids adjust_child_relids_multilevel ( PlannerInfo root,
Relids  relids,
Relids  child_relids,
Relids  top_parent_relids 
)

Definition at line 2278 of file prepunion.c.

References adjust_child_relids(), adjust_child_relids_multilevel(), bms_add_member(), bms_equal(), bms_free(), bms_overlap(), find_appinfos_by_relids(), AppendRelInfo::parent_relid, and pfree().

Referenced by adjust_child_relids_multilevel(), and reparameterize_path_by_child().

2280 {
2281  AppendRelInfo **appinfos;
2282  int nappinfos;
2283  Relids parent_relids = NULL;
2284  Relids result;
2285  Relids tmp_result = NULL;
2286  int cnt;
2287 
2288  /*
2289  * If the given relids set doesn't contain any of the top parent relids,
2290  * it will remain unchanged.
2291  */
2292  if (!bms_overlap(relids, top_parent_relids))
2293  return relids;
2294 
2295  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
2296 
2297  /* Construct relids set for the immediate parent of the given child. */
2298  for (cnt = 0; cnt < nappinfos; cnt++)
2299  {
2300  AppendRelInfo *appinfo = appinfos[cnt];
2301 
2302  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
2303  }
2304 
2305  /* Recurse if immediate parent is not the top parent. */
2306  if (!bms_equal(parent_relids, top_parent_relids))
2307  {
2308  tmp_result = adjust_child_relids_multilevel(root, relids,
2309  parent_relids,
2310  top_parent_relids);
2311  relids = tmp_result;
2312  }
2313 
2314  result = adjust_child_relids(relids, nappinfos, appinfos);
2315 
2316  /* Free memory consumed by any intermediate result. */
2317  if (tmp_result)
2318  bms_free(tmp_result);
2319  bms_free(parent_relids);
2320  pfree(appinfos);
2321 
2322  return result;
2323 }
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
Definition: prepunion.c:2278
void pfree(void *pointer)
Definition: mcxt.c:949
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2514
void bms_free(Bitmapset *a)
Definition: bitmapset.c:201
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:443
Index parent_relid
Definition: relation.h:2065
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:131
static Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2243
SpecialJoinInfo* build_child_join_sjinfo ( PlannerInfo root,
SpecialJoinInfo parent_sjinfo,
Relids  left_relids,
Relids  right_relids 
)

Definition at line 2470 of file prepunion.c.

References adjust_appendrel_attrs(), adjust_child_relids(), find_appinfos_by_relids(), makeNode, SpecialJoinInfo::min_lefthand, SpecialJoinInfo::min_righthand, pfree(), SpecialJoinInfo::semi_rhs_exprs, SpecialJoinInfo::syn_lefthand, and SpecialJoinInfo::syn_righthand.

Referenced by try_partition_wise_join().

2472 {
2474  AppendRelInfo **left_appinfos;
2475  int left_nappinfos;
2476  AppendRelInfo **right_appinfos;
2477  int right_nappinfos;
2478 
2479  memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo));
2480  left_appinfos = find_appinfos_by_relids(root, left_relids,
2481  &left_nappinfos);
2482  right_appinfos = find_appinfos_by_relids(root, right_relids,
2483  &right_nappinfos);
2484 
2485  sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
2486  left_nappinfos, left_appinfos);
2488  right_nappinfos,
2489  right_appinfos);
2490  sjinfo->syn_lefthand = adjust_child_relids(sjinfo->syn_lefthand,
2491  left_nappinfos, left_appinfos);
2493  right_nappinfos,
2494  right_appinfos);
2495  sjinfo->semi_rhs_exprs = (List *) adjust_appendrel_attrs(root,
2496  (Node *) sjinfo->semi_rhs_exprs,
2497  right_nappinfos,
2498  right_appinfos);
2499 
2500  pfree(left_appinfos);
2501  pfree(right_appinfos);
2502 
2503  return sjinfo;
2504 }
Relids min_righthand
Definition: relation.h:2008
Definition: nodes.h:510
Relids syn_lefthand
Definition: relation.h:2009
Relids syn_righthand
Definition: relation.h:2010
void pfree(void *pointer)
Definition: mcxt.c:949
List * semi_rhs_exprs
Definition: relation.h:2018
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:1943
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2514
#define makeNode(_type_)
Definition: nodes.h:558
Definition: pg_list.h:45
Relids min_lefthand
Definition: relation.h:2007
static Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2243
Expr* canonicalize_qual ( Expr qual)

Definition at line 286 of file prepqual.c.

References find_duplicate_ors().

Referenced by ATExecAttachPartition(), convert_EXISTS_to_ANY(), get_proposed_default_constraint(), get_relation_constraints(), PartConstraintImpliedByRelConstraint(), 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 }
static Expr * find_duplicate_ors(Expr *qual)
Definition: prepqual.c:407
void expand_inherited_tables ( PlannerInfo root)

Definition at line 1342 of file prepunion.c.

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

Referenced by subquery_planner().

1343 {
1344  Index nrtes;
1345  Index rti;
1346  ListCell *rl;
1347 
1348  /*
1349  * expand_inherited_rtentry may add RTEs to parse->rtable. The function is
1350  * expected to recursively handle any RTEs that it creates with inh=true.
1351  * So just scan as far as the original end of the rtable list.
1352  */
1353  nrtes = list_length(root->parse->rtable);
1354  rl = list_head(root->parse->rtable);
1355  for (rti = 1; rti <= nrtes; rti++)
1356  {
1357  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1358 
1359  expand_inherited_rtentry(root, rte, rti);
1360  rl = lnext(rl);
1361  }
1362 }
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:1385
unsigned int Index
Definition: c.h:359
#define lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
AppendRelInfo** find_appinfos_by_relids ( PlannerInfo root,
Relids  relids,
int *  nappinfos 
)

Definition at line 2514 of file prepunion.c.

References PlannerInfo::append_rel_list, bms_is_member(), bms_num_members(), AppendRelInfo::child_relid, elog, ERROR, lfirst, and palloc().

Referenced by add_placeholders_to_child_joinrel(), adjust_appendrel_attrs_multilevel(), adjust_child_relids_multilevel(), build_child_join_rel(), build_child_join_sjinfo(), and try_partition_wise_join().

2515 {
2516  ListCell *lc;
2517  AppendRelInfo **appinfos;
2518  int cnt = 0;
2519 
2520  *nappinfos = bms_num_members(relids);
2521  appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
2522 
2523  foreach(lc, root->append_rel_list)
2524  {
2525  AppendRelInfo *appinfo = lfirst(lc);
2526 
2527  if (bms_is_member(appinfo->child_relid, relids))
2528  {
2529  appinfos[cnt] = appinfo;
2530  cnt++;
2531 
2532  /* Stop when we have gathered all the AppendRelInfos. */
2533  if (cnt == *nappinfos)
2534  return appinfos;
2535  }
2536  }
2537 
2538  /* Should have found the entries ... */
2539  elog(ERROR, "did not find all requested child rels in append_rel_list");
2540  return NULL; /* not reached */
2541 }
#define ERROR
Definition: elog.h:43
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:605
List * append_rel_list
Definition: relation.h:252
#define lfirst(lc)
Definition: pg_list.h:106
void * palloc(Size size)
Definition: mcxt.c:848
#define elog
Definition: elog.h:219
Index child_relid
Definition: relation.h:2066
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420
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, 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:561
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
Definition: nodes.h:510
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1471
bool hasRecursion
Definition: relation.h:308
#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:558
#define Assert(condition)
Definition: c.h:681
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:945
Node * setOperations
Definition: parsenodes.h:163
#define copyObject(obj)
Definition: nodes.h:623
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, 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 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:510
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, 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().

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:561
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 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:515
#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:4806
List * rtable
Definition: parsenodes.h:135
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:999
RTEKind rtekind
Definition: parsenodes.h:945
Query * subquery
Definition: parsenodes.h:968
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, 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:510
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:558
#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:515
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 143 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, 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().

144 {
145  Query *parse = root->parse;
147  Node *node;
148  RangeTblEntry *leftmostRTE;
149  Query *leftmostQuery;
150  RelOptInfo *setop_rel;
151  Path *path;
152  List *top_tlist;
153 
154  Assert(topop);
155 
156  /* check for unsupported stuff */
157  Assert(parse->jointree->fromlist == NIL);
158  Assert(parse->jointree->quals == NULL);
159  Assert(parse->groupClause == NIL);
160  Assert(parse->havingQual == NULL);
161  Assert(parse->windowClause == NIL);
162  Assert(parse->distinctClause == NIL);
163 
164  /*
165  * We'll need to build RelOptInfos for each of the leaf subqueries, which
166  * are RTE_SUBQUERY rangetable entries in this Query. Prepare the index
167  * arrays for that.
168  */
170 
171  /*
172  * Find the leftmost component Query. We need to use its column names for
173  * all generated tlists (else SELECT INTO won't work right).
174  */
175  node = topop->larg;
176  while (node && IsA(node, SetOperationStmt))
177  node = ((SetOperationStmt *) node)->larg;
178  Assert(node && IsA(node, RangeTblRef));
179  leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
180  leftmostQuery = leftmostRTE->subquery;
181  Assert(leftmostQuery != NULL);
182 
183  /*
184  * We return our results in the (SETOP, NULL) upperrel. For the moment,
185  * this is also the parent rel of all Paths in the setop tree; we may well
186  * change that in future.
187  */
188  setop_rel = fetch_upper_rel(root, UPPERREL_SETOP, NULL);
189 
190  /*
191  * We don't currently worry about setting setop_rel's consider_parallel
192  * flag, nor about allowing FDWs to contribute paths to it.
193  */
194 
195  /*
196  * If the topmost node is a recursive union, it needs special processing.
197  */
198  if (root->hasRecursion)
199  {
200  path = generate_recursion_path(topop, root,
201  leftmostQuery->targetList,
202  &top_tlist);
203  }
204  else
205  {
206  /*
207  * Recurse on setOperations tree to generate paths for set ops. The
208  * final output path should have just the column types shown as the
209  * output from the top-level node, plus possibly resjunk working
210  * columns (we can rely on upper-level nodes to deal with that).
211  */
212  path = recurse_set_operations((Node *) topop, root,
213  topop->colTypes, topop->colCollations,
214  true, -1,
215  leftmostQuery->targetList,
216  &top_tlist,
217  NULL);
218  }
219 
220  /* Must return the built tlist into root->processed_tlist. */
221  root->processed_tlist = top_tlist;
222 
223  /* Add only the final path to the SETOP upperrel. */
224  add_path(setop_rel, path);
225 
226  /* Let extensions possibly add some more paths */
228  (*create_upper_paths_hook) (root, UPPERREL_SETOP,
229  NULL, setop_rel);
230 
231  /* Select cheapest path */
232  set_cheapest(setop_rel);
233 
234  return setop_rel;
235 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Query * parse
Definition: relation.h:155
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:420
FromExpr * jointree
Definition: parsenodes.h:136
static Path * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
Definition: prepunion.c:441
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
Definition: nodes.h:510
List * fromlist
Definition: primnodes.h:1471
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:69
bool hasRecursion
Definition: relation.h:308
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:1138
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:262
RangeTblEntry ** simple_rte_array
Definition: relation.h:188
void set_cheapest(RelOptInfo *parent_rel)
Definition: pathnode.c:242
List * colCollations
Definition: parsenodes.h:1583
#define Assert(condition)
Definition: c.h:681
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
Node * setOperations
Definition: parsenodes.h:163
Query * subquery
Definition: parsenodes.h:968
List * groupClause
Definition: parsenodes.h:146
Node * havingQual
Definition: parsenodes.h:150
List * processed_tlist
Definition: relation.h:284
Definition: pg_list.h:45
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(), 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:561
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:1076
int resultRelation
Definition: parsenodes.h:120
Definition: nodes.h:510
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:132
Index prti
Definition: plannodes.h:1014
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:1015
#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:1017
#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 lfirst(lc)
Definition: pg_list.h:106
static int list_length(const List *l)
Definition: pg_list.h:89
Query * subquery
Definition: parsenodes.h:968
void list_free(List *list)
Definition: list.c:1133
bool isParent
Definition: plannodes.h:1020
#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:650
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(), 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:561
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:510
#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
void pull_up_subqueries ( PlannerInfo root)

Definition at line 607 of file prepjointree.c.

References Assert, PlannerInfo::hasDeletedRTEs, IsA, Query::jointree, 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:561
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:510
bool hasDeletedRTEs
Definition: relation.h:304
static Node * pull_up_subqueries_cleanup(Node *jtnode)
#define Assert(condition)
Definition: c.h:681
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, 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:510
#define ERROR
Definition: elog.h:43
static reduce_outer_joins_state * reduce_outer_joins_pass1(Node *jtnode)
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)