PostgreSQL Source Code  git master
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)
 
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

◆ adjust_appendrel_attrs()

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

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

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

◆ adjust_appendrel_attrs_multilevel()

Node* adjust_appendrel_attrs_multilevel ( PlannerInfo root,
Node node,
Relids  child_relids,
Relids  top_parent_relids 
)

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

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

◆ adjust_child_relids_multilevel()

Relids adjust_child_relids_multilevel ( PlannerInfo root,
Relids  relids,
Relids  child_relids,
Relids  top_parent_relids 
)

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

2283 {
2284  AppendRelInfo **appinfos;
2285  int nappinfos;
2286  Relids parent_relids = NULL;
2287  Relids result;
2288  Relids tmp_result = NULL;
2289  int cnt;
2290 
2291  /*
2292  * If the given relids set doesn't contain any of the top parent relids,
2293  * it will remain unchanged.
2294  */
2295  if (!bms_overlap(relids, top_parent_relids))
2296  return relids;
2297 
2298  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
2299 
2300  /* Construct relids set for the immediate parent of the given child. */
2301  for (cnt = 0; cnt < nappinfos; cnt++)
2302  {
2303  AppendRelInfo *appinfo = appinfos[cnt];
2304 
2305  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
2306  }
2307 
2308  /* Recurse if immediate parent is not the top parent. */
2309  if (!bms_equal(parent_relids, top_parent_relids))
2310  {
2311  tmp_result = adjust_child_relids_multilevel(root, relids,
2312  parent_relids,
2313  top_parent_relids);
2314  relids = tmp_result;
2315  }
2316 
2317  result = adjust_child_relids(relids, nappinfos, appinfos);
2318 
2319  /* Free memory consumed by any intermediate result. */
2320  if (tmp_result)
2321  bms_free(tmp_result);
2322  bms_free(parent_relids);
2323  pfree(appinfos);
2324 
2325  return result;
2326 }
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
Definition: prepunion.c:2281
void pfree(void *pointer)
Definition: mcxt.c:949
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2517
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:2071
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:2246

◆ build_child_join_sjinfo()

SpecialJoinInfo* build_child_join_sjinfo ( PlannerInfo root,
SpecialJoinInfo parent_sjinfo,
Relids  left_relids,
Relids  right_relids 
)

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

2475 {
2477  AppendRelInfo **left_appinfos;
2478  int left_nappinfos;
2479  AppendRelInfo **right_appinfos;
2480  int right_nappinfos;
2481 
2482  memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo));
2483  left_appinfos = find_appinfos_by_relids(root, left_relids,
2484  &left_nappinfos);
2485  right_appinfos = find_appinfos_by_relids(root, right_relids,
2486  &right_nappinfos);
2487 
2488  sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
2489  left_nappinfos, left_appinfos);
2491  right_nappinfos,
2492  right_appinfos);
2493  sjinfo->syn_lefthand = adjust_child_relids(sjinfo->syn_lefthand,
2494  left_nappinfos, left_appinfos);
2496  right_nappinfos,
2497  right_appinfos);
2498  sjinfo->semi_rhs_exprs = (List *) adjust_appendrel_attrs(root,
2499  (Node *) sjinfo->semi_rhs_exprs,
2500  right_nappinfos,
2501  right_appinfos);
2502 
2503  pfree(left_appinfos);
2504  pfree(right_appinfos);
2505 
2506  return sjinfo;
2507 }
Relids min_righthand
Definition: relation.h:2014
Definition: nodes.h:512
Relids syn_lefthand
Definition: relation.h:2015
Relids syn_righthand
Definition: relation.h:2016
void pfree(void *pointer)
Definition: mcxt.c:949
List * semi_rhs_exprs
Definition: relation.h:2024
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:1946
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2517
#define makeNode(_type_)
Definition: nodes.h:560
Definition: pg_list.h:45
Relids min_lefthand
Definition: relation.h:2013
static Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2246

◆ canonicalize_qual()

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

◆ expand_inherited_tables()

void expand_inherited_tables ( PlannerInfo root)

Definition at line 1345 of file prepunion.c.

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

Referenced by subquery_planner().

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

◆ find_appinfos_by_relids()

AppendRelInfo** find_appinfos_by_relids ( PlannerInfo root,
Relids  relids,
int *  nappinfos 
)

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

2518 {
2519  ListCell *lc;
2520  AppendRelInfo **appinfos;
2521  int cnt = 0;
2522 
2523  *nappinfos = bms_num_members(relids);
2524  appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
2525 
2526  foreach(lc, root->append_rel_list)
2527  {
2528  AppendRelInfo *appinfo = lfirst(lc);
2529 
2530  if (bms_is_member(appinfo->child_relid, relids))
2531  {
2532  appinfos[cnt] = appinfo;
2533  cnt++;
2534 
2535  /* Stop when we have gathered all the AppendRelInfos. */
2536  if (cnt == *nappinfos)
2537  return appinfos;
2538  }
2539  }
2540 
2541  /* Should have found the entries ... */
2542  elog(ERROR, "did not find all requested child rels in append_rel_list");
2543  return NULL; /* not reached */
2544 }
#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:2072
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:420

◆ flatten_simple_union_all()

void flatten_simple_union_all ( PlannerInfo root)

Definition at line 2321 of file prepjointree.c.

References Assert, castNode, copyObject, FromExpr::fromlist, PlannerInfo::hasRecursion, RangeTblEntry::inh, is_simple_union_all_recurse(), IsA, Query::jointree, lappend(), list_length(), list_make1, makeNode, NIL, parse(), PlannerInfo::parse, pull_up_union_leaf_queries(), rt_fetch, Query::rtable, RTE_SUBQUERY, RangeTblEntry::rtekind, RangeTblRef::rtindex, and Query::setOperations.

Referenced by subquery_planner().

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:563
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
#define castNode(_type_, nodeptr)
Definition: nodes.h:581
Definition: nodes.h:512
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1478
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:560
#define Assert(condition)
Definition: c.h:670
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:951
Node * setOperations
Definition: parsenodes.h:163
#define copyObject(obj)
Definition: nodes.h:625
static struct subre * parse(struct vars *, int, int, struct state *, struct state *)
Definition: regcomp.c:649

◆ get_plan_rowmark()

PlanRowMark* get_plan_rowmark ( List rowmarks,
Index  rtindex 
)

Definition at line 424 of file preptlist.c.

References lfirst, and PlanRowMark::rti.

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

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

◆ get_relids_for_join()

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:512
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

◆ get_relids_in_jointree()

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, JoinExpr::rtindex, and pullup_replace_vars_context::varno.

Referenced by distribute_qual_to_rels(), get_relids_for_join(), get_relids_in_jointree(), is_simple_subquery(), preprocess_rowmarks(), 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:563
List * fromlist
Definition: primnodes.h:1478
Node * larg
Definition: primnodes.h:1458
#define ERROR
Definition: elog.h:43
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
Definition: bitmapset.c:910
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:1459
#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:517
#define elog
Definition: elog.h:219
int rtindex
Definition: primnodes.h:1463

◆ inline_set_returning_functions()

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:4837
List * rtable
Definition: parsenodes.h:135
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:1005
RTEKind rtekind
Definition: parsenodes.h:951
Query * subquery
Definition: parsenodes.h:974

◆ negate_clause()

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:512
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:356
Expr * arg
Definition: primnodes.h:1187
char * c
int location
Definition: primnodes.h:503
Expr * arg
Definition: primnodes.h:1210
#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:1211
Expr * make_notclause(Expr *notclause)
Definition: clauses.c:249
Oid opfuncid
Definition: primnodes.h:497
NullTestType nulltesttype
Definition: primnodes.h:1188
#define InvalidOid
Definition: postgres_ext.h:36
#define makeNode(_type_)
Definition: nodes.h:560
#define lfirst(lc)
Definition: pg_list.h:106
int location
Definition: primnodes.h:1190
Oid inputcollid
Definition: primnodes.h:501
List * args
Definition: primnodes.h:563
#define nodeTag(nodeptr)
Definition: nodes.h:517
bool argisrow
Definition: primnodes.h:1189
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

◆ plan_set_operations()

RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 143 of file prepunion.c.

References add_path(), Assert, castNode, 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:563
Query * parse
Definition: relation.h:155
void add_path(RelOptInfo *parent_rel, Path *new_path)
Definition: pathnode.c:422
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:581
Definition: nodes.h:512
List * fromlist
Definition: primnodes.h:1478
create_upper_paths_hook_type create_upper_paths_hook
Definition: planner.c:70
bool hasRecursion
Definition: relation.h:308
Node * quals
Definition: primnodes.h:1479
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:1137
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:244
#define Assert(condition)
Definition: c.h:670
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
Node * setOperations
Definition: parsenodes.h:163
Query * subquery
Definition: parsenodes.h:974
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

◆ preprocess_targetlist()

List* preprocess_targetlist ( PlannerInfo root)

Definition at line 70 of file preptlist.c.

References PlanRowMark::allMarkTypes, Assert, CMD_DELETE, CMD_INSERT, CMD_SELECT, CMD_UPDATE, Query::commandType, elog, ERROR, expand_targetlist(), heap_close, heap_open(), InvalidOid, IsA, PlanRowMark::isParent, lappend(), lfirst, list_free(), list_length(), makeTargetEntry(), makeVar(), makeWholeRowVar(), NoLock, OIDOID, Query::onConflict, OnConflictExpr::onConflictSet, parse(), PlannerInfo::parse, PlanRowMark::prti, pstrdup(), pull_var_clause(), PVC_INCLUDE_PLACEHOLDERS, PVC_RECURSE_AGGREGATES, PVC_RECURSE_WINDOWFUNCS, RangeTblEntry::relid, Query::resultRelation, Query::returningList, rewriteTargetListUD(), ROW_MARK_COPY, PlanRowMark::rowmarkId, PlannerInfo::rowMarks, rt_fetch, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, PlanRowMark::rti, SelfItemPointerAttributeNumber, snprintf(), TableOidAttributeNumber, Query::targetList, TIDOID, tlist_member(), and Var::varno.

Referenced by grouping_planner().

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

◆ pull_up_sublinks()

void pull_up_sublinks ( PlannerInfo root)

Definition at line 150 of file prepjointree.c.

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

Referenced by pull_up_simple_subquery(), and subquery_planner().

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:284
#define IsA(nodeptr, _type_)
Definition: nodes.h:563
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:512
#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

◆ pull_up_subqueries()

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:563
Query * parse
Definition: relation.h:155
FromExpr * jointree
Definition: parsenodes.h:136
Definition: nodes.h:512
bool hasDeletedRTEs
Definition: relation.h:304
static Node * pull_up_subqueries_cleanup(Node *jtnode)
#define Assert(condition)
Definition: c.h:670

◆ reduce_outer_joins()

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:512
#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)