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, bool is_check)
 
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 2047 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(), apply_scanjoin_target_to_paths(), build_child_join_rel(), build_child_join_sjinfo(), create_partitionwise_grouping_paths(), inheritance_planner(), set_append_rel_size(), and try_partitionwise_join().

2049 {
2050  Node *result;
2052 
2053  context.root = root;
2054  context.nappinfos = nappinfos;
2055  context.appinfos = appinfos;
2056 
2057  /* If there's nothing to adjust, don't call this function. */
2058  Assert(nappinfos >= 1 && appinfos != NULL);
2059 
2060  /*
2061  * Must be prepared to start with a Query or a bare expression tree.
2062  */
2063  if (node && IsA(node, Query))
2064  {
2065  Query *newnode;
2066  int cnt;
2067 
2068  newnode = query_tree_mutator((Query *) node,
2070  (void *) &context,
2072  for (cnt = 0; cnt < nappinfos; cnt++)
2073  {
2074  AppendRelInfo *appinfo = appinfos[cnt];
2075 
2076  if (newnode->resultRelation == appinfo->parent_relid)
2077  {
2078  newnode->resultRelation = appinfo->child_relid;
2079  /* Fix tlist resnos too, if it's inherited UPDATE */
2080  if (newnode->commandType == CMD_UPDATE)
2081  newnode->targetList =
2083  appinfo);
2084  break;
2085  }
2086  }
2087 
2088  result = (Node *) newnode;
2089  }
2090  else
2091  result = adjust_appendrel_attrs_mutator(node, &context);
2092 
2093  return result;
2094 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
int resultRelation
Definition: parsenodes.h:122
Definition: nodes.h:516
static List * adjust_inherited_tlist(List *tlist, AppendRelInfo *context)
Definition: prepunion.c:2446
List * targetList
Definition: parsenodes.h:140
#define QTW_IGNORE_RC_SUBQUERIES
Definition: nodeFuncs.h:22
CmdType commandType
Definition: parsenodes.h:112
static Node * adjust_appendrel_attrs_mutator(Node *node, adjust_appendrel_attrs_context *context)
Definition: prepunion.c:2097
#define Assert(condition)
Definition: c.h:699
AppendRelInfo ** appinfos
Definition: prepunion.c:60
Index child_relid
Definition: relation.h:2125
Index parent_relid
Definition: relation.h:2124
Query * query_tree_mutator(Query *query, Node *(*mutator)(), void *context, int flags)
Definition: nodeFuncs.c:3093

◆ adjust_appendrel_attrs_multilevel()

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

Definition at line 2534 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(), generate_join_implied_equalities_broken(), and make_partition_pruneinfo().

2537 {
2538  AppendRelInfo **appinfos;
2539  Bitmapset *parent_relids = NULL;
2540  int nappinfos;
2541  int cnt;
2542 
2543  Assert(bms_num_members(child_relids) == bms_num_members(top_parent_relids));
2544 
2545  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
2546 
2547  /* Construct relids set for the immediate parent of given child. */
2548  for (cnt = 0; cnt < nappinfos; cnt++)
2549  {
2550  AppendRelInfo *appinfo = appinfos[cnt];
2551 
2552  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
2553  }
2554 
2555  /* Recurse if immediate parent is not the top parent. */
2556  if (!bms_equal(parent_relids, top_parent_relids))
2557  node = adjust_appendrel_attrs_multilevel(root, node, parent_relids,
2558  top_parent_relids);
2559 
2560  /* Now translate for this child */
2561  node = adjust_appendrel_attrs(root, node, nappinfos, appinfos);
2562 
2563  pfree(appinfos);
2564 
2565  return node;
2566 }
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, Relids child_relids, Relids top_parent_relids)
Definition: prepunion.c:2534
void pfree(void *pointer)
Definition: mcxt.c:1031
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2047
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2618
#define Assert(condition)
Definition: c.h:699
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
Index parent_relid
Definition: relation.h:2124
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153

◆ adjust_child_relids_multilevel()

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

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

2384 {
2385  AppendRelInfo **appinfos;
2386  int nappinfos;
2387  Relids parent_relids = NULL;
2388  Relids result;
2389  Relids tmp_result = NULL;
2390  int cnt;
2391 
2392  /*
2393  * If the given relids set doesn't contain any of the top parent relids,
2394  * it will remain unchanged.
2395  */
2396  if (!bms_overlap(relids, top_parent_relids))
2397  return relids;
2398 
2399  appinfos = find_appinfos_by_relids(root, child_relids, &nappinfos);
2400 
2401  /* Construct relids set for the immediate parent of the given child. */
2402  for (cnt = 0; cnt < nappinfos; cnt++)
2403  {
2404  AppendRelInfo *appinfo = appinfos[cnt];
2405 
2406  parent_relids = bms_add_member(parent_relids, appinfo->parent_relid);
2407  }
2408 
2409  /* Recurse if immediate parent is not the top parent. */
2410  if (!bms_equal(parent_relids, top_parent_relids))
2411  {
2412  tmp_result = adjust_child_relids_multilevel(root, relids,
2413  parent_relids,
2414  top_parent_relids);
2415  relids = tmp_result;
2416  }
2417 
2418  result = adjust_child_relids(relids, nappinfos, appinfos);
2419 
2420  /* Free memory consumed by any intermediate result. */
2421  if (tmp_result)
2422  bms_free(tmp_result);
2423  bms_free(parent_relids);
2424  pfree(appinfos);
2425 
2426  return result;
2427 }
Relids adjust_child_relids_multilevel(PlannerInfo *root, Relids relids, Relids child_relids, Relids top_parent_relids)
Definition: prepunion.c:2382
void pfree(void *pointer)
Definition: mcxt.c:1031
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2618
void bms_free(Bitmapset *a)
Definition: bitmapset.c:267
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:764
bool bms_overlap(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:509
Index parent_relid
Definition: relation.h:2124
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:153
static Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2347

◆ build_child_join_sjinfo()

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

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

2576 {
2578  AppendRelInfo **left_appinfos;
2579  int left_nappinfos;
2580  AppendRelInfo **right_appinfos;
2581  int right_nappinfos;
2582 
2583  memcpy(sjinfo, parent_sjinfo, sizeof(SpecialJoinInfo));
2584  left_appinfos = find_appinfos_by_relids(root, left_relids,
2585  &left_nappinfos);
2586  right_appinfos = find_appinfos_by_relids(root, right_relids,
2587  &right_nappinfos);
2588 
2589  sjinfo->min_lefthand = adjust_child_relids(sjinfo->min_lefthand,
2590  left_nappinfos, left_appinfos);
2592  right_nappinfos,
2593  right_appinfos);
2594  sjinfo->syn_lefthand = adjust_child_relids(sjinfo->syn_lefthand,
2595  left_nappinfos, left_appinfos);
2597  right_nappinfos,
2598  right_appinfos);
2599  sjinfo->semi_rhs_exprs = (List *) adjust_appendrel_attrs(root,
2600  (Node *) sjinfo->semi_rhs_exprs,
2601  right_nappinfos,
2602  right_appinfos);
2603 
2604  pfree(left_appinfos);
2605  pfree(right_appinfos);
2606 
2607  return sjinfo;
2608 }
Relids min_righthand
Definition: relation.h:2067
Definition: nodes.h:516
Relids syn_lefthand
Definition: relation.h:2068
Relids syn_righthand
Definition: relation.h:2069
void pfree(void *pointer)
Definition: mcxt.c:1031
List * semi_rhs_exprs
Definition: relation.h:2077
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2047
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Definition: prepunion.c:2618
#define makeNode(_type_)
Definition: nodes.h:564
Definition: pg_list.h:45
Relids min_lefthand
Definition: relation.h:2066
static Relids adjust_child_relids(Relids relids, int nappinfos, AppendRelInfo **appinfos)
Definition: prepunion.c:2347

◆ canonicalize_qual()

Expr* canonicalize_qual ( Expr qual,
bool  is_check 
)

Definition at line 291 of file prepqual.c.

References Assert, find_duplicate_ors(), and IsA.

Referenced by convert_EXISTS_to_ANY(), get_proposed_default_constraint(), get_relation_constraints(), PartConstraintImpliedByRelConstraint(), preprocess_expression(), and RelationGetIndexPredicate().

292 {
293  Expr *newqual;
294 
295  /* Quick exit for empty qual */
296  if (qual == NULL)
297  return NULL;
298 
299  /* This should not be invoked on quals in implicit-AND format */
300  Assert(!IsA(qual, List));
301 
302  /*
303  * Pull up redundant subclauses in OR-of-AND trees. We do this only
304  * within the top-level AND/OR structure; there's no point in looking
305  * deeper. Also remove any NULL constants in the top-level structure.
306  */
307  newqual = find_duplicate_ors(qual, is_check);
308 
309  return newqual;
310 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
static Expr * find_duplicate_ors(Expr *qual, bool is_check)
Definition: prepqual.c:416
#define Assert(condition)
Definition: c.h:699
Definition: pg_list.h:45

◆ expand_inherited_tables()

void expand_inherited_tables ( PlannerInfo root)

Definition at line 1466 of file prepunion.c.

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

Referenced by subquery_planner().

1467 {
1468  Index nrtes;
1469  Index rti;
1470  ListCell *rl;
1471 
1472  /*
1473  * expand_inherited_rtentry may add RTEs to parse->rtable. The function is
1474  * expected to recursively handle any RTEs that it creates with inh=true.
1475  * So just scan as far as the original end of the rtable list.
1476  */
1477  nrtes = list_length(root->parse->rtable);
1478  rl = list_head(root->parse->rtable);
1479  for (rti = 1; rti <= nrtes; rti++)
1480  {
1481  RangeTblEntry *rte = (RangeTblEntry *) lfirst(rl);
1482 
1483  expand_inherited_rtentry(root, rte, rti);
1484  rl = lnext(rl);
1485  }
1486 }
Query * parse
Definition: relation.h:169
List * rtable
Definition: parsenodes.h:137
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:1509
unsigned int Index
Definition: c.h:442
#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 2618 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(), apply_scanjoin_target_to_paths(), build_child_join_rel(), build_child_join_sjinfo(), create_partitionwise_grouping_paths(), and try_partitionwise_join().

2619 {
2620  ListCell *lc;
2621  AppendRelInfo **appinfos;
2622  int cnt = 0;
2623 
2624  *nappinfos = bms_num_members(relids);
2625  appinfos = (AppendRelInfo **) palloc(sizeof(AppendRelInfo *) * *nappinfos);
2626 
2627  foreach(lc, root->append_rel_list)
2628  {
2629  AppendRelInfo *appinfo = lfirst(lc);
2630 
2631  if (bms_is_member(appinfo->child_relid, relids))
2632  {
2633  appinfos[cnt] = appinfo;
2634  cnt++;
2635 
2636  /* Stop when we have gathered all the AppendRelInfos. */
2637  if (cnt == *nappinfos)
2638  return appinfos;
2639  }
2640  }
2641 
2642  /* Should have found the entries ... */
2643  elog(ERROR, "did not find all requested child rels in append_rel_list");
2644  return NULL; /* not reached */
2645 }
#define ERROR
Definition: elog.h:43
int bms_num_members(const Bitmapset *a)
Definition: bitmapset.c:671
List * append_rel_list
Definition: relation.h:266
#define lfirst(lc)
Definition: pg_list.h:106
void * palloc(Size size)
Definition: mcxt.c:924
#define elog
Definition: elog.h:219
Index child_relid
Definition: relation.h:2125
bool bms_is_member(int x, const Bitmapset *a)
Definition: bitmapset.c:486

◆ flatten_simple_union_all()

void flatten_simple_union_all ( PlannerInfo root)

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

2354 {
2355  Query *parse = root->parse;
2356  SetOperationStmt *topop;
2357  Node *leftmostjtnode;
2358  int leftmostRTI;
2359  RangeTblEntry *leftmostRTE;
2360  int childRTI;
2361  RangeTblEntry *childRTE;
2362  RangeTblRef *rtr;
2363 
2364  /* Shouldn't be called unless query has setops */
2365  topop = castNode(SetOperationStmt, parse->setOperations);
2366  Assert(topop);
2367 
2368  /* Can't optimize away a recursive UNION */
2369  if (root->hasRecursion)
2370  return;
2371 
2372  /*
2373  * Recursively check the tree of set operations. If not all UNION ALL
2374  * with identical column types, punt.
2375  */
2376  if (!is_simple_union_all_recurse((Node *) topop, parse, topop->colTypes))
2377  return;
2378 
2379  /*
2380  * Locate the leftmost leaf query in the setops tree. The upper query's
2381  * Vars all refer to this RTE (see transformSetOperationStmt).
2382  */
2383  leftmostjtnode = topop->larg;
2384  while (leftmostjtnode && IsA(leftmostjtnode, SetOperationStmt))
2385  leftmostjtnode = ((SetOperationStmt *) leftmostjtnode)->larg;
2386  Assert(leftmostjtnode && IsA(leftmostjtnode, RangeTblRef));
2387  leftmostRTI = ((RangeTblRef *) leftmostjtnode)->rtindex;
2388  leftmostRTE = rt_fetch(leftmostRTI, parse->rtable);
2389  Assert(leftmostRTE->rtekind == RTE_SUBQUERY);
2390 
2391  /*
2392  * Make a copy of the leftmost RTE and add it to the rtable. This copy
2393  * will represent the leftmost leaf query in its capacity as a member of
2394  * the appendrel. The original will represent the appendrel as a whole.
2395  * (We must do things this way because the upper query's Vars have to be
2396  * seen as referring to the whole appendrel.)
2397  */
2398  childRTE = copyObject(leftmostRTE);
2399  parse->rtable = lappend(parse->rtable, childRTE);
2400  childRTI = list_length(parse->rtable);
2401 
2402  /* Modify the setops tree to reference the child copy */
2403  ((RangeTblRef *) leftmostjtnode)->rtindex = childRTI;
2404 
2405  /* Modify the formerly-leftmost RTE to mark it as an appendrel parent */
2406  leftmostRTE->inh = true;
2407 
2408  /*
2409  * Form a RangeTblRef for the appendrel, and insert it into FROM. The top
2410  * Query of a setops tree should have had an empty FromClause initially.
2411  */
2412  rtr = makeNode(RangeTblRef);
2413  rtr->rtindex = leftmostRTI;
2414  Assert(parse->jointree->fromlist == NIL);
2415  parse->jointree->fromlist = list_make1(rtr);
2416 
2417  /*
2418  * Now pretend the query has no setops. We must do this before trying to
2419  * do subquery pullup, because of Assert in pull_up_simple_subquery.
2420  */
2421  parse->setOperations = NULL;
2422 
2423  /*
2424  * Build AppendRelInfo information, and apply pull_up_subqueries to the
2425  * leaf queries of the UNION ALL. (We must do that now because they
2426  * weren't previously referenced by the jointree, and so were missed by
2427  * the main invocation of pull_up_subqueries.)
2428  */
2429  pull_up_union_leaf_queries((Node *) topop, root, leftmostRTI, parse, 0);
2430 }
#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:567
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:585
Definition: nodes.h:516
static bool is_simple_union_all_recurse(Node *setOp, Query *setOpQuery, List *colTypes)
List * fromlist
Definition: primnodes.h:1478
bool hasRecursion
Definition: relation.h:321
#define list_make1(x1)
Definition: pg_list.h:139
List * rtable
Definition: parsenodes.h:137
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
List * lappend(List *list, void *datum)
Definition: list.c:128
#define makeNode(_type_)
Definition: nodes.h:564
#define Assert(condition)
Definition: c.h:699
static int list_length(const List *l)
Definition: pg_list.h:89
RTEKind rtekind
Definition: parsenodes.h:962
Node * setOperations
Definition: parsenodes.h:165
#define copyObject(obj)
Definition: nodes.h:629
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 3019 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().

3020 {
3021  Node *jtnode;
3022 
3023  jtnode = find_jointree_node_for_rel((Node *) root->parse->jointree,
3024  joinrelid);
3025  if (!jtnode)
3026  elog(ERROR, "could not find join node %d", joinrelid);
3027  return get_relids_in_jointree(jtnode, false);
3028 }
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:516
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 2975 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().

2976 {
2977  Relids result = NULL;
2978 
2979  if (jtnode == NULL)
2980  return result;
2981  if (IsA(jtnode, RangeTblRef))
2982  {
2983  int varno = ((RangeTblRef *) jtnode)->rtindex;
2984 
2985  result = bms_make_singleton(varno);
2986  }
2987  else if (IsA(jtnode, FromExpr))
2988  {
2989  FromExpr *f = (FromExpr *) jtnode;
2990  ListCell *l;
2991 
2992  foreach(l, f->fromlist)
2993  {
2994  result = bms_join(result,
2996  include_joins));
2997  }
2998  }
2999  else if (IsA(jtnode, JoinExpr))
3000  {
3001  JoinExpr *j = (JoinExpr *) jtnode;
3002 
3003  result = get_relids_in_jointree(j->larg, include_joins);
3004  result = bms_join(result,
3005  get_relids_in_jointree(j->rarg, include_joins));
3006  if (include_joins && j->rtindex)
3007  result = bms_add_member(result, j->rtindex);
3008  }
3009  else
3010  elog(ERROR, "unrecognized node type: %d",
3011  (int) nodeTag(jtnode));
3012  return result;
3013 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
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:976
Relids get_relids_in_jointree(Node *jtnode, bool include_joins)
Bitmapset * bms_make_singleton(int x)
Definition: bitmapset.c:245
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:764
#define nodeTag(nodeptr)
Definition: nodes.h:521
#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:169
Query * inline_set_returning_function(PlannerInfo *root, RangeTblEntry *rte)
Definition: clauses.c:4932
List * rtable
Definition: parsenodes.h:137
#define lfirst(lc)
Definition: pg_list.h:106
List * functions
Definition: parsenodes.h:1016
RTEKind rtekind
Definition: parsenodes.h:962
Query * subquery
Definition: parsenodes.h:985

◆ 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(), match_boolean_partition_clause(), 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:516
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:378
Oid opcollid
Definition: primnodes.h:500
Definition: nodes.h:151
List * lappend(List *list, void *datum)
Definition: list.c:128
BoolTestType booltesttype
Definition: primnodes.h:1211
Expr * make_notclause(Expr *notclause)
Definition: clauses.c:250
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:564
#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:521
bool argisrow
Definition: primnodes.h:1189
Expr * make_andclause(List *andclauses)
Definition: clauses.c:328
Oid opno
Definition: primnodes.h:496
#define elog
Definition: elog.h:219
Oid get_negator(Oid opno)
Definition: lsyscache.c:1322
List * args
Definition: primnodes.h:502
Definition: pg_list.h:45
Expr * make_orclause(List *orclauses)
Definition: clauses.c:294
bool constisnull
Definition: primnodes.h:197
bool opretset
Definition: primnodes.h:499

◆ plan_set_operations()

RelOptInfo* plan_set_operations ( PlannerInfo root)

Definition at line 142 of file prepunion.c.

References Assert, castNode, Query::distinctClause, FromExpr::fromlist, generate_recursion_path(), Query::groupClause, PlannerInfo::hasRecursion, Query::havingQual, IsA, Query::jointree, SetOperationStmt::larg, NIL, parse(), PlannerInfo::parse, PlannerInfo::processed_tlist, FromExpr::quals, recurse_set_operations(), Query::setOperations, setup_simple_rel_arrays(), PlannerInfo::simple_rte_array, RangeTblEntry::subquery, Query::targetList, and Query::windowClause.

Referenced by grouping_planner().

143 {
144  Query *parse = root->parse;
146  Node *node;
147  RangeTblEntry *leftmostRTE;
148  Query *leftmostQuery;
149  RelOptInfo *setop_rel;
150  List *top_tlist;
151 
152  Assert(topop);
153 
154  /* check for unsupported stuff */
155  Assert(parse->jointree->fromlist == NIL);
156  Assert(parse->jointree->quals == NULL);
157  Assert(parse->groupClause == NIL);
158  Assert(parse->havingQual == NULL);
159  Assert(parse->windowClause == NIL);
160  Assert(parse->distinctClause == NIL);
161 
162  /*
163  * We'll need to build RelOptInfos for each of the leaf subqueries, which
164  * are RTE_SUBQUERY rangetable entries in this Query. Prepare the index
165  * arrays for that.
166  */
168 
169  /*
170  * Find the leftmost component Query. We need to use its column names for
171  * all generated tlists (else SELECT INTO won't work right).
172  */
173  node = topop->larg;
174  while (node && IsA(node, SetOperationStmt))
175  node = ((SetOperationStmt *) node)->larg;
176  Assert(node && IsA(node, RangeTblRef));
177  leftmostRTE = root->simple_rte_array[((RangeTblRef *) node)->rtindex];
178  leftmostQuery = leftmostRTE->subquery;
179  Assert(leftmostQuery != NULL);
180 
181  /*
182  * If the topmost node is a recursive union, it needs special processing.
183  */
184  if (root->hasRecursion)
185  {
186  setop_rel = generate_recursion_path(topop, root,
187  leftmostQuery->targetList,
188  &top_tlist);
189  }
190  else
191  {
192  /*
193  * Recurse on setOperations tree to generate paths for set ops. The
194  * final output paths should have just the column types shown as the
195  * output from the top-level node, plus possibly resjunk working
196  * columns (we can rely on upper-level nodes to deal with that).
197  */
198  setop_rel = recurse_set_operations((Node *) topop, root,
199  topop->colTypes, topop->colCollations,
200  true, -1,
201  leftmostQuery->targetList,
202  &top_tlist,
203  NULL);
204  }
205 
206  /* Must return the built tlist into root->processed_tlist. */
207  root->processed_tlist = top_tlist;
208 
209  return setop_rel;
210 }
static RelOptInfo * generate_recursion_path(SetOperationStmt *setOp, PlannerInfo *root, List *refnames_tlist, List **pTargetList)
Definition: prepunion.c:463
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
#define castNode(_type_, nodeptr)
Definition: nodes.h:585
Definition: nodes.h:516
static RelOptInfo * recurse_set_operations(Node *setOp, PlannerInfo *root, List *colTypes, List *colCollations, bool junkOK, int flag, List *refnames_tlist, List **pTargetList, double *pNumGroups)
Definition: prepunion.c:237
List * fromlist
Definition: primnodes.h:1478
bool hasRecursion
Definition: relation.h:321
Node * quals
Definition: primnodes.h:1479
List * windowClause
Definition: parsenodes.h:154
List * targetList
Definition: parsenodes.h:140
List * distinctClause
Definition: parsenodes.h:156
RangeTblEntry ** simple_rte_array
Definition: relation.h:202
#define Assert(condition)
Definition: c.h:699
void setup_simple_rel_arrays(PlannerInfo *root)
Definition: relnode.c:67
Node * setOperations
Definition: parsenodes.h:165
Query * subquery
Definition: parsenodes.h:985
List * groupClause
Definition: parsenodes.h:148
Node * havingQual
Definition: parsenodes.h:152
List * processed_tlist
Definition: relation.h:296
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, 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, 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:268
#define IsA(nodeptr, _type_)
Definition: nodes.h:567
Query * parse
Definition: relation.h:169
#define PVC_RECURSE_AGGREGATES
Definition: var.h:21
OnConflictExpr * onConflict
Definition: parsenodes.h:144
char * pstrdup(const char *in)
Definition: mcxt.c:1161
int resultRelation
Definition: parsenodes.h:122
Definition: nodes.h:516
Var * makeWholeRowVar(RangeTblEntry *rte, Index varno, Index varlevelsup, bool allowScalar)
Definition: makefuncs.c:134
Index prti
Definition: plannodes.h:1039
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:1040
List * targetList
Definition: parsenodes.h:140
#define PVC_INCLUDE_PLACEHOLDERS
Definition: var.h:24
List * rtable
Definition: parsenodes.h:137
#define ERROR
Definition: elog.h:43
#define NoLock
Definition: lockdefs.h:34
#define TableOidAttributeNumber
Definition: sysattr.h:27
int allMarkTypes
Definition: plannodes.h:1042
#define PVC_RECURSE_WINDOWFUNCS
Definition: var.h:23
List * returningList
Definition: parsenodes.h:146
#define rt_fetch(rangetable_index, rangetable)
Definition: parsetree.h:31
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c: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:1294
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:72
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:112
#define Assert(condition)
Definition: c.h:699
#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:962
void list_free(List *list)
Definition: list.c:1133
List * onConflictSet
Definition: primnodes.h:1503
bool isParent
Definition: plannodes.h:1045
#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:656
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:567
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:516
#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:567
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:516
bool hasDeletedRTEs
Definition: relation.h:317
static Node * pull_up_subqueries_cleanup(Node *jtnode)
#define Assert(condition)
Definition: c.h:699

◆ reduce_outer_joins()

void reduce_outer_joins ( PlannerInfo root)

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

2472 {
2474 
2475  /*
2476  * To avoid doing strictness checks on more quals than necessary, we want
2477  * to stop descending the jointree as soon as there are no outer joins
2478  * below our current point. This consideration forces a two-pass process.
2479  * The first pass gathers information about which base rels appear below
2480  * each side of each join clause, and about whether there are outer
2481  * join(s) below each side of each join clause. The second pass examines
2482  * qual clauses and changes join types as it descends the tree.
2483  */
2484  state = reduce_outer_joins_pass1((Node *) root->parse->jointree);
2485 
2486  /* planner.c shouldn't have called me if no outer joins */
2487  if (state == NULL || !state->contains_outer)
2488  elog(ERROR, "so where are the outer joins?");
2489 
2491  state, root, NULL, NIL, NIL);
2492 }
#define NIL
Definition: pg_list.h:69
Query * parse
Definition: relation.h:169
FromExpr * jointree
Definition: parsenodes.h:138
Definition: nodes.h:516
#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)