PostgreSQL Source Code  git master
setrefs.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/pathnode.h"
#include "optimizer/planmain.h"
#include "optimizer/planner.h"
#include "optimizer/tlist.h"
#include "tcop/utility.h"
#include "utils/lsyscache.h"
#include "utils/syscache.h"
Include dependency graph for setrefs.c:

Go to the source code of this file.

Data Structures

struct  tlist_vinfo
 
struct  indexed_tlist
 
struct  fix_scan_expr_context
 
struct  fix_join_expr_context
 
struct  fix_upper_expr_context
 

Macros

#define ISREGCLASSCONST(con)
 
#define fix_scan_list(root, lst, rtoffset)   ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))
 

Functions

static void add_rtes_to_flat_rtable (PlannerInfo *root, bool recursing)
 
static void flatten_unplanned_rtes (PlannerGlobal *glob, RangeTblEntry *rte)
 
static bool flatten_rtes_walker (Node *node, PlannerGlobal *glob)
 
static void add_rte_to_flat_rtable (PlannerGlobal *glob, RangeTblEntry *rte)
 
static Planset_plan_refs (PlannerInfo *root, Plan *plan, int rtoffset)
 
static Planset_indexonlyscan_references (PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
 
static Planset_subqueryscan_references (PlannerInfo *root, SubqueryScan *plan, int rtoffset)
 
static bool trivial_subqueryscan (SubqueryScan *plan)
 
static void set_foreignscan_references (PlannerInfo *root, ForeignScan *fscan, int rtoffset)
 
static void set_customscan_references (PlannerInfo *root, CustomScan *cscan, int rtoffset)
 
static Nodefix_scan_expr (PlannerInfo *root, Node *node, int rtoffset)
 
static Nodefix_scan_expr_mutator (Node *node, fix_scan_expr_context *context)
 
static bool fix_scan_expr_walker (Node *node, fix_scan_expr_context *context)
 
static void set_join_references (PlannerInfo *root, Join *join, int rtoffset)
 
static void set_upper_references (PlannerInfo *root, Plan *plan, int rtoffset)
 
static void set_param_references (PlannerInfo *root, Plan *plan)
 
static Nodeconvert_combining_aggrefs (Node *node, void *context)
 
static void set_dummy_tlist_references (Plan *plan, int rtoffset)
 
static indexed_tlistbuild_tlist_index (List *tlist)
 
static Varsearch_indexed_tlist_for_var (Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
 
static Varsearch_indexed_tlist_for_non_var (Expr *node, indexed_tlist *itlist, Index newvarno)
 
static Varsearch_indexed_tlist_for_sortgroupref (Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
 
static Listfix_join_expr (PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset)
 
static Nodefix_join_expr_mutator (Node *node, fix_join_expr_context *context)
 
static Nodefix_upper_expr (PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
 
static Nodefix_upper_expr_mutator (Node *node, fix_upper_expr_context *context)
 
static Listset_returning_clause_references (PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
 
static bool extract_query_dependencies_walker (Node *node, PlannerInfo *context)
 
static bool is_converted_whole_row_reference (Node *node)
 
Planset_plan_references (PlannerInfo *root, Plan *plan)
 
static VarcopyVar (Var *var)
 
static void fix_expr_common (PlannerInfo *root, Node *node)
 
static Nodefix_param_node (PlannerInfo *root, Param *p)
 
static indexed_tlistbuild_tlist_index_other_vars (List *tlist, Index ignore_rel)
 
void record_plan_function_dependency (PlannerInfo *root, Oid funcid)
 
void extract_query_dependencies (Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
 

Macro Definition Documentation

◆ fix_scan_list

#define fix_scan_list (   root,
  lst,
  rtoffset 
)    ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))

◆ ISREGCLASSCONST

#define ISREGCLASSCONST (   con)
Value:
(((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
!(con)->constisnull)
#define REGCLASSOID
Definition: pg_type.h:577
#define OIDOID
Definition: pg_type.h:328

Definition at line 80 of file setrefs.c.

Referenced by fix_expr_common().

Function Documentation

◆ add_rte_to_flat_rtable()

static void add_rte_to_flat_rtable ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 388 of file setrefs.c.

References RangeTblEntry::colcollations, RangeTblEntry::coltypes, RangeTblEntry::coltypmods, ereport, errcode(), errmsg(), ERROR, PlannerGlobal::finalrtable, RangeTblEntry::functions, IS_SPECIAL_VARNO, RangeTblEntry::joinaliasvars, lappend(), lappend_oid(), list_length(), NIL, palloc(), PlannerGlobal::relationOids, RangeTblEntry::relid, RTE_RELATION, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, RangeTblEntry::subquery, RangeTblEntry::tablefunc, RangeTblEntry::tablesample, and RangeTblEntry::values_lists.

Referenced by add_rtes_to_flat_rtable(), and flatten_rtes_walker().

389 {
390  RangeTblEntry *newrte;
391 
392  /* flat copy to duplicate all the scalar fields */
393  newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
394  memcpy(newrte, rte, sizeof(RangeTblEntry));
395 
396  /* zap unneeded sub-structure */
397  newrte->tablesample = NULL;
398  newrte->subquery = NULL;
399  newrte->joinaliasvars = NIL;
400  newrte->functions = NIL;
401  newrte->tablefunc = NULL;
402  newrte->values_lists = NIL;
403  newrte->coltypes = NIL;
404  newrte->coltypmods = NIL;
405  newrte->colcollations = NIL;
406  newrte->securityQuals = NIL;
407 
408  glob->finalrtable = lappend(glob->finalrtable, newrte);
409 
410  /*
411  * Check for RT index overflow; it's very unlikely, but if it did happen,
412  * the executor would get confused by varnos that match the special varno
413  * values.
414  */
416  ereport(ERROR,
417  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
418  errmsg("too many range table entries")));
419 
420  /*
421  * If it's a plain relation RTE, add the table to relationOids.
422  *
423  * We do this even though the RTE might be unreferenced in the plan tree;
424  * this would correspond to cases such as views that were expanded, child
425  * tables that were eliminated by constraint exclusion, etc. Schema
426  * invalidation on such a rel must still force rebuilding of the plan.
427  *
428  * Note we don't bother to avoid making duplicate list entries. We could,
429  * but it would probably cost more cycles than it would save.
430  */
431  if (newrte->rtekind == RTE_RELATION)
432  glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
433 }
#define NIL
Definition: pg_list.h:69
List * joinaliasvars
Definition: parsenodes.h:995
List * securityQuals
Definition: parsenodes.h:1064
List * coltypmods
Definition: parsenodes.h:1042
int errcode(int sqlerrcode)
Definition: elog.c:575
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
List * colcollations
Definition: parsenodes.h:1043
List * values_lists
Definition: parsenodes.h:1016
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:157
#define ERROR
Definition: elog.h:43
TableFunc * tablefunc
Definition: parsenodes.h:1011
#define ereport(elevel, rest)
Definition: elog.h:122
List * lappend(List *list, void *datum)
Definition: list.c:128
List * functions
Definition: parsenodes.h:1005
static int list_length(const List *l)
Definition: pg_list.h:89
List * relationOids
Definition: relation.h:113
RTEKind rtekind
Definition: parsenodes.h:951
List * finalrtable
Definition: relation.h:104
Query * subquery
Definition: parsenodes.h:974
void * palloc(Size size)
Definition: mcxt.c:848
int errmsg(const char *fmt,...)
Definition: elog.c:797
List * coltypes
Definition: parsenodes.h:1041
struct TableSampleClause * tablesample
Definition: parsenodes.h:969

◆ add_rtes_to_flat_rtable()

static void add_rtes_to_flat_rtable ( PlannerInfo root,
bool  recursing 
)
static

Definition at line 256 of file setrefs.c.

References add_rte_to_flat_rtable(), Assert, fetch_upper_rel(), flatten_unplanned_rtes(), PlannerInfo::glob, RangeTblEntry::inh, IS_DUMMY_REL, lfirst, PlannerInfo::parse, RelOptInfo::relid, Query::rtable, RTE_RELATION, RTE_SUBQUERY, RangeTblEntry::rtekind, PlannerInfo::simple_rel_array, RelOptInfo::subroot, and UPPERREL_FINAL.

Referenced by set_plan_references().

257 {
258  PlannerGlobal *glob = root->glob;
259  Index rti;
260  ListCell *lc;
261 
262  /*
263  * Add the query's own RTEs to the flattened rangetable.
264  *
265  * At top level, we must add all RTEs so that their indexes in the
266  * flattened rangetable match up with their original indexes. When
267  * recursing, we only care about extracting relation RTEs.
268  */
269  foreach(lc, root->parse->rtable)
270  {
271  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
272 
273  if (!recursing || rte->rtekind == RTE_RELATION)
274  add_rte_to_flat_rtable(glob, rte);
275  }
276 
277  /*
278  * If there are any dead subqueries, they are not referenced in the Plan
279  * tree, so we must add RTEs contained in them to the flattened rtable
280  * separately. (If we failed to do this, the executor would not perform
281  * expected permission checks for tables mentioned in such subqueries.)
282  *
283  * Note: this pass over the rangetable can't be combined with the previous
284  * one, because that would mess up the numbering of the live RTEs in the
285  * flattened rangetable.
286  */
287  rti = 1;
288  foreach(lc, root->parse->rtable)
289  {
290  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
291 
292  /*
293  * We should ignore inheritance-parent RTEs: their contents have been
294  * pulled up into our rangetable already. Also ignore any subquery
295  * RTEs without matching RelOptInfos, as they likewise have been
296  * pulled up.
297  */
298  if (rte->rtekind == RTE_SUBQUERY && !rte->inh &&
299  rti < root->simple_rel_array_size)
300  {
301  RelOptInfo *rel = root->simple_rel_array[rti];
302 
303  if (rel != NULL)
304  {
305  Assert(rel->relid == rti); /* sanity check on array */
306 
307  /*
308  * The subquery might never have been planned at all, if it
309  * was excluded on the basis of self-contradictory constraints
310  * in our query level. In this case apply
311  * flatten_unplanned_rtes.
312  *
313  * If it was planned but the result rel is dummy, we assume
314  * that it has been omitted from our plan tree (see
315  * set_subquery_pathlist), and recurse to pull up its RTEs.
316  *
317  * Otherwise, it should be represented by a SubqueryScan node
318  * somewhere in our plan tree, and we'll pull up its RTEs when
319  * we process that plan node.
320  *
321  * However, if we're recursing, then we should pull up RTEs
322  * whether the subquery is dummy or not, because we've found
323  * that some upper query level is treating this one as dummy,
324  * and so we won't scan this level's plan tree at all.
325  */
326  if (rel->subroot == NULL)
327  flatten_unplanned_rtes(glob, rte);
328  else if (recursing ||
330  UPPERREL_FINAL, NULL)))
331  add_rtes_to_flat_rtable(rel->subroot, true);
332  }
333  }
334  rti++;
335  }
336 }
Query * parse
Definition: relation.h:155
static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:342
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:388
struct RelOptInfo ** simple_rel_array
Definition: relation.h:179
PlannerInfo * subroot
Definition: relation.h:627
List * rtable
Definition: parsenodes.h:135
#define IS_DUMMY_REL(r)
Definition: relation.h:1275
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1137
PlannerGlobal * glob
Definition: relation.h:157
Index relid
Definition: relation.h:613
unsigned int Index
Definition: c.h:413
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:256
RTEKind rtekind
Definition: parsenodes.h:951

◆ build_tlist_index()

static indexed_tlist * build_tlist_index ( List tlist)
static

Definition at line 1986 of file setrefs.c.

References TargetEntry::expr, indexed_tlist::has_conv_whole_rows, indexed_tlist::has_non_vars, indexed_tlist::has_ph_vars, is_converted_whole_row_reference(), IsA, lfirst, list_length(), indexed_tlist::num_vars, offsetof, palloc(), tlist_vinfo::resno, TargetEntry::resno, indexed_tlist::tlist, tlist_vinfo::varattno, Var::varattno, tlist_vinfo::varno, Var::varno, and indexed_tlist::vars.

Referenced by set_customscan_references(), set_foreignscan_references(), set_indexonlyscan_references(), set_join_references(), set_plan_refs(), and set_upper_references().

1987 {
1988  indexed_tlist *itlist;
1989  tlist_vinfo *vinfo;
1990  ListCell *l;
1991 
1992  /* Create data structure with enough slots for all tlist entries */
1993  itlist = (indexed_tlist *)
1995  list_length(tlist) * sizeof(tlist_vinfo));
1996 
1997  itlist->tlist = tlist;
1998  itlist->has_ph_vars = false;
1999  itlist->has_non_vars = false;
2000  itlist->has_conv_whole_rows = false;
2001 
2002  /* Find the Vars and fill in the index array */
2003  vinfo = itlist->vars;
2004  foreach(l, tlist)
2005  {
2006  TargetEntry *tle = (TargetEntry *) lfirst(l);
2007 
2008  if (tle->expr && IsA(tle->expr, Var))
2009  {
2010  Var *var = (Var *) tle->expr;
2011 
2012  vinfo->varno = var->varno;
2013  vinfo->varattno = var->varattno;
2014  vinfo->resno = tle->resno;
2015  vinfo++;
2016  }
2017  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2018  itlist->has_ph_vars = true;
2019  else if (is_converted_whole_row_reference((Node *) tle->expr))
2020  itlist->has_conv_whole_rows = true;
2021  else
2022  itlist->has_non_vars = true;
2023  }
2024 
2025  itlist->num_vars = (vinfo - itlist->vars);
2026 
2027  return itlist;
2028 }
Index varno
Definition: setrefs.c:33
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:47
AttrNumber resno
Definition: setrefs.c:35
Definition: nodes.h:510
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
AttrNumber varattno
Definition: setrefs.c:34
bool has_ph_vars
Definition: setrefs.c:42
int num_vars
Definition: setrefs.c:41
AttrNumber resno
Definition: primnodes.h:1376
Index varno
Definition: primnodes.h:166
bool has_non_vars
Definition: setrefs.c:43
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
bool has_conv_whole_rows
Definition: setrefs.c:44
void * palloc(Size size)
Definition: mcxt.c:848
static bool is_converted_whole_row_reference(Node *node)
Definition: setrefs.c:2680
Definition: regcomp.c:224
#define offsetof(type, field)
Definition: c.h:593
List * tlist
Definition: setrefs.c:40

◆ build_tlist_index_other_vars()

static indexed_tlist* build_tlist_index_other_vars ( List tlist,
Index  ignore_rel 
)
static

Definition at line 2042 of file setrefs.c.

References TargetEntry::expr, indexed_tlist::has_conv_whole_rows, indexed_tlist::has_non_vars, indexed_tlist::has_ph_vars, IsA, lfirst, list_length(), indexed_tlist::num_vars, offsetof, palloc(), tlist_vinfo::resno, TargetEntry::resno, indexed_tlist::tlist, tlist_vinfo::varattno, Var::varattno, tlist_vinfo::varno, Var::varno, and indexed_tlist::vars.

Referenced by set_returning_clause_references().

2043 {
2044  indexed_tlist *itlist;
2045  tlist_vinfo *vinfo;
2046  ListCell *l;
2047 
2048  /* Create data structure with enough slots for all tlist entries */
2049  itlist = (indexed_tlist *)
2051  list_length(tlist) * sizeof(tlist_vinfo));
2052 
2053  itlist->tlist = tlist;
2054  itlist->has_ph_vars = false;
2055  itlist->has_non_vars = false;
2056  itlist->has_conv_whole_rows = false;
2057 
2058  /* Find the desired Vars and fill in the index array */
2059  vinfo = itlist->vars;
2060  foreach(l, tlist)
2061  {
2062  TargetEntry *tle = (TargetEntry *) lfirst(l);
2063 
2064  if (tle->expr && IsA(tle->expr, Var))
2065  {
2066  Var *var = (Var *) tle->expr;
2067 
2068  if (var->varno != ignore_rel)
2069  {
2070  vinfo->varno = var->varno;
2071  vinfo->varattno = var->varattno;
2072  vinfo->resno = tle->resno;
2073  vinfo++;
2074  }
2075  }
2076  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2077  itlist->has_ph_vars = true;
2078  }
2079 
2080  itlist->num_vars = (vinfo - itlist->vars);
2081 
2082  return itlist;
2083 }
Index varno
Definition: setrefs.c:33
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:47
AttrNumber resno
Definition: setrefs.c:35
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
AttrNumber varattno
Definition: setrefs.c:34
bool has_ph_vars
Definition: setrefs.c:42
int num_vars
Definition: setrefs.c:41
AttrNumber resno
Definition: primnodes.h:1376
Index varno
Definition: primnodes.h:166
bool has_non_vars
Definition: setrefs.c:43
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
bool has_conv_whole_rows
Definition: setrefs.c:44
void * palloc(Size size)
Definition: mcxt.c:848
Definition: regcomp.c:224
#define offsetof(type, field)
Definition: c.h:593
List * tlist
Definition: setrefs.c:40

◆ convert_combining_aggrefs()

static Node * convert_combining_aggrefs ( Node node,
void *  context 
)
static

Definition at line 1851 of file setrefs.c.

References Aggref::aggdistinct, Aggref::aggfilter, Aggref::aggorder, AGGSPLIT_FINAL_DESERIAL, AGGSPLIT_INITIAL_SERIAL, Aggref::args, Assert, copyObject, expression_tree_mutator(), IsA, list_make1, makeNode, makeTargetEntry(), mark_partial_aggref(), and NIL.

Referenced by set_plan_refs().

1852 {
1853  if (node == NULL)
1854  return NULL;
1855  if (IsA(node, Aggref))
1856  {
1857  Aggref *orig_agg = (Aggref *) node;
1858  Aggref *child_agg;
1859  Aggref *parent_agg;
1860 
1861  /* Assert we've not chosen to partial-ize any unsupported cases */
1862  Assert(orig_agg->aggorder == NIL);
1863  Assert(orig_agg->aggdistinct == NIL);
1864 
1865  /*
1866  * Since aggregate calls can't be nested, we needn't recurse into the
1867  * arguments. But for safety, flat-copy the Aggref node itself rather
1868  * than modifying it in-place.
1869  */
1870  child_agg = makeNode(Aggref);
1871  memcpy(child_agg, orig_agg, sizeof(Aggref));
1872 
1873  /*
1874  * For the parent Aggref, we want to copy all the fields of the
1875  * original aggregate *except* the args list, which we'll replace
1876  * below, and the aggfilter expression, which should be applied only
1877  * by the child not the parent. Rather than explicitly knowing about
1878  * all the other fields here, we can momentarily modify child_agg to
1879  * provide a suitable source for copyObject.
1880  */
1881  child_agg->args = NIL;
1882  child_agg->aggfilter = NULL;
1883  parent_agg = copyObject(child_agg);
1884  child_agg->args = orig_agg->args;
1885  child_agg->aggfilter = orig_agg->aggfilter;
1886 
1887  /*
1888  * Now, set up child_agg to represent the first phase of partial
1889  * aggregation. For now, assume serialization is required.
1890  */
1892 
1893  /*
1894  * And set up parent_agg to represent the second phase.
1895  */
1896  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
1897  1, NULL, false));
1899 
1900  return (Node *) parent_agg;
1901  }
1903  (void *) context);
1904 }
List * aggdistinct
Definition: primnodes.h:303
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2409
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:5325
Definition: nodes.h:510
List * args
Definition: primnodes.h:301
#define list_make1(x1)
Definition: pg_list.h:139
List * aggorder
Definition: primnodes.h:302
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:237
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:1851
#define makeNode(_type_)
Definition: nodes.h:558
#define Assert(condition)
Definition: c.h:670
Expr * aggfilter
Definition: primnodes.h:304
#define copyObject(obj)
Definition: nodes.h:623

◆ copyVar()

static Var* copyVar ( Var var)
inlinestatic

Definition at line 1342 of file setrefs.c.

References palloc().

Referenced by fix_join_expr_mutator(), fix_scan_expr_mutator(), and search_indexed_tlist_for_var().

1343 {
1344  Var *newvar = (Var *) palloc(sizeof(Var));
1345 
1346  *newvar = *var;
1347  return newvar;
1348 }
Definition: primnodes.h:163
void * palloc(Size size)
Definition: mcxt.c:848

◆ extract_query_dependencies()

void extract_query_dependencies ( Node query,
List **  relationOids,
List **  invalItems,
bool hasRowSecurity 
)

Definition at line 2596 of file setrefs.c.

References PlannerGlobal::dependsOnRole, extract_query_dependencies_walker(), PlannerInfo::glob, PlannerGlobal::invalItems, MemSet, NIL, PlannerGlobal::relationOids, T_PlannerGlobal, T_PlannerInfo, PlannerGlobal::type, and PlannerInfo::type.

Referenced by CompleteCachedPlan(), and RevalidateCachedQuery().

2600 {
2601  PlannerGlobal glob;
2602  PlannerInfo root;
2603 
2604  /* Make up dummy planner state so we can use this module's machinery */
2605  MemSet(&glob, 0, sizeof(glob));
2606  glob.type = T_PlannerGlobal;
2607  glob.relationOids = NIL;
2608  glob.invalItems = NIL;
2609  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2610  glob.dependsOnRole = false;
2611 
2612  MemSet(&root, 0, sizeof(root));
2613  root.type = T_PlannerInfo;
2614  root.glob = &glob;
2615 
2616  (void) extract_query_dependencies_walker(query, &root);
2617 
2618  *relationOids = glob.relationOids;
2619  *invalItems = glob.invalItems;
2620  *hasRowSecurity = glob.dependsOnRole;
2621 }
#define NIL
Definition: pg_list.h:69
#define MemSet(start, val, len)
Definition: c.h:853
bool dependsOnRole
Definition: relation.h:127
PlannerGlobal * glob
Definition: relation.h:157
List * invalItems
Definition: relation.h:115
NodeTag type
Definition: relation.h:153
static bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2624
NodeTag type
Definition: relation.h:94
List * relationOids
Definition: relation.h:113

◆ extract_query_dependencies_walker()

static bool extract_query_dependencies_walker ( Node node,
PlannerInfo context 
)
static

Definition at line 2624 of file setrefs.c.

References Assert, CMD_UTILITY, Query::commandType, PlannerGlobal::dependsOnRole, expression_tree_walker(), fix_expr_common(), PlannerInfo::glob, Query::hasRowSecurity, IsA, lappend_oid(), lfirst, OidIsValid, query_tree_walker(), PlannerGlobal::relationOids, RangeTblEntry::relid, Query::rtable, RTE_NAMEDTUPLESTORE, RTE_RELATION, RangeTblEntry::rtekind, UtilityContainsQuery(), and Query::utilityStmt.

Referenced by extract_query_dependencies().

2625 {
2626  if (node == NULL)
2627  return false;
2628  Assert(!IsA(node, PlaceHolderVar));
2629  /* Extract function dependencies and check for regclass Consts */
2630  fix_expr_common(context, node);
2631  if (IsA(node, Query))
2632  {
2633  Query *query = (Query *) node;
2634  ListCell *lc;
2635 
2636  if (query->commandType == CMD_UTILITY)
2637  {
2638  /*
2639  * Ignore utility statements, except those (such as EXPLAIN) that
2640  * contain a parsed-but-not-planned query.
2641  */
2642  query = UtilityContainsQuery(query->utilityStmt);
2643  if (query == NULL)
2644  return false;
2645  }
2646 
2647  /* Remember if any Query has RLS quals applied by rewriter */
2648  if (query->hasRowSecurity)
2649  context->glob->dependsOnRole = true;
2650 
2651  /* Collect relation OIDs in this Query's rtable */
2652  foreach(lc, query->rtable)
2653  {
2654  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2655 
2656  if (rte->rtekind == RTE_RELATION)
2657  context->glob->relationOids =
2658  lappend_oid(context->glob->relationOids, rte->relid);
2659  else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
2660  OidIsValid(rte->relid))
2661  context->glob->relationOids =
2662  lappend_oid(context->glob->relationOids,
2663  rte->relid);
2664  }
2665 
2666  /* And recurse into the query's subexpressions */
2668  (void *) context, 0);
2669  }
2671  (void *) context);
2672 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2245
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Node * utilityStmt
Definition: parsenodes.h:118
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:576
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1856
bool dependsOnRole
Definition: relation.h:127
List * rtable
Definition: parsenodes.h:135
PlannerGlobal * glob
Definition: relation.h:157
static bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2624
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1364
CmdType commandType
Definition: parsenodes.h:110
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1834
List * relationOids
Definition: relation.h:113
RTEKind rtekind
Definition: parsenodes.h:951
bool hasRowSecurity
Definition: parsenodes.h:131

◆ fix_expr_common()

static void fix_expr_common ( PlannerInfo root,
Node node 
)
static

Definition at line 1364 of file setrefs.c.

References Assert, GroupingFunc::cols, Const::constvalue, DatumGetObjectId, equal(), PlannerInfo::glob, PlannerInfo::grouping_map, IsA, ISREGCLASSCONST, lappend_int(), lappend_oid(), lfirst_int, NIL, record_plan_function_dependency(), GroupingFunc::refs, PlannerGlobal::relationOids, set_opfuncid(), and set_sa_opfuncid().

Referenced by extract_query_dependencies_walker(), fix_join_expr_mutator(), fix_scan_expr_mutator(), fix_scan_expr_walker(), and fix_upper_expr_mutator().

1365 {
1366  /* We assume callers won't call us on a NULL pointer */
1367  if (IsA(node, Aggref))
1368  {
1370  ((Aggref *) node)->aggfnoid);
1371  }
1372  else if (IsA(node, WindowFunc))
1373  {
1375  ((WindowFunc *) node)->winfnoid);
1376  }
1377  else if (IsA(node, FuncExpr))
1378  {
1380  ((FuncExpr *) node)->funcid);
1381  }
1382  else if (IsA(node, OpExpr))
1383  {
1384  set_opfuncid((OpExpr *) node);
1386  ((OpExpr *) node)->opfuncid);
1387  }
1388  else if (IsA(node, DistinctExpr))
1389  {
1390  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1392  ((DistinctExpr *) node)->opfuncid);
1393  }
1394  else if (IsA(node, NullIfExpr))
1395  {
1396  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1398  ((NullIfExpr *) node)->opfuncid);
1399  }
1400  else if (IsA(node, ScalarArrayOpExpr))
1401  {
1404  ((ScalarArrayOpExpr *) node)->opfuncid);
1405  }
1406  else if (IsA(node, Const))
1407  {
1408  Const *con = (Const *) node;
1409 
1410  /* Check for regclass reference */
1411  if (ISREGCLASSCONST(con))
1412  root->glob->relationOids =
1413  lappend_oid(root->glob->relationOids,
1415  }
1416  else if (IsA(node, GroupingFunc))
1417  {
1418  GroupingFunc *g = (GroupingFunc *) node;
1419  AttrNumber *grouping_map = root->grouping_map;
1420 
1421  /* If there are no grouping sets, we don't need this. */
1422 
1423  Assert(grouping_map || g->cols == NIL);
1424 
1425  if (grouping_map)
1426  {
1427  ListCell *lc;
1428  List *cols = NIL;
1429 
1430  foreach(lc, g->refs)
1431  {
1432  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1433  }
1434 
1435  Assert(!g->cols || equal(cols, g->cols));
1436 
1437  if (!g->cols)
1438  g->cols = cols;
1439  }
1440  }
1441 }
Datum constvalue
Definition: primnodes.h:196
#define NIL
Definition: pg_list.h:69
#define ISREGCLASSCONST(con)
Definition: setrefs.c:80
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
List * refs
Definition: primnodes.h:343
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2974
#define DatumGetObjectId(X)
Definition: postgres.h:506
AttrNumber * grouping_map
Definition: relation.h:287
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define lfirst_int(lc)
Definition: pg_list.h:107
PlannerGlobal * glob
Definition: relation.h:157
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * cols
Definition: primnodes.h:344
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2558
#define Assert(condition)
Definition: c.h:670
List * relationOids
Definition: relation.h:113
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1613
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1624

◆ fix_join_expr()

static List * fix_join_expr ( PlannerInfo root,
List clauses,
indexed_tlist outer_itlist,
indexed_tlist inner_itlist,
Index  acceptable_rel,
int  rtoffset 
)
static

Definition at line 2238 of file setrefs.c.

References fix_join_expr_context::acceptable_rel, fix_join_expr_mutator(), fix_join_expr_context::inner_itlist, fix_join_expr_context::outer_itlist, fix_join_expr_context::root, and fix_join_expr_context::rtoffset.

Referenced by set_join_references(), set_plan_refs(), and set_returning_clause_references().

2244 {
2245  fix_join_expr_context context;
2246 
2247  context.root = root;
2248  context.outer_itlist = outer_itlist;
2249  context.inner_itlist = inner_itlist;
2250  context.acceptable_rel = acceptable_rel;
2251  context.rtoffset = rtoffset;
2252  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2253 }
indexed_tlist * inner_itlist
Definition: setrefs.c:60
Definition: nodes.h:510
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2256
PlannerInfo * root
Definition: setrefs.c:58
indexed_tlist * outer_itlist
Definition: setrefs.c:59
Definition: pg_list.h:45

◆ fix_join_expr_mutator()

static Node * fix_join_expr_mutator ( Node node,
fix_join_expr_context context 
)
static

Definition at line 2256 of file setrefs.c.

References fix_join_expr_context::acceptable_rel, copyVar(), elog, ERROR, expression_tree_mutator(), fix_expr_common(), fix_param_node(), indexed_tlist::has_conv_whole_rows, indexed_tlist::has_non_vars, indexed_tlist::has_ph_vars, fix_join_expr_context::inner_itlist, INNER_VAR, is_converted_whole_row_reference(), IsA, fix_join_expr_context::outer_itlist, OUTER_VAR, PlaceHolderVar::phexpr, fix_join_expr_context::root, fix_join_expr_context::rtoffset, search_indexed_tlist_for_non_var(), search_indexed_tlist_for_var(), Var::varno, and Var::varnoold.

Referenced by fix_join_expr().

2257 {
2258  Var *newvar;
2259  bool converted_whole_row;
2260 
2261  if (node == NULL)
2262  return NULL;
2263  if (IsA(node, Var))
2264  {
2265  Var *var = (Var *) node;
2266 
2267  /* Look for the var in the input tlists, first in the outer */
2268  if (context->outer_itlist)
2269  {
2270  newvar = search_indexed_tlist_for_var(var,
2271  context->outer_itlist,
2272  OUTER_VAR,
2273  context->rtoffset);
2274  if (newvar)
2275  return (Node *) newvar;
2276  }
2277 
2278  /* then in the inner. */
2279  if (context->inner_itlist)
2280  {
2281  newvar = search_indexed_tlist_for_var(var,
2282  context->inner_itlist,
2283  INNER_VAR,
2284  context->rtoffset);
2285  if (newvar)
2286  return (Node *) newvar;
2287  }
2288 
2289  /* If it's for acceptable_rel, adjust and return it */
2290  if (var->varno == context->acceptable_rel)
2291  {
2292  var = copyVar(var);
2293  var->varno += context->rtoffset;
2294  if (var->varnoold > 0)
2295  var->varnoold += context->rtoffset;
2296  return (Node *) var;
2297  }
2298 
2299  /* No referent found for Var */
2300  elog(ERROR, "variable not found in subplan target lists");
2301  }
2302  if (IsA(node, PlaceHolderVar))
2303  {
2304  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2305 
2306  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2307  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2308  {
2309  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2310  context->outer_itlist,
2311  OUTER_VAR);
2312  if (newvar)
2313  return (Node *) newvar;
2314  }
2315  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2316  {
2317  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2318  context->inner_itlist,
2319  INNER_VAR);
2320  if (newvar)
2321  return (Node *) newvar;
2322  }
2323 
2324  /* If not supplied by input plans, evaluate the contained expr */
2325  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2326  }
2327  if (IsA(node, Param))
2328  return fix_param_node(context->root, (Param *) node);
2329 
2330  /* Try matching more complex expressions too, if tlists have any */
2331  converted_whole_row = is_converted_whole_row_reference(node);
2332  if (context->outer_itlist &&
2333  (context->outer_itlist->has_non_vars ||
2334  (context->outer_itlist->has_conv_whole_rows && converted_whole_row)))
2335  {
2336  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2337  context->outer_itlist,
2338  OUTER_VAR);
2339  if (newvar)
2340  return (Node *) newvar;
2341  }
2342  if (context->inner_itlist &&
2343  (context->inner_itlist->has_non_vars ||
2344  (context->inner_itlist->has_conv_whole_rows && converted_whole_row)))
2345  {
2346  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2347  context->inner_itlist,
2348  INNER_VAR);
2349  if (newvar)
2350  return (Node *) newvar;
2351  }
2352  fix_expr_common(context->root, node);
2353  return expression_tree_mutator(node,
2355  (void *) context);
2356 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
indexed_tlist * inner_itlist
Definition: setrefs.c:60
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2409
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1452
Definition: nodes.h:510
Definition: primnodes.h:163
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2256
Index varnoold
Definition: primnodes.h:176
bool has_ph_vars
Definition: setrefs.c:42
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1940
static Var * copyVar(Var *var)
Definition: setrefs.c:1342
PlannerInfo * root
Definition: setrefs.c:58
Index varno
Definition: primnodes.h:166
bool has_non_vars
Definition: setrefs.c:43
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2134
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1364
#define INNER_VAR
Definition: primnodes.h:153
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2094
bool has_conv_whole_rows
Definition: setrefs.c:44
static bool is_converted_whole_row_reference(Node *node)
Definition: setrefs.c:2680
indexed_tlist * outer_itlist
Definition: setrefs.c:59
#define elog
Definition: elog.h:219
#define OUTER_VAR
Definition: primnodes.h:154

◆ fix_param_node()

static Node* fix_param_node ( PlannerInfo root,
Param p 
)
static

Definition at line 1452 of file setrefs.c.

References copyObject, elog, ERROR, list_length(), list_nth(), PlannerInfo::multiexpr_params, PARAM_MULTIEXPR, Param::paramid, and Param::paramkind.

Referenced by fix_join_expr_mutator(), fix_scan_expr_mutator(), and fix_upper_expr_mutator().

1453 {
1454  if (p->paramkind == PARAM_MULTIEXPR)
1455  {
1456  int subqueryid = p->paramid >> 16;
1457  int colno = p->paramid & 0xFFFF;
1458  List *params;
1459 
1460  if (subqueryid <= 0 ||
1461  subqueryid > list_length(root->multiexpr_params))
1462  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1463  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1464  if (colno <= 0 || colno > list_length(params))
1465  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1466  return copyObject(list_nth(params, colno - 1));
1467  }
1468  return (Node *) copyObject(p);
1469 }
ParamKind paramkind
Definition: primnodes.h:244
Definition: nodes.h:510
List * multiexpr_params
Definition: relation.h:232
#define ERROR
Definition: elog.h:43
void * list_nth(const List *list, int n)
Definition: list.c:410
int paramid
Definition: primnodes.h:245
static int list_length(const List *l)
Definition: pg_list.h:89
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:623
Definition: pg_list.h:45

◆ fix_scan_expr()

static Node * fix_scan_expr ( PlannerInfo root,
Node node,
int  rtoffset 
)
static

Definition at line 1482 of file setrefs.c.

References fix_scan_expr_mutator(), fix_scan_expr_walker(), PlannerInfo::glob, PlannerGlobal::lastPHId, PlannerInfo::minmax_aggs, PlannerInfo::multiexpr_params, NIL, fix_scan_expr_context::root, and fix_scan_expr_context::rtoffset.

Referenced by set_plan_refs().

1483 {
1484  fix_scan_expr_context context;
1485 
1486  context.root = root;
1487  context.rtoffset = rtoffset;
1488 
1489  if (rtoffset != 0 ||
1490  root->multiexpr_params != NIL ||
1491  root->glob->lastPHId != 0 ||
1492  root->minmax_aggs != NIL)
1493  {
1494  return fix_scan_expr_mutator(node, &context);
1495  }
1496  else
1497  {
1498  /*
1499  * If rtoffset == 0, we don't need to change any Vars, and if there
1500  * are no MULTIEXPR subqueries then we don't need to replace
1501  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1502  * we won't need to remove them, and if there are no minmax Aggrefs we
1503  * won't need to replace them. Then it's OK to just scribble on the
1504  * input node tree instead of copying (since the only change, filling
1505  * in any unset opfuncid fields, is harmless). This saves just enough
1506  * cycles to be noticeable on trivial queries.
1507  */
1508  (void) fix_scan_expr_walker(node, &context);
1509  return node;
1510  }
1511 }
#define NIL
Definition: pg_list.h:69
PlannerInfo * root
Definition: setrefs.c:52
List * minmax_aggs
Definition: relation.h:288
List * multiexpr_params
Definition: relation.h:232
PlannerGlobal * glob
Definition: relation.h:157
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1583
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1514
Index lastPHId
Definition: relation.h:119

◆ fix_scan_expr_mutator()

static Node * fix_scan_expr_mutator ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1514 of file setrefs.c.

References Aggref::aggfnoid, MinMaxAggInfo::aggfnoid, Aggref::args, Assert, copyObject, copyVar(), CurrentOfExpr::cvarno, equal(), TargetEntry::expr, expression_tree_mutator(), fix_expr_common(), fix_param_node(), INNER_VAR, IS_SPECIAL_VARNO, IsA, lfirst, linitial, list_length(), PlannerInfo::minmax_aggs, NIL, OUTER_VAR, MinMaxAggInfo::param, PlaceHolderVar::phexpr, fix_scan_expr_context::root, fix_scan_expr_context::rtoffset, MinMaxAggInfo::target, Var::varlevelsup, Var::varno, and Var::varnoold.

Referenced by fix_scan_expr().

1515 {
1516  if (node == NULL)
1517  return NULL;
1518  if (IsA(node, Var))
1519  {
1520  Var *var = copyVar((Var *) node);
1521 
1522  Assert(var->varlevelsup == 0);
1523 
1524  /*
1525  * We should not see any Vars marked INNER_VAR or OUTER_VAR. But an
1526  * indexqual expression could contain INDEX_VAR Vars.
1527  */
1528  Assert(var->varno != INNER_VAR);
1529  Assert(var->varno != OUTER_VAR);
1530  if (!IS_SPECIAL_VARNO(var->varno))
1531  var->varno += context->rtoffset;
1532  if (var->varnoold > 0)
1533  var->varnoold += context->rtoffset;
1534  return (Node *) var;
1535  }
1536  if (IsA(node, Param))
1537  return fix_param_node(context->root, (Param *) node);
1538  if (IsA(node, Aggref))
1539  {
1540  Aggref *aggref = (Aggref *) node;
1541 
1542  /* See if the Aggref should be replaced by a Param */
1543  if (context->root->minmax_aggs != NIL &&
1544  list_length(aggref->args) == 1)
1545  {
1546  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1547  ListCell *lc;
1548 
1549  foreach(lc, context->root->minmax_aggs)
1550  {
1551  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1552 
1553  if (mminfo->aggfnoid == aggref->aggfnoid &&
1554  equal(mminfo->target, curTarget->expr))
1555  return (Node *) copyObject(mminfo->param);
1556  }
1557  }
1558  /* If no match, just fall through to process it normally */
1559  }
1560  if (IsA(node, CurrentOfExpr))
1561  {
1562  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1563 
1564  Assert(cexpr->cvarno != INNER_VAR);
1565  Assert(cexpr->cvarno != OUTER_VAR);
1566  if (!IS_SPECIAL_VARNO(cexpr->cvarno))
1567  cexpr->cvarno += context->rtoffset;
1568  return (Node *) cexpr;
1569  }
1570  if (IsA(node, PlaceHolderVar))
1571  {
1572  /* At scan level, we should always just evaluate the contained expr */
1573  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1574 
1575  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1576  }
1577  fix_expr_common(context->root, node);
1579  (void *) context);
1580 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Index varlevelsup
Definition: primnodes.h:173
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2409
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1452
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2974
Param * param
Definition: relation.h:2175
PlannerInfo * root
Definition: setrefs.c:52
Definition: nodes.h:510
List * args
Definition: primnodes.h:301
List * minmax_aggs
Definition: relation.h:288
Definition: primnodes.h:163
Index varnoold
Definition: primnodes.h:176
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:157
#define linitial(l)
Definition: pg_list.h:111
Expr * phexpr
Definition: relation.h:1940
static Var * copyVar(Var *var)
Definition: setrefs.c:1342
Index varno
Definition: primnodes.h:166
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1514
Oid aggfnoid
Definition: primnodes.h:294
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1364
#define INNER_VAR
Definition: primnodes.h:153
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Expr * target
Definition: relation.h:2171
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
#define copyObject(obj)
Definition: nodes.h:623
#define OUTER_VAR
Definition: primnodes.h:154

◆ fix_scan_expr_walker()

static bool fix_scan_expr_walker ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1583 of file setrefs.c.

References Assert, expression_tree_walker(), fix_expr_common(), IsA, and fix_scan_expr_context::root.

Referenced by fix_scan_expr().

1584 {
1585  if (node == NULL)
1586  return false;
1587  Assert(!IsA(node, PlaceHolderVar));
1588  fix_expr_common(context->root, node);
1590  (void *) context);
1591 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
PlannerInfo * root
Definition: setrefs.c:52
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1583
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1364
#define Assert(condition)
Definition: c.h:670
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1834

◆ fix_upper_expr()

static Node * fix_upper_expr ( PlannerInfo root,
Node node,
indexed_tlist subplan_itlist,
Index  newvarno,
int  rtoffset 
)
static

Definition at line 2389 of file setrefs.c.

References fix_upper_expr_mutator(), fix_upper_expr_context::newvarno, fix_upper_expr_context::root, fix_upper_expr_context::rtoffset, and fix_upper_expr_context::subplan_itlist.

Referenced by set_customscan_references(), set_foreignscan_references(), set_indexonlyscan_references(), set_join_references(), and set_upper_references().

2394 {
2395  fix_upper_expr_context context;
2396 
2397  context.root = root;
2398  context.subplan_itlist = subplan_itlist;
2399  context.newvarno = newvarno;
2400  context.rtoffset = rtoffset;
2401  return fix_upper_expr_mutator(node, &context);
2402 }
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2405
PlannerInfo * root
Definition: setrefs.c:67
indexed_tlist * subplan_itlist
Definition: setrefs.c:68

◆ fix_upper_expr_mutator()

static Node * fix_upper_expr_mutator ( Node node,
fix_upper_expr_context context 
)
static

Definition at line 2405 of file setrefs.c.

References Aggref::aggfnoid, MinMaxAggInfo::aggfnoid, Aggref::args, copyObject, elog, equal(), ERROR, TargetEntry::expr, expression_tree_mutator(), fix_expr_common(), fix_param_node(), indexed_tlist::has_conv_whole_rows, indexed_tlist::has_non_vars, indexed_tlist::has_ph_vars, is_converted_whole_row_reference(), IsA, lfirst, linitial, list_length(), PlannerInfo::minmax_aggs, fix_upper_expr_context::newvarno, NIL, MinMaxAggInfo::param, PlaceHolderVar::phexpr, fix_upper_expr_context::root, fix_upper_expr_context::rtoffset, search_indexed_tlist_for_non_var(), search_indexed_tlist_for_var(), fix_upper_expr_context::subplan_itlist, and MinMaxAggInfo::target.

Referenced by fix_upper_expr().

2406 {
2407  Var *newvar;
2408 
2409  if (node == NULL)
2410  return NULL;
2411  if (IsA(node, Var))
2412  {
2413  Var *var = (Var *) node;
2414 
2415  newvar = search_indexed_tlist_for_var(var,
2416  context->subplan_itlist,
2417  context->newvarno,
2418  context->rtoffset);
2419  if (!newvar)
2420  elog(ERROR, "variable not found in subplan target list");
2421  return (Node *) newvar;
2422  }
2423  if (IsA(node, PlaceHolderVar))
2424  {
2425  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2426 
2427  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2428  if (context->subplan_itlist->has_ph_vars)
2429  {
2430  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2431  context->subplan_itlist,
2432  context->newvarno);
2433  if (newvar)
2434  return (Node *) newvar;
2435  }
2436  /* If not supplied by input plan, evaluate the contained expr */
2437  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2438  }
2439  if (IsA(node, Param))
2440  return fix_param_node(context->root, (Param *) node);
2441  if (IsA(node, Aggref))
2442  {
2443  Aggref *aggref = (Aggref *) node;
2444 
2445  /* See if the Aggref should be replaced by a Param */
2446  if (context->root->minmax_aggs != NIL &&
2447  list_length(aggref->args) == 1)
2448  {
2449  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2450  ListCell *lc;
2451 
2452  foreach(lc, context->root->minmax_aggs)
2453  {
2454  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2455 
2456  if (mminfo->aggfnoid == aggref->aggfnoid &&
2457  equal(mminfo->target, curTarget->expr))
2458  return (Node *) copyObject(mminfo->param);
2459  }
2460  }
2461  /* If no match, just fall through to process it normally */
2462  }
2463  /* Try matching more complex expressions too, if tlist has any */
2464  if (context->subplan_itlist->has_non_vars ||
2465  (context->subplan_itlist->has_conv_whole_rows &&
2467  {
2468  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2469  context->subplan_itlist,
2470  context->newvarno);
2471  if (newvar)
2472  return (Node *) newvar;
2473  }
2474  fix_expr_common(context->root, node);
2475  return expression_tree_mutator(node,
2477  (void *) context);
2478 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2409
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1452
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2974
Param * param
Definition: relation.h:2175
Definition: nodes.h:510
List * args
Definition: primnodes.h:301
List * minmax_aggs
Definition: relation.h:288
Definition: primnodes.h:163
bool has_ph_vars
Definition: setrefs.c:42
#define linitial(l)
Definition: pg_list.h:111
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1940
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2405
bool has_non_vars
Definition: setrefs.c:43
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2134
Oid aggfnoid
Definition: primnodes.h:294
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1364
#define lfirst(lc)
Definition: pg_list.h:106
Expr * target
Definition: relation.h:2171
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2094
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
bool has_conv_whole_rows
Definition: setrefs.c:44
static bool is_converted_whole_row_reference(Node *node)
Definition: setrefs.c:2680
PlannerInfo * root
Definition: setrefs.c:67
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:623
indexed_tlist * subplan_itlist
Definition: setrefs.c:68

◆ flatten_rtes_walker()

static bool flatten_rtes_walker ( Node node,
PlannerGlobal glob 
)
static

Definition at line 352 of file setrefs.c.

References add_rte_to_flat_rtable(), expression_tree_walker(), IsA, QTW_EXAMINE_RTES, query_tree_walker(), RTE_RELATION, and RangeTblEntry::rtekind.

Referenced by flatten_unplanned_rtes().

353 {
354  if (node == NULL)
355  return false;
356  if (IsA(node, RangeTblEntry))
357  {
358  RangeTblEntry *rte = (RangeTblEntry *) node;
359 
360  /* As above, we need only save relation RTEs */
361  if (rte->rtekind == RTE_RELATION)
362  add_rte_to_flat_rtable(glob, rte);
363  return false;
364  }
365  if (IsA(node, Query))
366  {
367  /* Recurse into subselects */
368  return query_tree_walker((Query *) node,
370  (void *) glob,
372  }
374  (void *) glob);
375 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2245
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:388
#define QTW_EXAMINE_RTES
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:352
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1834
RTEKind rtekind
Definition: parsenodes.h:951

◆ flatten_unplanned_rtes()

static void flatten_unplanned_rtes ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 342 of file setrefs.c.

References flatten_rtes_walker(), QTW_EXAMINE_RTES, query_tree_walker(), and RangeTblEntry::subquery.

Referenced by add_rtes_to_flat_rtable().

343 {
344  /* Use query_tree_walker to find all RTEs in the parse tree */
345  (void) query_tree_walker(rte->subquery,
347  (void *) glob,
349 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2245
#define QTW_EXAMINE_RTES
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:352
Query * subquery
Definition: parsenodes.h:974

◆ is_converted_whole_row_reference()

static bool is_converted_whole_row_reference ( Node node)
static

Definition at line 2680 of file setrefs.c.

References ConvertRowtypeExpr::arg, castNode, COERCE_IMPLICIT_CAST, ConvertRowtypeExpr::convertformat, IsA, and Var::varattno.

Referenced by build_tlist_index(), fix_join_expr_mutator(), and fix_upper_expr_mutator().

2681 {
2682  ConvertRowtypeExpr *convexpr;
2683 
2684  if (!node || !IsA(node, ConvertRowtypeExpr))
2685  return false;
2686 
2687  /* Traverse nested ConvertRowtypeExpr's. */
2688  convexpr = castNode(ConvertRowtypeExpr, node);
2689  while (convexpr->convertformat == COERCE_IMPLICIT_CAST &&
2690  IsA(convexpr->arg, ConvertRowtypeExpr))
2691  convexpr = castNode(ConvertRowtypeExpr, convexpr->arg);
2692 
2693  if (IsA(convexpr->arg, Var))
2694  {
2695  Var *var = castNode(Var, convexpr->arg);
2696 
2697  if (var->varattno == 0)
2698  return true;
2699  }
2700 
2701  return false;
2702 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
CoercionForm convertformat
Definition: primnodes.h:866

◆ record_plan_function_dependency()

void record_plan_function_dependency ( PlannerInfo root,
Oid  funcid 
)

Definition at line 2558 of file setrefs.c.

References PlanInvalItem::cacheId, FirstBootstrapObjectId, GetSysCacheHashValue1, PlannerInfo::glob, PlanInvalItem::hashValue, PlannerGlobal::invalItems, lappend(), makeNode, ObjectIdGetDatum, and PROCOID.

Referenced by fix_expr_common(), inline_function(), and inline_set_returning_function().

2559 {
2560  /*
2561  * For performance reasons, we don't bother to track built-in functions;
2562  * we just assume they'll never change (or at least not in ways that'd
2563  * invalidate plans using them). For this purpose we can consider a
2564  * built-in function to be one with OID less than FirstBootstrapObjectId.
2565  * Note that the OID generator guarantees never to generate such an OID
2566  * after startup, even at OID wraparound.
2567  */
2568  if (funcid >= (Oid) FirstBootstrapObjectId)
2569  {
2570  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2571 
2572  /*
2573  * It would work to use any syscache on pg_proc, but the easiest is
2574  * PROCOID since we already have the function's OID at hand. Note
2575  * that plancache.c knows we use PROCOID.
2576  */
2577  inval_item->cacheId = PROCOID;
2578  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2579  ObjectIdGetDatum(funcid));
2580 
2581  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2582  }
2583 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:200
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:513
PlannerGlobal * glob
Definition: relation.h:157
#define FirstBootstrapObjectId
Definition: transam.h:93
List * lappend(List *list, void *datum)
Definition: list.c:128
List * invalItems
Definition: relation.h:115
uint32 hashValue
Definition: plannodes.h:1041
#define makeNode(_type_)
Definition: nodes.h:558

◆ search_indexed_tlist_for_non_var()

static Var * search_indexed_tlist_for_non_var ( Expr node,
indexed_tlist itlist,
Index  newvarno 
)
static

Definition at line 2134 of file setrefs.c.

References IsA, makeVarFromTargetEntry(), indexed_tlist::tlist, tlist_member(), Var::varnoold, and Var::varoattno.

Referenced by fix_join_expr_mutator(), and fix_upper_expr_mutator().

2136 {
2137  TargetEntry *tle;
2138 
2139  /*
2140  * If it's a simple Const, replacing it with a Var is silly, even if there
2141  * happens to be an identical Const below; a Var is more expensive to
2142  * execute than a Const. What's more, replacing it could confuse some
2143  * places in the executor that expect to see simple Consts for, eg,
2144  * dropped columns.
2145  */
2146  if (IsA(node, Const))
2147  return NULL;
2148 
2149  tle = tlist_member(node, itlist->tlist);
2150  if (tle)
2151  {
2152  /* Found a matching subplan output expression */
2153  Var *newvar;
2154 
2155  newvar = makeVarFromTargetEntry(newvarno, tle);
2156  newvar->varnoold = 0; /* wasn't ever a plain Var */
2157  newvar->varoattno = 0;
2158  return newvar;
2159  }
2160  return NULL; /* no match */
2161 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:104
Definition: primnodes.h:163
Index varnoold
Definition: primnodes.h:176
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:54
AttrNumber varoattno
Definition: primnodes.h:177
List * tlist
Definition: setrefs.c:40

◆ search_indexed_tlist_for_sortgroupref()

static Var * search_indexed_tlist_for_sortgroupref ( Expr node,
Index  sortgroupref,
indexed_tlist itlist,
Index  newvarno 
)
static

Definition at line 2174 of file setrefs.c.

References equal(), TargetEntry::expr, lfirst, makeVarFromTargetEntry(), TargetEntry::ressortgroupref, indexed_tlist::tlist, Var::varnoold, and Var::varoattno.

Referenced by set_upper_references().

2178 {
2179  ListCell *lc;
2180 
2181  foreach(lc, itlist->tlist)
2182  {
2183  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2184 
2185  /* The equal() check should be redundant, but let's be paranoid */
2186  if (tle->ressortgroupref == sortgroupref &&
2187  equal(node, tle->expr))
2188  {
2189  /* Found a matching subplan output expression */
2190  Var *newvar;
2191 
2192  newvar = makeVarFromTargetEntry(newvarno, tle);
2193  newvar->varnoold = 0; /* wasn't ever a plain Var */
2194  newvar->varoattno = 0;
2195  return newvar;
2196  }
2197  }
2198  return NULL; /* no match */
2199 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2974
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:104
Definition: primnodes.h:163
Index varnoold
Definition: primnodes.h:176
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
AttrNumber varoattno
Definition: primnodes.h:177
Index ressortgroupref
Definition: primnodes.h:1378
List * tlist
Definition: setrefs.c:40

◆ search_indexed_tlist_for_var()

static Var * search_indexed_tlist_for_var ( Var var,
indexed_tlist itlist,
Index  newvarno,
int  rtoffset 
)
static

Definition at line 2094 of file setrefs.c.

References copyVar(), i, indexed_tlist::num_vars, tlist_vinfo::resno, tlist_vinfo::varattno, Var::varattno, tlist_vinfo::varno, Var::varno, Var::varnoold, and indexed_tlist::vars.

Referenced by fix_join_expr_mutator(), and fix_upper_expr_mutator().

2096 {
2097  Index varno = var->varno;
2098  AttrNumber varattno = var->varattno;
2099  tlist_vinfo *vinfo;
2100  int i;
2101 
2102  vinfo = itlist->vars;
2103  i = itlist->num_vars;
2104  while (i-- > 0)
2105  {
2106  if (vinfo->varno == varno && vinfo->varattno == varattno)
2107  {
2108  /* Found a match */
2109  Var *newvar = copyVar(var);
2110 
2111  newvar->varno = newvarno;
2112  newvar->varattno = vinfo->resno;
2113  if (newvar->varnoold > 0)
2114  newvar->varnoold += rtoffset;
2115  return newvar;
2116  }
2117  vinfo++;
2118  }
2119  return NULL; /* no match */
2120 }
Index varno
Definition: setrefs.c:33
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:47
AttrNumber resno
Definition: setrefs.c:35
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
AttrNumber varattno
Definition: setrefs.c:34
Index varnoold
Definition: primnodes.h:176
int num_vars
Definition: setrefs.c:41
static Var * copyVar(Var *var)
Definition: setrefs.c:1342
Index varno
Definition: primnodes.h:166
unsigned int Index
Definition: c.h:413
int i
int16 AttrNumber
Definition: attnum.h:21

◆ set_customscan_references()

static void set_customscan_references ( PlannerInfo root,
CustomScan cscan,
int  rtoffset 
)
static

Definition at line 1267 of file setrefs.c.

References bms_add_member(), bms_next_member(), build_tlist_index(), CustomScan::custom_exprs, CustomScan::custom_plans, CustomScan::custom_relids, CustomScan::custom_scan_tlist, fix_scan_list, fix_upper_expr(), INDEX_VAR, lfirst, NIL, pfree(), Scan::plan, Plan::qual, CustomScan::scan, Scan::scanrelid, set_plan_refs(), and Plan::targetlist.

Referenced by set_plan_refs().

1270 {
1271  ListCell *lc;
1272 
1273  /* Adjust scanrelid if it's valid */
1274  if (cscan->scan.scanrelid > 0)
1275  cscan->scan.scanrelid += rtoffset;
1276 
1277  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1278  {
1279  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1281 
1282  cscan->scan.plan.targetlist = (List *)
1283  fix_upper_expr(root,
1284  (Node *) cscan->scan.plan.targetlist,
1285  itlist,
1286  INDEX_VAR,
1287  rtoffset);
1288  cscan->scan.plan.qual = (List *)
1289  fix_upper_expr(root,
1290  (Node *) cscan->scan.plan.qual,
1291  itlist,
1292  INDEX_VAR,
1293  rtoffset);
1294  cscan->custom_exprs = (List *)
1295  fix_upper_expr(root,
1296  (Node *) cscan->custom_exprs,
1297  itlist,
1298  INDEX_VAR,
1299  rtoffset);
1300  pfree(itlist);
1301  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1302  cscan->custom_scan_tlist =
1303  fix_scan_list(root, cscan->custom_scan_tlist, rtoffset);
1304  }
1305  else
1306  {
1307  /* Adjust tlist, qual, custom_exprs in the standard way */
1308  cscan->scan.plan.targetlist =
1309  fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
1310  cscan->scan.plan.qual =
1311  fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
1312  cscan->custom_exprs =
1313  fix_scan_list(root, cscan->custom_exprs, rtoffset);
1314  }
1315 
1316  /* Adjust child plan-nodes recursively, if needed */
1317  foreach(lc, cscan->custom_plans)
1318  {
1319  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1320  }
1321 
1322  /* Adjust custom_relids if needed */
1323  if (rtoffset > 0)
1324  {
1325  Bitmapset *tempset = NULL;
1326  int x = -1;
1327 
1328  while ((x = bms_next_member(cscan->custom_relids, x)) >= 0)
1329  tempset = bms_add_member(tempset, x + rtoffset);
1330  cscan->custom_relids = tempset;
1331  }
1332 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
Index scanrelid
Definition: plannodes.h:329
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:937
Definition: nodes.h:510
List * custom_exprs
Definition: plannodes.h:629
List * custom_plans
Definition: plannodes.h:628
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:439
void pfree(void *pointer)
Definition: mcxt.c:949
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2389
Scan scan
Definition: plannodes.h:625
#define lfirst(lc)
Definition: pg_list.h:106
List * custom_scan_tlist
Definition: plannodes.h:631
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
Bitmapset * custom_relids
Definition: plannodes.h:632
List * targetlist
Definition: plannodes.h:144
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:84

◆ set_dummy_tlist_references()

static void set_dummy_tlist_references ( Plan plan,
int  rtoffset 
)
static

Definition at line 1920 of file setrefs.c.

References TargetEntry::expr, exprCollation(), exprType(), exprTypmod(), flatCopyTargetEntry(), IsA, lappend(), lfirst, makeVar(), NIL, OUTER_VAR, TargetEntry::resno, and Plan::targetlist.

Referenced by set_plan_refs().

1921 {
1922  List *output_targetlist;
1923  ListCell *l;
1924 
1925  output_targetlist = NIL;
1926  foreach(l, plan->targetlist)
1927  {
1928  TargetEntry *tle = (TargetEntry *) lfirst(l);
1929  Var *oldvar = (Var *) tle->expr;
1930  Var *newvar;
1931 
1932  /*
1933  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
1934  * as Consts, not Vars referencing Consts. Here, there's no speed
1935  * advantage to be had, but it makes EXPLAIN output look cleaner, and
1936  * again it avoids confusing the executor.
1937  */
1938  if (IsA(oldvar, Const))
1939  {
1940  /* just reuse the existing TLE node */
1941  output_targetlist = lappend(output_targetlist, tle);
1942  continue;
1943  }
1944 
1945  newvar = makeVar(OUTER_VAR,
1946  tle->resno,
1947  exprType((Node *) oldvar),
1948  exprTypmod((Node *) oldvar),
1949  exprCollation((Node *) oldvar),
1950  0);
1951  if (IsA(oldvar, Var))
1952  {
1953  newvar->varnoold = oldvar->varno + rtoffset;
1954  newvar->varoattno = oldvar->varattno;
1955  }
1956  else
1957  {
1958  newvar->varnoold = 0; /* wasn't ever a plain Var */
1959  newvar->varoattno = 0;
1960  }
1961 
1962  tle = flatCopyTargetEntry(tle);
1963  tle->expr = (Expr *) newvar;
1964  output_targetlist = lappend(output_targetlist, tle);
1965  }
1966  plan->targetlist = output_targetlist;
1967 
1968  /* We don't touch plan->qual here */
1969 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:276
Definition: nodes.h:510
Definition: primnodes.h:163
AttrNumber resno
Definition: primnodes.h:1376
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:270
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
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:720
List * targetlist
Definition: plannodes.h:144
Definition: pg_list.h:45
#define OUTER_VAR
Definition: primnodes.h:154

◆ set_foreignscan_references()

static void set_foreignscan_references ( PlannerInfo root,
ForeignScan fscan,
int  rtoffset 
)
static

Definition at line 1189 of file setrefs.c.

References bms_add_member(), bms_next_member(), build_tlist_index(), ForeignScan::fdw_exprs, ForeignScan::fdw_recheck_quals, ForeignScan::fdw_scan_tlist, fix_scan_list, fix_upper_expr(), ForeignScan::fs_relids, INDEX_VAR, NIL, pfree(), Scan::plan, Plan::qual, ForeignScan::scan, Scan::scanrelid, and Plan::targetlist.

Referenced by set_plan_refs().

1192 {
1193  /* Adjust scanrelid if it's valid */
1194  if (fscan->scan.scanrelid > 0)
1195  fscan->scan.scanrelid += rtoffset;
1196 
1197  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1198  {
1199  /*
1200  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1201  * foreign scan tuple
1202  */
1204 
1205  fscan->scan.plan.targetlist = (List *)
1206  fix_upper_expr(root,
1207  (Node *) fscan->scan.plan.targetlist,
1208  itlist,
1209  INDEX_VAR,
1210  rtoffset);
1211  fscan->scan.plan.qual = (List *)
1212  fix_upper_expr(root,
1213  (Node *) fscan->scan.plan.qual,
1214  itlist,
1215  INDEX_VAR,
1216  rtoffset);
1217  fscan->fdw_exprs = (List *)
1218  fix_upper_expr(root,
1219  (Node *) fscan->fdw_exprs,
1220  itlist,
1221  INDEX_VAR,
1222  rtoffset);
1223  fscan->fdw_recheck_quals = (List *)
1224  fix_upper_expr(root,
1225  (Node *) fscan->fdw_recheck_quals,
1226  itlist,
1227  INDEX_VAR,
1228  rtoffset);
1229  pfree(itlist);
1230  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1231  fscan->fdw_scan_tlist =
1232  fix_scan_list(root, fscan->fdw_scan_tlist, rtoffset);
1233  }
1234  else
1235  {
1236  /*
1237  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1238  * way
1239  */
1240  fscan->scan.plan.targetlist =
1241  fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset);
1242  fscan->scan.plan.qual =
1243  fix_scan_list(root, fscan->scan.plan.qual, rtoffset);
1244  fscan->fdw_exprs =
1245  fix_scan_list(root, fscan->fdw_exprs, rtoffset);
1246  fscan->fdw_recheck_quals =
1247  fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
1248  }
1249 
1250  /* Adjust fs_relids if needed */
1251  if (rtoffset > 0)
1252  {
1253  Bitmapset *tempset = NULL;
1254  int x = -1;
1255 
1256  while ((x = bms_next_member(fscan->fs_relids, x)) >= 0)
1257  tempset = bms_add_member(tempset, x + rtoffset);
1258  fscan->fs_relids = tempset;
1259  }
1260 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
Index scanrelid
Definition: plannodes.h:329
List * fdw_exprs
Definition: plannodes.h:600
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:937
Definition: nodes.h:510
List * fdw_scan_tlist
Definition: plannodes.h:602
void pfree(void *pointer)
Definition: mcxt.c:949
List * fdw_recheck_quals
Definition: plannodes.h:603
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2389
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
List * targetlist
Definition: plannodes.h:144
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:84
Bitmapset * fs_relids
Definition: plannodes.h:604

◆ set_indexonlyscan_references()

static Plan * set_indexonlyscan_references ( PlannerInfo root,
IndexOnlyScan plan,
int  rtoffset 
)
static

Definition at line 1021 of file setrefs.c.

References build_tlist_index(), fix_scan_list, fix_upper_expr(), INDEX_VAR, IndexOnlyScan::indexorderby, IndexOnlyScan::indexqual, IndexOnlyScan::indextlist, pfree(), Scan::plan, Plan::qual, IndexOnlyScan::scan, Scan::scanrelid, and Plan::targetlist.

Referenced by set_plan_refs().

1024 {
1025  indexed_tlist *index_itlist;
1026 
1027  index_itlist = build_tlist_index(plan->indextlist);
1028 
1029  plan->scan.scanrelid += rtoffset;
1030  plan->scan.plan.targetlist = (List *)
1031  fix_upper_expr(root,
1032  (Node *) plan->scan.plan.targetlist,
1033  index_itlist,
1034  INDEX_VAR,
1035  rtoffset);
1036  plan->scan.plan.qual = (List *)
1037  fix_upper_expr(root,
1038  (Node *) plan->scan.plan.qual,
1039  index_itlist,
1040  INDEX_VAR,
1041  rtoffset);
1042  /* indexqual is already transformed to reference index columns */
1043  plan->indexqual = fix_scan_list(root, plan->indexqual, rtoffset);
1044  /* indexorderby is already transformed to reference index columns */
1045  plan->indexorderby = fix_scan_list(root, plan->indexorderby, rtoffset);
1046  /* indextlist must NOT be transformed to reference index columns */
1047  plan->indextlist = fix_scan_list(root, plan->indextlist, rtoffset);
1048 
1049  pfree(index_itlist);
1050 
1051  return (Plan *) plan;
1052 }
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
Index scanrelid
Definition: plannodes.h:329
Definition: nodes.h:510
void pfree(void *pointer)
Definition: mcxt.c:949
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2389
List * indextlist
Definition: plannodes.h:421
List * indexorderby
Definition: plannodes.h:420
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
List * indexqual
Definition: plannodes.h:419
List * targetlist
Definition: plannodes.h:144
#define INDEX_VAR
Definition: primnodes.h:155
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:84

◆ set_join_references()

static void set_join_references ( PlannerInfo root,
Join join,
int  rtoffset 
)
static

Definition at line 1602 of file setrefs.c.

References build_tlist_index(), elog, ERROR, fix_join_expr(), fix_upper_expr(), indexed_tlist::has_non_vars, HashJoin::hashclauses, IsA, JOIN_ANTI, JOIN_FULL, JOIN_LEFT, JOIN_RIGHT, JOIN_SEMI, Join::joinqual, Join::jointype, Plan::lefttree, lfirst, MergeJoin::mergeclauses, NestLoop::nestParams, OUTER_VAR, NestLoopParam::paramval, pfree(), Join::plan, Plan::qual, Plan::righttree, Plan::targetlist, and Var::varno.

Referenced by set_plan_refs().

1603 {
1604  Plan *outer_plan = join->plan.lefttree;
1605  Plan *inner_plan = join->plan.righttree;
1606  indexed_tlist *outer_itlist;
1607  indexed_tlist *inner_itlist;
1608 
1609  outer_itlist = build_tlist_index(outer_plan->targetlist);
1610  inner_itlist = build_tlist_index(inner_plan->targetlist);
1611 
1612  /*
1613  * First process the joinquals (including merge or hash clauses). These
1614  * are logically below the join so they can always use all values
1615  * available from the input tlists. It's okay to also handle
1616  * NestLoopParams now, because those couldn't refer to nullable
1617  * subexpressions.
1618  */
1619  join->joinqual = fix_join_expr(root,
1620  join->joinqual,
1621  outer_itlist,
1622  inner_itlist,
1623  (Index) 0,
1624  rtoffset);
1625 
1626  /* Now do join-type-specific stuff */
1627  if (IsA(join, NestLoop))
1628  {
1629  NestLoop *nl = (NestLoop *) join;
1630  ListCell *lc;
1631 
1632  foreach(lc, nl->nestParams)
1633  {
1634  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1635 
1636  nlp->paramval = (Var *) fix_upper_expr(root,
1637  (Node *) nlp->paramval,
1638  outer_itlist,
1639  OUTER_VAR,
1640  rtoffset);
1641  /* Check we replaced any PlaceHolderVar with simple Var */
1642  if (!(IsA(nlp->paramval, Var) &&
1643  nlp->paramval->varno == OUTER_VAR))
1644  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
1645  }
1646  }
1647  else if (IsA(join, MergeJoin))
1648  {
1649  MergeJoin *mj = (MergeJoin *) join;
1650 
1651  mj->mergeclauses = fix_join_expr(root,
1652  mj->mergeclauses,
1653  outer_itlist,
1654  inner_itlist,
1655  (Index) 0,
1656  rtoffset);
1657  }
1658  else if (IsA(join, HashJoin))
1659  {
1660  HashJoin *hj = (HashJoin *) join;
1661 
1662  hj->hashclauses = fix_join_expr(root,
1663  hj->hashclauses,
1664  outer_itlist,
1665  inner_itlist,
1666  (Index) 0,
1667  rtoffset);
1668  }
1669 
1670  /*
1671  * Now we need to fix up the targetlist and qpqual, which are logically
1672  * above the join. This means they should not re-use any input expression
1673  * that was computed in the nullable side of an outer join. Vars and
1674  * PlaceHolderVars are fine, so we can implement this restriction just by
1675  * clearing has_non_vars in the indexed_tlist structs.
1676  *
1677  * XXX This is a grotty workaround for the fact that we don't clearly
1678  * distinguish between a Var appearing below an outer join and the "same"
1679  * Var appearing above it. If we did, we'd not need to hack the matching
1680  * rules this way.
1681  */
1682  switch (join->jointype)
1683  {
1684  case JOIN_LEFT:
1685  case JOIN_SEMI:
1686  case JOIN_ANTI:
1687  inner_itlist->has_non_vars = false;
1688  break;
1689  case JOIN_RIGHT:
1690  outer_itlist->has_non_vars = false;
1691  break;
1692  case JOIN_FULL:
1693  outer_itlist->has_non_vars = false;
1694  inner_itlist->has_non_vars = false;
1695  break;
1696  default:
1697  break;
1698  }
1699 
1700  join->plan.targetlist = fix_join_expr(root,
1701  join->plan.targetlist,
1702  outer_itlist,
1703  inner_itlist,
1704  (Index) 0,
1705  rtoffset);
1706  join->plan.qual = fix_join_expr(root,
1707  join->plan.qual,
1708  outer_itlist,
1709  inner_itlist,
1710  (Index) 0,
1711  rtoffset);
1712 
1713  pfree(outer_itlist);
1714  pfree(inner_itlist);
1715 }
List * qual
Definition: plannodes.h:145
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
List * nestParams
Definition: plannodes.h:686
List * hashclauses
Definition: plannodes.h:726
Definition: nodes.h:510
Definition: primnodes.h:163
List * mergeclauses
Definition: plannodes.h:711
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset)
Definition: setrefs.c:2238
JoinType jointype
Definition: plannodes.h:667
struct Plan * righttree
Definition: plannodes.h:147
void pfree(void *pointer)
Definition: mcxt.c:949
Var * paramval
Definition: plannodes.h:693
#define ERROR
Definition: elog.h:43
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2389
Index varno
Definition: primnodes.h:166
bool has_non_vars
Definition: setrefs.c:43
unsigned int Index
Definition: c.h:413
#define lfirst(lc)
Definition: pg_list.h:106
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
struct Plan * lefttree
Definition: plannodes.h:146
List * targetlist
Definition: plannodes.h:144
#define elog
Definition: elog.h:219
#define OUTER_VAR
Definition: primnodes.h:154
List * joinqual
Definition: plannodes.h:669
Plan plan
Definition: plannodes.h:666

◆ set_param_references()

static void set_param_references ( PlannerInfo root,
Plan plan 
)
static

Definition at line 1796 of file setrefs.c.

References Assert, bms_add_member(), bms_intersect(), Plan::extParam, PlannerInfo::init_plans, IsA, Plan::lefttree, lfirst, lfirst_int, PlannerInfo::parent_root, and SubPlan::setParam.

Referenced by set_plan_refs().

1797 {
1798  Assert(IsA(plan, Gather) || IsA(plan, GatherMerge));
1799 
1800  if (plan->lefttree->extParam)
1801  {
1802  PlannerInfo *proot;
1803  Bitmapset *initSetParam = NULL;
1804  ListCell *l;
1805 
1806  for (proot = root; proot != NULL; proot = proot->parent_root)
1807  {
1808  foreach(l, proot->init_plans)
1809  {
1810  SubPlan *initsubplan = (SubPlan *) lfirst(l);
1811  ListCell *l2;
1812 
1813  foreach(l2, initsubplan->setParam)
1814  {
1815  initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
1816  }
1817  }
1818  }
1819 
1820  /*
1821  * Remember the list of all external initplan params that are used by
1822  * the children of Gather or Gather merge node.
1823  */
1824  if (IsA(plan, Gather))
1825  ((Gather *) plan)->initParam =
1826  bms_intersect(plan->lefttree->extParam, initSetParam);
1827  else
1828  ((GatherMerge *) plan)->initParam =
1829  bms_intersect(plan->lefttree->extParam, initSetParam);
1830  }
1831 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
#define lfirst_int(lc)
Definition: pg_list.h:107
struct PlannerInfo * parent_root
Definition: relation.h:161
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:252
List * init_plans
Definition: relation.h:228
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
List * setParam
Definition: primnodes.h:707
Bitmapset * extParam
Definition: plannodes.h:162
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:698
struct Plan * lefttree
Definition: plannodes.h:146

◆ set_plan_references()

Plan* set_plan_references ( PlannerInfo root,
Plan plan 
)

Definition at line 214 of file setrefs.c.

References add_rtes_to_flat_rtable(), PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerInfo::glob, lappend(), lfirst_node, list_length(), palloc(), PlanRowMark::prti, PlannerInfo::rowMarks, PlanRowMark::rti, and set_plan_refs().

Referenced by set_subqueryscan_references(), and standard_planner().

215 {
216  PlannerGlobal *glob = root->glob;
217  int rtoffset = list_length(glob->finalrtable);
218  ListCell *lc;
219 
220  /*
221  * Add all the query's RTEs to the flattened rangetable. The live ones
222  * will have their rangetable indexes increased by rtoffset. (Additional
223  * RTEs, not referenced by the Plan tree, might get added after those.)
224  */
225  add_rtes_to_flat_rtable(root, false);
226 
227  /*
228  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
229  */
230  foreach(lc, root->rowMarks)
231  {
233  PlanRowMark *newrc;
234 
235  /* flat copy is enough since all fields are scalars */
236  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
237  memcpy(newrc, rc, sizeof(PlanRowMark));
238 
239  /* adjust indexes ... but *not* the rowmarkId */
240  newrc->rti += rtoffset;
241  newrc->prti += rtoffset;
242 
243  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
244  }
245 
246  /* Now fix the Plan tree */
247  return set_plan_refs(root, plan, rtoffset);
248 }
List * rowMarks
Definition: relation.h:256
Index prti
Definition: plannodes.h:1018
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:439
#define lfirst_node(type, lc)
Definition: pg_list.h:109
PlannerGlobal * glob
Definition: relation.h:157
List * lappend(List *list, void *datum)
Definition: list.c:128
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:256
static int list_length(const List *l)
Definition: pg_list.h:89
List * finalrtable
Definition: relation.h:104
void * palloc(Size size)
Definition: mcxt.c:848
List * finalrowmarks
Definition: relation.h:106

◆ set_plan_refs()

static Plan * set_plan_refs ( PlannerInfo root,
Plan plan,
int  rtoffset 
)
static

Definition at line 439 of file setrefs.c.

References Agg::aggsplit, Append::appendplans, Assert, BitmapAnd::bitmapplans, BitmapOr::bitmapplans, BitmapHeapScan::bitmapqualorig, build_tlist_index(), convert_combining_aggrefs(), copyObject, DO_AGGSPLIT_COMBINE, elog, WindowAgg::endOffset, ERROR, ModifyTable::exclRelRTI, ModifyTable::exclRelTlist, fix_join_expr(), fix_scan_expr(), fix_scan_list, forthree, FunctionScan::functions, PlannerInfo::glob, IndexScan::indexorderby, IndexScan::indexorderbyorig, IndexScan::indexqual, BitmapIndexScan::indexqual, IndexScan::indexqualorig, BitmapIndexScan::indexqualorig, lappend(), lappend_int(), PlannerGlobal::lastPlanNodeId, Plan::lefttree, lfirst, lfirst_int, Limit::limitCount, Limit::limitOffset, linitial, linitial_int, list_concat(), list_copy(), list_length(), MergeAppend::mergeplans, NIL, nodeTag, ModifyTable::nominalRelation, PlannerGlobal::nonleafResultRelations, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, ModifyTable::partitioned_rels, Append::partitioned_rels, MergeAppend::partitioned_rels, pfree(), Result::plan, ModifyTable::plan, Append::plan, MergeAppend::plan, BitmapAnd::plan, BitmapOr::plan, Scan::plan, LockRows::plan, Limit::plan, Plan::plan_node_id, ModifyTable::plans, PlanRowMark::prti, Plan::qual, Result::resconstantqual, PlannerGlobal::resultRelations, ModifyTable::resultRelations, ModifyTable::resultRelIndex, ModifyTable::returningLists, Plan::righttree, PlannerGlobal::rootResultRelations, ModifyTable::rootResultRelIndex, ModifyTable::rowMarks, LockRows::rowMarks, PlanRowMark::rti, SampleScan::scan, IndexScan::scan, BitmapIndexScan::scan, BitmapHeapScan::scan, TidScan::scan, FunctionScan::scan, ValuesScan::scan, TableFuncScan::scan, CteScan::scan, NamedTuplestoreScan::scan, WorkTableScan::scan, Scan::scanrelid, set_customscan_references(), set_dummy_tlist_references(), set_foreignscan_references(), set_indexonlyscan_references(), set_join_references(), set_param_references(), set_returning_clause_references(), set_subqueryscan_references(), set_upper_references(), splan, WindowAgg::startOffset, T_Agg, T_Append, T_BitmapAnd, T_BitmapHeapScan, T_BitmapIndexScan, T_BitmapOr, T_CteScan, T_CustomScan, T_ForeignScan, T_FunctionScan, T_Gather, T_GatherMerge, T_Group, T_Hash, T_HashJoin, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_MergeJoin, T_ModifyTable, T_NamedTuplestoreScan, T_NestLoop, T_ProjectSet, T_RecursiveUnion, T_Result, T_SampleScan, T_SeqScan, T_SetOp, T_Sort, T_SubqueryScan, T_TableFuncScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, T_WorkTableScan, TableFuncScan::tablefunc, SampleScan::tablesample, Plan::targetlist, TidScan::tidquals, ValuesScan::values_lists, and ModifyTable::withCheckOptionLists.

Referenced by set_customscan_references(), and set_plan_references().

440 {
441  ListCell *l;
442 
443  if (plan == NULL)
444  return NULL;
445 
446  /* Assign this node a unique ID. */
447  plan->plan_node_id = root->glob->lastPlanNodeId++;
448 
449  /*
450  * Plan-type-specific fixes
451  */
452  switch (nodeTag(plan))
453  {
454  case T_SeqScan:
455  {
456  SeqScan *splan = (SeqScan *) plan;
457 
458  splan->scanrelid += rtoffset;
459  splan->plan.targetlist =
460  fix_scan_list(root, splan->plan.targetlist, rtoffset);
461  splan->plan.qual =
462  fix_scan_list(root, splan->plan.qual, rtoffset);
463  }
464  break;
465  case T_SampleScan:
466  {
467  SampleScan *splan = (SampleScan *) plan;
468 
469  splan->scan.scanrelid += rtoffset;
470  splan->scan.plan.targetlist =
471  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
472  splan->scan.plan.qual =
473  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
474  splan->tablesample = (TableSampleClause *)
475  fix_scan_expr(root, (Node *) splan->tablesample, rtoffset);
476  }
477  break;
478  case T_IndexScan:
479  {
480  IndexScan *splan = (IndexScan *) plan;
481 
482  splan->scan.scanrelid += rtoffset;
483  splan->scan.plan.targetlist =
484  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
485  splan->scan.plan.qual =
486  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
487  splan->indexqual =
488  fix_scan_list(root, splan->indexqual, rtoffset);
489  splan->indexqualorig =
490  fix_scan_list(root, splan->indexqualorig, rtoffset);
491  splan->indexorderby =
492  fix_scan_list(root, splan->indexorderby, rtoffset);
493  splan->indexorderbyorig =
494  fix_scan_list(root, splan->indexorderbyorig, rtoffset);
495  }
496  break;
497  case T_IndexOnlyScan:
498  {
499  IndexOnlyScan *splan = (IndexOnlyScan *) plan;
500 
501  return set_indexonlyscan_references(root, splan, rtoffset);
502  }
503  break;
504  case T_BitmapIndexScan:
505  {
506  BitmapIndexScan *splan = (BitmapIndexScan *) plan;
507 
508  splan->scan.scanrelid += rtoffset;
509  /* no need to fix targetlist and qual */
510  Assert(splan->scan.plan.targetlist == NIL);
511  Assert(splan->scan.plan.qual == NIL);
512  splan->indexqual =
513  fix_scan_list(root, splan->indexqual, rtoffset);
514  splan->indexqualorig =
515  fix_scan_list(root, splan->indexqualorig, rtoffset);
516  }
517  break;
518  case T_BitmapHeapScan:
519  {
520  BitmapHeapScan *splan = (BitmapHeapScan *) plan;
521 
522  splan->scan.scanrelid += rtoffset;
523  splan->scan.plan.targetlist =
524  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
525  splan->scan.plan.qual =
526  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
527  splan->bitmapqualorig =
528  fix_scan_list(root, splan->bitmapqualorig, rtoffset);
529  }
530  break;
531  case T_TidScan:
532  {
533  TidScan *splan = (TidScan *) plan;
534 
535  splan->scan.scanrelid += rtoffset;
536  splan->scan.plan.targetlist =
537  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
538  splan->scan.plan.qual =
539  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
540  splan->tidquals =
541  fix_scan_list(root, splan->tidquals, rtoffset);
542  }
543  break;
544  case T_SubqueryScan:
545  /* Needs special treatment, see comments below */
546  return set_subqueryscan_references(root,
547  (SubqueryScan *) plan,
548  rtoffset);
549  case T_FunctionScan:
550  {
551  FunctionScan *splan = (FunctionScan *) plan;
552 
553  splan->scan.scanrelid += rtoffset;
554  splan->scan.plan.targetlist =
555  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
556  splan->scan.plan.qual =
557  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
558  splan->functions =
559  fix_scan_list(root, splan->functions, rtoffset);
560  }
561  break;
562  case T_TableFuncScan:
563  {
564  TableFuncScan *splan = (TableFuncScan *) plan;
565 
566  splan->scan.scanrelid += rtoffset;
567  splan->scan.plan.targetlist =
568  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
569  splan->scan.plan.qual =
570  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
571  splan->tablefunc = (TableFunc *)
572  fix_scan_expr(root, (Node *) splan->tablefunc, rtoffset);
573  }
574  break;
575  case T_ValuesScan:
576  {
577  ValuesScan *splan = (ValuesScan *) plan;
578 
579  splan->scan.scanrelid += rtoffset;
580  splan->scan.plan.targetlist =
581  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
582  splan->scan.plan.qual =
583  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
584  splan->values_lists =
585  fix_scan_list(root, splan->values_lists, rtoffset);
586  }
587  break;
588  case T_CteScan:
589  {
590  CteScan *splan = (CteScan *) plan;
591 
592  splan->scan.scanrelid += rtoffset;
593  splan->scan.plan.targetlist =
594  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
595  splan->scan.plan.qual =
596  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
597  }
598  break;
600  {
601  NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
602 
603  splan->scan.scanrelid += rtoffset;
604  splan->scan.plan.targetlist =
605  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
606  splan->scan.plan.qual =
607  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
608  }
609  break;
610  case T_WorkTableScan:
611  {
612  WorkTableScan *splan = (WorkTableScan *) plan;
613 
614  splan->scan.scanrelid += rtoffset;
615  splan->scan.plan.targetlist =
616  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
617  splan->scan.plan.qual =
618  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
619  }
620  break;
621  case T_ForeignScan:
622  set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
623  break;
624  case T_CustomScan:
625  set_customscan_references(root, (CustomScan *) plan, rtoffset);
626  break;
627 
628  case T_NestLoop:
629  case T_MergeJoin:
630  case T_HashJoin:
631  set_join_references(root, (Join *) plan, rtoffset);
632  break;
633 
634  case T_Gather:
635  case T_GatherMerge:
636  {
637  set_upper_references(root, plan, rtoffset);
638  set_param_references(root, plan);
639  }
640  break;
641 
642  case T_Hash:
643  case T_Material:
644  case T_Sort:
645  case T_Unique:
646  case T_SetOp:
647 
648  /*
649  * These plan types don't actually bother to evaluate their
650  * targetlists, because they just return their unmodified input
651  * tuples. Even though the targetlist won't be used by the
652  * executor, we fix it up for possible use by EXPLAIN (not to
653  * mention ease of debugging --- wrong varnos are very confusing).
654  */
655  set_dummy_tlist_references(plan, rtoffset);
656 
657  /*
658  * Since these plan types don't check quals either, we should not
659  * find any qual expression attached to them.
660  */
661  Assert(plan->qual == NIL);
662  break;
663  case T_LockRows:
664  {
665  LockRows *splan = (LockRows *) plan;
666 
667  /*
668  * Like the plan types above, LockRows doesn't evaluate its
669  * tlist or quals. But we have to fix up the RT indexes in
670  * its rowmarks.
671  */
672  set_dummy_tlist_references(plan, rtoffset);
673  Assert(splan->plan.qual == NIL);
674 
675  foreach(l, splan->rowMarks)
676  {
677  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
678 
679  rc->rti += rtoffset;
680  rc->prti += rtoffset;
681  }
682  }
683  break;
684  case T_Limit:
685  {
686  Limit *splan = (Limit *) plan;
687 
688  /*
689  * Like the plan types above, Limit doesn't evaluate its tlist
690  * or quals. It does have live expressions for limit/offset,
691  * however; and those cannot contain subplan variable refs, so
692  * fix_scan_expr works for them.
693  */
694  set_dummy_tlist_references(plan, rtoffset);
695  Assert(splan->plan.qual == NIL);
696 
697  splan->limitOffset =
698  fix_scan_expr(root, splan->limitOffset, rtoffset);
699  splan->limitCount =
700  fix_scan_expr(root, splan->limitCount, rtoffset);
701  }
702  break;
703  case T_Agg:
704  {
705  Agg *agg = (Agg *) plan;
706 
707  /*
708  * If this node is combining partial-aggregation results, we
709  * must convert its Aggrefs to contain references to the
710  * partial-aggregate subexpressions that will be available
711  * from the child plan node.
712  */
713  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
714  {
715  plan->targetlist = (List *)
717  NULL);
718  plan->qual = (List *)
720  NULL);
721  }
722 
723  set_upper_references(root, plan, rtoffset);
724  }
725  break;
726  case T_Group:
727  set_upper_references(root, plan, rtoffset);
728  break;
729  case T_WindowAgg:
730  {
731  WindowAgg *wplan = (WindowAgg *) plan;
732 
733  set_upper_references(root, plan, rtoffset);
734 
735  /*
736  * Like Limit node limit/offset expressions, WindowAgg has
737  * frame offset expressions, which cannot contain subplan
738  * variable refs, so fix_scan_expr works for them.
739  */
740  wplan->startOffset =
741  fix_scan_expr(root, wplan->startOffset, rtoffset);
742  wplan->endOffset =
743  fix_scan_expr(root, wplan->endOffset, rtoffset);
744  }
745  break;
746  case T_Result:
747  {
748  Result *splan = (Result *) plan;
749 
750  /*
751  * Result may or may not have a subplan; if not, it's more
752  * like a scan node than an upper node.
753  */
754  if (splan->plan.lefttree != NULL)
755  set_upper_references(root, plan, rtoffset);
756  else
757  {
758  splan->plan.targetlist =
759  fix_scan_list(root, splan->plan.targetlist, rtoffset);
760  splan->plan.qual =
761  fix_scan_list(root, splan->plan.qual, rtoffset);
762  }
763  /* resconstantqual can't contain any subplan variable refs */
764  splan->resconstantqual =
765  fix_scan_expr(root, splan->resconstantqual, rtoffset);
766  }
767  break;
768  case T_ProjectSet:
769  set_upper_references(root, plan, rtoffset);
770  break;
771  case T_ModifyTable:
772  {
773  ModifyTable *splan = (ModifyTable *) plan;
774 
775  Assert(splan->plan.targetlist == NIL);
776  Assert(splan->plan.qual == NIL);
777 
778  splan->withCheckOptionLists =
779  fix_scan_list(root, splan->withCheckOptionLists, rtoffset);
780 
781  if (splan->returningLists)
782  {
783  List *newRL = NIL;
784  ListCell *lcrl,
785  *lcrr,
786  *lcp;
787 
788  /*
789  * Pass each per-subplan returningList through
790  * set_returning_clause_references().
791  */
793  Assert(list_length(splan->returningLists) == list_length(splan->plans));
794  forthree(lcrl, splan->returningLists,
795  lcrr, splan->resultRelations,
796  lcp, splan->plans)
797  {
798  List *rlist = (List *) lfirst(lcrl);
799  Index resultrel = lfirst_int(lcrr);
800  Plan *subplan = (Plan *) lfirst(lcp);
801 
802  rlist = set_returning_clause_references(root,
803  rlist,
804  subplan,
805  resultrel,
806  rtoffset);
807  newRL = lappend(newRL, rlist);
808  }
809  splan->returningLists = newRL;
810 
811  /*
812  * Set up the visible plan targetlist as being the same as
813  * the first RETURNING list. This is for the use of
814  * EXPLAIN; the executor won't pay any attention to the
815  * targetlist. We postpone this step until here so that
816  * we don't have to do set_returning_clause_references()
817  * twice on identical targetlists.
818  */
819  splan->plan.targetlist = copyObject(linitial(newRL));
820  }
821 
822  /*
823  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
824  * join', where the inner side is the EXCLUDED tuple.
825  * Therefore use fix_join_expr to setup the relevant variables
826  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
827  * those are already used by RETURNING and it seems better to
828  * be non-conflicting.
829  */
830  if (splan->onConflictSet)
831  {
832  indexed_tlist *itlist;
833 
834  itlist = build_tlist_index(splan->exclRelTlist);
835 
836  splan->onConflictSet =
837  fix_join_expr(root, splan->onConflictSet,
838  NULL, itlist,
840  rtoffset);
841 
842  splan->onConflictWhere = (Node *)
843  fix_join_expr(root, (List *) splan->onConflictWhere,
844  NULL, itlist,
846  rtoffset);
847 
848  pfree(itlist);
849 
850  splan->exclRelTlist =
851  fix_scan_list(root, splan->exclRelTlist, rtoffset);
852  }
853 
854  splan->nominalRelation += rtoffset;
855  splan->exclRelRTI += rtoffset;
856 
857  foreach(l, splan->partitioned_rels)
858  {
859  lfirst_int(l) += rtoffset;
860  }
861  foreach(l, splan->resultRelations)
862  {
863  lfirst_int(l) += rtoffset;
864  }
865  foreach(l, splan->rowMarks)
866  {
867  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
868 
869  rc->rti += rtoffset;
870  rc->prti += rtoffset;
871  }
872  foreach(l, splan->plans)
873  {
874  lfirst(l) = set_plan_refs(root,
875  (Plan *) lfirst(l),
876  rtoffset);
877  }
878 
879  /*
880  * Append this ModifyTable node's final result relation RT
881  * index(es) to the global list for the plan, and set its
882  * resultRelIndex to reflect their starting position in the
883  * global list.
884  */
886  root->glob->resultRelations =
888  list_copy(splan->resultRelations));
889 
890  /*
891  * If the main target relation is a partitioned table, the
892  * following list contains the RT indexes of partitioned child
893  * relations including the root, which are not included in the
894  * above list. We also keep RT indexes of the roots
895  * separately to be identitied as such during the executor
896  * initialization.
897  */
898  if (splan->partitioned_rels != NIL)
899  {
902  list_copy(splan->partitioned_rels));
903  /* Remember where this root will be in the global list. */
904  splan->rootResultRelIndex =
906  root->glob->rootResultRelations =
909  }
910  }
911  break;
912  case T_Append:
913  {
914  Append *splan = (Append *) plan;
915 
916  /*
917  * Append, like Sort et al, doesn't actually evaluate its
918  * targetlist or check quals.
919  */
920  set_dummy_tlist_references(plan, rtoffset);
921  Assert(splan->plan.qual == NIL);
922  foreach(l, splan->partitioned_rels)
923  {
924  lfirst_int(l) += rtoffset;
925  }
926  foreach(l, splan->appendplans)
927  {
928  lfirst(l) = set_plan_refs(root,
929  (Plan *) lfirst(l),
930  rtoffset);
931  }
932  }
933  break;
934  case T_MergeAppend:
935  {
936  MergeAppend *splan = (MergeAppend *) plan;
937 
938  /*
939  * MergeAppend, like Sort et al, doesn't actually evaluate its
940  * targetlist or check quals.
941  */
942  set_dummy_tlist_references(plan, rtoffset);
943  Assert(splan->plan.qual == NIL);
944  foreach(l, splan->partitioned_rels)
945  {
946  lfirst_int(l) += rtoffset;
947  }
948  foreach(l, splan->mergeplans)
949  {
950  lfirst(l) = set_plan_refs(root,
951  (Plan *) lfirst(l),
952  rtoffset);
953  }
954  }
955  break;
956  case T_RecursiveUnion:
957  /* This doesn't evaluate targetlist or check quals either */
958  set_dummy_tlist_references(plan, rtoffset);
959  Assert(plan->qual == NIL);
960  break;
961  case T_BitmapAnd:
962  {
963  BitmapAnd *splan = (BitmapAnd *) plan;
964 
965  /* BitmapAnd works like Append, but has no tlist */
966  Assert(splan->plan.targetlist == NIL);
967  Assert(splan->plan.qual == NIL);
968  foreach(l, splan->bitmapplans)
969  {
970  lfirst(l) = set_plan_refs(root,
971  (Plan *) lfirst(l),
972  rtoffset);
973  }
974  }
975  break;
976  case T_BitmapOr:
977  {
978  BitmapOr *splan = (BitmapOr *) plan;
979 
980  /* BitmapOr works like Append, but has no tlist */
981  Assert(splan->plan.targetlist == NIL);
982  Assert(splan->plan.qual == NIL);
983  foreach(l, splan->bitmapplans)
984  {
985  lfirst(l) = set_plan_refs(root,
986  (Plan *) lfirst(l),
987  rtoffset);
988  }
989  }
990  break;
991  default:
992  elog(ERROR, "unrecognized node type: %d",
993  (int) nodeTag(plan));
994  break;
995  }
996 
997  /*
998  * Now recurse into child plans, if any
999  *
1000  * NOTE: it is essential that we recurse into child plans AFTER we set
1001  * subplan references in this plan's tlist and quals. If we did the
1002  * reference-adjustments bottom-up, then we would fail to match this
1003  * plan's var nodes against the already-modified nodes of the children.
1004  */
1005  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
1006  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1007 
1008  return plan;
1009 }
List * bitmapplans
Definition: plannodes.h:303
#define NIL
Definition: pg_list.h:69
Plan plan
Definition: plannodes.h:190
List * qual
Definition: plannodes.h:145
Definition: nodes.h:77
Plan plan
Definition: plannodes.h:328
Plan plan
Definition: plannodes.h:927
Index nominalRelation
Definition: plannodes.h:219
Definition: nodes.h:79
Index scanrelid
Definition: plannodes.h:329
Plan plan
Definition: plannodes.h:913
List * withCheckOptionLists
Definition: plannodes.h:226
List * functions
Definition: plannodes.h:508
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset)
Definition: setrefs.c:1602
int resultRelIndex
Definition: plannodes.h:223
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:203
int lastPlanNodeId
Definition: relation.h:123
List * indexqual
Definition: plannodes.h:447
List * tidquals
Definition: plannodes.h:476
TableFunc * tablefunc
Definition: plannodes.h:529
int plan_node_id
Definition: plannodes.h:143
List * resultRelations
Definition: relation.h:108
List * indexqualorig
Definition: plannodes.h:391
struct TableSampleClause * tablesample
Definition: plannodes.h:346
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:510
Definition: nodes.h:48
Index prti
Definition: plannodes.h:1018
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * values_lists
Definition: plannodes.h:519
static void set_param_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:1796
Definition: nodes.h:75
Scan scan
Definition: plannodes.h:518
Node * limitOffset
Definition: plannodes.h:928
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:769
List * plans
Definition: plannodes.h:225
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:439
List * onConflictSet
Definition: plannodes.h:234
int rootResultRelIndex
Definition: plannodes.h:224
List * resultRelations
Definition: plannodes.h:222
static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, int rtoffset)
Definition: setrefs.c:1189
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset)
Definition: setrefs.c:2238
List * rootResultRelations
Definition: relation.h:111
List * appendplans
Definition: plannodes.h:250
#define linitial_int(l)
Definition: pg_list.h:112
Node * startOffset
Definition: plannodes.h:810
Node * resconstantqual
Definition: plannodes.h:191
List * rowMarks
Definition: plannodes.h:230
struct Plan * righttree
Definition: plannodes.h:147
void pfree(void *pointer)
Definition: mcxt.c:949
#define linitial(l)
Definition: pg_list.h:111
Definition: nodes.h:45
#define ERROR
Definition: elog.h:43
List * indexorderbyorig
Definition: plannodes.h:393
#define lfirst_int(lc)
Definition: pg_list.h:107
Scan scan
Definition: plannodes.h:344
Scan scan
Definition: plannodes.h:538
Node * limitCount
Definition: plannodes.h:929
Scan scan
Definition: plannodes.h:388
Definition: nodes.h:76
List * partitioned_rels
Definition: plannodes.h:262
PlannerGlobal * glob
Definition: relation.h:157
Node * endOffset
Definition: plannodes.h:811
static SPIPlanPtr splan
Definition: regress.c:449
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1267
List * partitioned_rels
Definition: plannodes.h:221
List * partitioned_rels
Definition: plannodes.h:249
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:1062
List * indexqual
Definition: plannodes.h:390
List * bitmapqualorig
Definition: plannodes.h:463
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * lappend(List *list, void *datum)
Definition: list.c:128
Plan plan
Definition: plannodes.h:316
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:1021
List * bitmapplans
Definition: plannodes.h:318
static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1736
unsigned int Index
Definition: c.h:413
Definition: nodes.h:82
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:1851
List * indexorderby
Definition: plannodes.h:392
List * nonleafResultRelations
Definition: relation.h:110
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
AggSplit aggsplit
Definition: plannodes.h:784
List * rowMarks
Definition: plannodes.h:914
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
Scan scan
Definition: plannodes.h:475
static int list_length(const List *l)
Definition: pg_list.h:89
struct Plan * lefttree
Definition: plannodes.h:146
List * indexqualorig
Definition: plannodes.h:448
#define nodeTag(nodeptr)
Definition: nodes.h:515
List * targetlist
Definition: plannodes.h:144
Definition: nodes.h:83
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2509
List * mergeplans
Definition: plannodes.h:263
Definition: nodes.h:80
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
Definition: setrefs.c:1482
List * returningLists
Definition: plannodes.h:227
Plan plan
Definition: plannodes.h:302
Definition: plannodes.h:780
#define elog
Definition: elog.h:219
#define copyObject(obj)
Definition: nodes.h:623
Index exclRelRTI
Definition: plannodes.h:236
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:84
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:1920
List * exclRelTlist
Definition: plannodes.h:237
Plan plan
Definition: plannodes.h:247
Node * onConflictWhere
Definition: plannodes.h:235
Definition: nodes.h:85

◆ set_returning_clause_references()

static List * set_returning_clause_references ( PlannerInfo root,
List rlist,
Plan topplan,
Index  resultRelation,
int  rtoffset 
)
static

Definition at line 2509 of file setrefs.c.

References build_tlist_index_other_vars(), fix_join_expr(), pfree(), and Plan::targetlist.

Referenced by set_plan_refs().

2514 {
2515  indexed_tlist *itlist;
2516 
2517  /*
2518  * We can perform the desired Var fixup by abusing the fix_join_expr
2519  * machinery that formerly handled inner indexscan fixup. We search the
2520  * top plan's targetlist for Vars of non-result relations, and use
2521  * fix_join_expr to convert RETURNING Vars into references to those tlist
2522  * entries, while leaving result-rel Vars as-is.
2523  *
2524  * PlaceHolderVars will also be sought in the targetlist, but no
2525  * more-complex expressions will be. Note that it is not possible for a
2526  * PlaceHolderVar to refer to the result relation, since the result is
2527  * never below an outer join. If that case could happen, we'd have to be
2528  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2529  * expression instead.
2530  */
2531  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2532 
2533  rlist = fix_join_expr(root,
2534  rlist,
2535  itlist,
2536  NULL,
2537  resultRelation,
2538  rtoffset);
2539 
2540  pfree(itlist);
2541 
2542  return rlist;
2543 }
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset)
Definition: setrefs.c:2238
void pfree(void *pointer)
Definition: mcxt.c:949
static indexed_tlist * build_tlist_index_other_vars(List *tlist, Index ignore_rel)
Definition: setrefs.c:2042
List * targetlist
Definition: plannodes.h:144

◆ set_subqueryscan_references()

static Plan * set_subqueryscan_references ( PlannerInfo root,
SubqueryScan plan,
int  rtoffset 
)
static

Definition at line 1062 of file setrefs.c.

References find_base_rel(), fix_scan_list, forboth, Plan::initPlan, lfirst, list_concat(), Scan::plan, Plan::qual, TargetEntry::resname, TargetEntry::resorigcol, TargetEntry::resorigtbl, SubqueryScan::scan, Scan::scanrelid, set_plan_references(), SubqueryScan::subplan, RelOptInfo::subroot, Plan::targetlist, and trivial_subqueryscan().

Referenced by set_plan_refs().

1065 {
1066  RelOptInfo *rel;
1067  Plan *result;
1068 
1069  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1070  rel = find_base_rel(root, plan->scan.scanrelid);
1071 
1072  /* Recursively process the subplan */
1073  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1074 
1075  if (trivial_subqueryscan(plan))
1076  {
1077  /*
1078  * We can omit the SubqueryScan node and just pull up the subplan.
1079  */
1080  ListCell *lp,
1081  *lc;
1082 
1083  result = plan->subplan;
1084 
1085  /* We have to be sure we don't lose any initplans */
1086  result->initPlan = list_concat(plan->scan.plan.initPlan,
1087  result->initPlan);
1088 
1089  /*
1090  * We also have to transfer the SubqueryScan's result-column names
1091  * into the subplan, else columns sent to client will be improperly
1092  * labeled if this is the topmost plan level. Copy the "source
1093  * column" information too.
1094  */
1095  forboth(lp, plan->scan.plan.targetlist, lc, result->targetlist)
1096  {
1097  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1098  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1099 
1100  ctle->resname = ptle->resname;
1101  ctle->resorigtbl = ptle->resorigtbl;
1102  ctle->resorigcol = ptle->resorigcol;
1103  }
1104  }
1105  else
1106  {
1107  /*
1108  * Keep the SubqueryScan node. We have to do the processing that
1109  * set_plan_references would otherwise have done on it. Notice we do
1110  * not do set_upper_references() here, because a SubqueryScan will
1111  * always have been created with correct references to its subplan's
1112  * outputs to begin with.
1113  */
1114  plan->scan.scanrelid += rtoffset;
1115  plan->scan.plan.targetlist =
1116  fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
1117  plan->scan.plan.qual =
1118  fix_scan_list(root, plan->scan.plan.qual, rtoffset);
1119 
1120  result = (Plan *) plan;
1121  }
1122 
1123  return result;
1124 }
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
Index scanrelid
Definition: plannodes.h:329
Oid resorigtbl
Definition: primnodes.h:1380
List * list_concat(List *list1, List *list2)
Definition: list.c:321
char * resname
Definition: primnodes.h:1377
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1134
PlannerInfo * subroot
Definition: relation.h:627
#define lfirst(lc)
Definition: pg_list.h:106
List * targetlist
Definition: plannodes.h:144
AttrNumber resorigcol
Definition: primnodes.h:1381
List * initPlan
Definition: plannodes.h:148
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:214
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:277
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:84
Plan * subplan
Definition: plannodes.h:498

◆ set_upper_references()

static void set_upper_references ( PlannerInfo root,
Plan plan,
int  rtoffset 
)
static

Definition at line 1736 of file setrefs.c.

References build_tlist_index(), TargetEntry::expr, fix_upper_expr(), flatCopyTargetEntry(), lappend(), Plan::lefttree, lfirst, NIL, OUTER_VAR, pfree(), Plan::qual, TargetEntry::ressortgroupref, search_indexed_tlist_for_sortgroupref(), and Plan::targetlist.

Referenced by set_plan_refs().

1737 {
1738  Plan *subplan = plan->lefttree;
1739  indexed_tlist *subplan_itlist;
1740  List *output_targetlist;
1741  ListCell *l;
1742 
1743  subplan_itlist = build_tlist_index(subplan->targetlist);
1744 
1745  output_targetlist = NIL;
1746  foreach(l, plan->targetlist)
1747  {
1748  TargetEntry *tle = (TargetEntry *) lfirst(l);
1749  Node *newexpr;
1750 
1751  /* If it's a sort/group item, first try to match by sortref */
1752  if (tle->ressortgroupref != 0)
1753  {
1754  newexpr = (Node *)
1756  tle->ressortgroupref,
1757  subplan_itlist,
1758  OUTER_VAR);
1759  if (!newexpr)
1760  newexpr = fix_upper_expr(root,
1761  (Node *) tle->expr,
1762  subplan_itlist,
1763  OUTER_VAR,
1764  rtoffset);
1765  }
1766  else
1767  newexpr = fix_upper_expr(root,
1768  (Node *) tle->expr,
1769  subplan_itlist,
1770  OUTER_VAR,
1771  rtoffset);
1772  tle = flatCopyTargetEntry(tle);
1773  tle->expr = (Expr *) newexpr;
1774  output_targetlist = lappend(output_targetlist, tle);
1775  }
1776  plan->targetlist = output_targetlist;
1777 
1778  plan->qual = (List *)
1779  fix_upper_expr(root,
1780  (Node *) plan->qual,
1781  subplan_itlist,
1782  OUTER_VAR,
1783  rtoffset);
1784 
1785  pfree(subplan_itlist);
1786 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
Definition: nodes.h:510
void pfree(void *pointer)
Definition: mcxt.c:949
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:270
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2389
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1986
struct Plan * lefttree
Definition: plannodes.h:146
List * targetlist
Definition: plannodes.h:144
Index ressortgroupref
Definition: primnodes.h:1378
static Var * search_indexed_tlist_for_sortgroupref(Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2174
Definition: pg_list.h:45
#define OUTER_VAR
Definition: primnodes.h:154

◆ trivial_subqueryscan()

static bool trivial_subqueryscan ( SubqueryScan plan)
static

Definition at line 1134 of file setrefs.c.

References Assert, equal(), TargetEntry::expr, forboth, IsA, lfirst, list_length(), NIL, Scan::plan, Plan::qual, TargetEntry::resjunk, SubqueryScan::scan, Scan::scanrelid, SubqueryScan::subplan, Plan::targetlist, Var::varattno, Var::varlevelsup, and Var::varno.

Referenced by set_subqueryscan_references().

1135 {
1136  int attrno;
1137  ListCell *lp,
1138  *lc;
1139 
1140  if (plan->scan.plan.qual != NIL)
1141  return false;
1142 
1143  if (list_length(plan->scan.plan.targetlist) !=
1144  list_length(plan->subplan->targetlist))
1145  return false; /* tlists not same length */
1146 
1147  attrno = 1;
1148  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1149  {
1150  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1151  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1152 
1153  if (ptle->resjunk != ctle->resjunk)
1154  return false; /* tlist doesn't match junk status */
1155 
1156  /*
1157  * We accept either a Var referencing the corresponding element of the
1158  * subplan tlist, or a Const equaling the subplan element. See
1159  * generate_setop_tlist() for motivation.
1160  */
1161  if (ptle->expr && IsA(ptle->expr, Var))
1162  {
1163  Var *var = (Var *) ptle->expr;
1164 
1165  Assert(var->varno == plan->scan.scanrelid);
1166  Assert(var->varlevelsup == 0);
1167  if (var->varattno != attrno)
1168  return false; /* out of order */
1169  }
1170  else if (ptle->expr && IsA(ptle->expr, Const))
1171  {
1172  if (!equal(ptle->expr, ctle->expr))
1173  return false;
1174  }
1175  else
1176  return false;
1177 
1178  attrno++;
1179  }
1180 
1181  return true;
1182 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
Plan plan
Definition: plannodes.h:328
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
Index varlevelsup
Definition: primnodes.h:173
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:180
Index scanrelid
Definition: plannodes.h:329
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2974
AttrNumber varattno
Definition: primnodes.h:168
Definition: primnodes.h:163
bool resjunk
Definition: primnodes.h:1382
Index varno
Definition: primnodes.h:166
#define Assert(condition)
Definition: c.h:670
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1375
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:144
Plan * subplan
Definition: plannodes.h:498