PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
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 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 (Node *node, indexed_tlist *itlist, Index newvarno)
 
static Varsearch_indexed_tlist_for_sortgroupref (Node *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)
 
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

#define fix_scan_list (   root,
  lst,
  rtoffset 
)    ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))
#define ISREGCLASSCONST (   con)
Value:
(((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
!(con)->constisnull)
#define REGCLASSOID
Definition: pg_type.h:565
#define OIDOID
Definition: pg_type.h:328

Definition at line 77 of file setrefs.c.

Referenced by fix_expr_common().

Function Documentation

static void add_rte_to_flat_rtable ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 383 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, NULL, palloc(), PlannerGlobal::relationOids, RangeTblEntry::relid, RTE_RELATION, RangeTblEntry::rtekind, RangeTblEntry::securityQuals, RangeTblEntry::subquery, RangeTblEntry::tablesample, and RangeTblEntry::values_lists.

Referenced by add_rtes_to_flat_rtable(), and flatten_rtes_walker().

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

Definition at line 251 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, NULL, 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().

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

Definition at line 1880 of file setrefs.c.

References TargetEntry::expr, 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_customscan_references(), set_foreignscan_references(), set_indexonlyscan_references(), set_join_references(), set_plan_refs(), and set_upper_references().

1881 {
1882  indexed_tlist *itlist;
1883  tlist_vinfo *vinfo;
1884  ListCell *l;
1885 
1886  /* Create data structure with enough slots for all tlist entries */
1887  itlist = (indexed_tlist *)
1889  list_length(tlist) * sizeof(tlist_vinfo));
1890 
1891  itlist->tlist = tlist;
1892  itlist->has_ph_vars = false;
1893  itlist->has_non_vars = false;
1894 
1895  /* Find the Vars and fill in the index array */
1896  vinfo = itlist->vars;
1897  foreach(l, tlist)
1898  {
1899  TargetEntry *tle = (TargetEntry *) lfirst(l);
1900 
1901  if (tle->expr && IsA(tle->expr, Var))
1902  {
1903  Var *var = (Var *) tle->expr;
1904 
1905  vinfo->varno = var->varno;
1906  vinfo->varattno = var->varattno;
1907  vinfo->resno = tle->resno;
1908  vinfo++;
1909  }
1910  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
1911  itlist->has_ph_vars = true;
1912  else
1913  itlist->has_non_vars = true;
1914  }
1915 
1916  itlist->num_vars = (vinfo - itlist->vars);
1917 
1918  return itlist;
1919 }
Index varno
Definition: setrefs.c:33
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:44
AttrNumber resno
Definition: setrefs.c:35
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
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:1331
Index varno
Definition: primnodes.h:144
bool has_non_vars
Definition: setrefs.c:43
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:891
Definition: regcomp.c:226
#define offsetof(type, field)
Definition: c.h:551
List * tlist
Definition: setrefs.c:40
static indexed_tlist* build_tlist_index_other_vars ( List tlist,
Index  ignore_rel 
)
static

Definition at line 1930 of file setrefs.c.

References TargetEntry::expr, 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().

1931 {
1932  indexed_tlist *itlist;
1933  tlist_vinfo *vinfo;
1934  ListCell *l;
1935 
1936  /* Create data structure with enough slots for all tlist entries */
1937  itlist = (indexed_tlist *)
1939  list_length(tlist) * sizeof(tlist_vinfo));
1940 
1941  itlist->tlist = tlist;
1942  itlist->has_ph_vars = false;
1943  itlist->has_non_vars = false;
1944 
1945  /* Find the desired Vars and fill in the index array */
1946  vinfo = itlist->vars;
1947  foreach(l, tlist)
1948  {
1949  TargetEntry *tle = (TargetEntry *) lfirst(l);
1950 
1951  if (tle->expr && IsA(tle->expr, Var))
1952  {
1953  Var *var = (Var *) tle->expr;
1954 
1955  if (var->varno != ignore_rel)
1956  {
1957  vinfo->varno = var->varno;
1958  vinfo->varattno = var->varattno;
1959  vinfo->resno = tle->resno;
1960  vinfo++;
1961  }
1962  }
1963  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
1964  itlist->has_ph_vars = true;
1965  }
1966 
1967  itlist->num_vars = (vinfo - itlist->vars);
1968 
1969  return itlist;
1970 }
Index varno
Definition: setrefs.c:33
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:44
AttrNumber resno
Definition: setrefs.c:35
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
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:1331
Index varno
Definition: primnodes.h:144
bool has_non_vars
Definition: setrefs.c:43
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
void * palloc(Size size)
Definition: mcxt.c:891
Definition: regcomp.c:226
#define offsetof(type, field)
Definition: c.h:551
List * tlist
Definition: setrefs.c:40
static Node * convert_combining_aggrefs ( Node node,
void *  context 
)
static

Definition at line 1745 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(), NIL, and NULL.

Referenced by set_plan_refs().

1746 {
1747  if (node == NULL)
1748  return NULL;
1749  if (IsA(node, Aggref))
1750  {
1751  Aggref *orig_agg = (Aggref *) node;
1752  Aggref *child_agg;
1753  Aggref *parent_agg;
1754 
1755  /* Assert we've not chosen to partial-ize any unsupported cases */
1756  Assert(orig_agg->aggorder == NIL);
1757  Assert(orig_agg->aggdistinct == NIL);
1758 
1759  /*
1760  * Since aggregate calls can't be nested, we needn't recurse into the
1761  * arguments. But for safety, flat-copy the Aggref node itself rather
1762  * than modifying it in-place.
1763  */
1764  child_agg = makeNode(Aggref);
1765  memcpy(child_agg, orig_agg, sizeof(Aggref));
1766 
1767  /*
1768  * For the parent Aggref, we want to copy all the fields of the
1769  * original aggregate *except* the args list, which we'll replace
1770  * below, and the aggfilter expression, which should be applied only
1771  * by the child not the parent. Rather than explicitly knowing about
1772  * all the other fields here, we can momentarily modify child_agg to
1773  * provide a suitable source for copyObject.
1774  */
1775  child_agg->args = NIL;
1776  child_agg->aggfilter = NULL;
1777  parent_agg = (Aggref *) copyObject(child_agg);
1778  child_agg->args = orig_agg->args;
1779  child_agg->aggfilter = orig_agg->aggfilter;
1780 
1781  /*
1782  * Now, set up child_agg to represent the first phase of partial
1783  * aggregation. For now, assume serialization is required.
1784  */
1786 
1787  /*
1788  * And set up parent_agg to represent the second phase.
1789  */
1790  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
1791  1, NULL, false));
1793 
1794  return (Node *) parent_agg;
1795  }
1797  (void *) context);
1798 }
List * aggdistinct
Definition: primnodes.h:281
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2397
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:4507
Definition: nodes.h:508
List * args
Definition: primnodes.h:279
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
#define list_make1(x1)
Definition: pg_list.h:133
List * aggorder
Definition: primnodes.h:280
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:235
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:1745
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
Expr * aggfilter
Definition: primnodes.h:282
static Var* copyVar ( Var var)
inlinestatic

Definition at line 1275 of file setrefs.c.

References palloc().

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

1276 {
1277  Var *newvar = (Var *) palloc(sizeof(Var));
1278 
1279  *newvar = *var;
1280  return newvar;
1281 }
Definition: primnodes.h:141
void * palloc(Size size)
Definition: mcxt.c:891
void extract_query_dependencies ( Node query,
List **  relationOids,
List **  invalItems,
bool hasRowSecurity 
)

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

2479 {
2480  PlannerGlobal glob;
2481  PlannerInfo root;
2482 
2483  /* Make up dummy planner state so we can use this module's machinery */
2484  MemSet(&glob, 0, sizeof(glob));
2485  glob.type = T_PlannerGlobal;
2486  glob.relationOids = NIL;
2487  glob.invalItems = NIL;
2488  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2489  glob.dependsOnRole = false;
2490 
2491  MemSet(&root, 0, sizeof(root));
2492  root.type = T_PlannerInfo;
2493  root.glob = &glob;
2494 
2495  (void) extract_query_dependencies_walker(query, &root);
2496 
2497  *relationOids = glob.relationOids;
2498  *invalItems = glob.invalItems;
2499  *hasRowSecurity = glob.dependsOnRole;
2500 }
#define NIL
Definition: pg_list.h:69
#define MemSet(start, val, len)
Definition: c.h:853
bool dependsOnRole
Definition: relation.h:124
PlannerGlobal * glob
Definition: relation.h:154
List * invalItems
Definition: relation.h:112
NodeTag type
Definition: relation.h:150
static bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2503
NodeTag type
Definition: relation.h:94
List * relationOids
Definition: relation.h:110
static bool extract_query_dependencies_walker ( Node node,
PlannerInfo context 
)
static

Definition at line 2503 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, NULL, query_tree_walker(), PlannerGlobal::relationOids, RangeTblEntry::relid, Query::rtable, RTE_RELATION, RangeTblEntry::rtekind, UtilityContainsQuery(), and Query::utilityStmt.

Referenced by extract_query_dependencies().

2504 {
2505  if (node == NULL)
2506  return false;
2507  Assert(!IsA(node, PlaceHolderVar));
2508  /* Extract function dependencies and check for regclass Consts */
2509  fix_expr_common(context, node);
2510  if (IsA(node, Query))
2511  {
2512  Query *query = (Query *) node;
2513  ListCell *lc;
2514 
2515  if (query->commandType == CMD_UTILITY)
2516  {
2517  /*
2518  * Ignore utility statements, except those (such as EXPLAIN) that
2519  * contain a parsed-but-not-planned query.
2520  */
2521  query = UtilityContainsQuery(query->utilityStmt);
2522  if (query == NULL)
2523  return false;
2524  }
2525 
2526  /* Remember if any Query has RLS quals applied by rewriter */
2527  if (query->hasRowSecurity)
2528  context->glob->dependsOnRole = true;
2529 
2530  /* Collect relation OIDs in this Query's rtable */
2531  foreach(lc, query->rtable)
2532  {
2533  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2534 
2535  if (rte->rtekind == RTE_RELATION)
2536  context->glob->relationOids =
2537  lappend_oid(context->glob->relationOids, rte->relid);
2538  }
2539 
2540  /* And recurse into the query's subexpressions */
2542  (void *) context, 0);
2543  }
2545  (void *) context);
2546 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2238
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Node * utilityStmt
Definition: parsenodes.h:111
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:1835
bool dependsOnRole
Definition: relation.h:124
List * rtable
Definition: parsenodes.h:128
PlannerGlobal * glob
Definition: relation.h:154
static bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2503
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1297
CmdType commandType
Definition: parsenodes.h:103
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1852
List * relationOids
Definition: relation.h:110
RTEKind rtekind
Definition: parsenodes.h:882
bool hasRowSecurity
Definition: parsenodes.h:124
static void fix_expr_common ( PlannerInfo root,
Node node 
)
static

Definition at line 1297 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, OidIsValid, 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().

1298 {
1299  /* We assume callers won't call us on a NULL pointer */
1300  if (IsA(node, Aggref))
1301  {
1303  ((Aggref *) node)->aggfnoid);
1304  }
1305  else if (IsA(node, WindowFunc))
1306  {
1308  ((WindowFunc *) node)->winfnoid);
1309  }
1310  else if (IsA(node, FuncExpr))
1311  {
1313  ((FuncExpr *) node)->funcid);
1314  }
1315  else if (IsA(node, OpExpr))
1316  {
1317  set_opfuncid((OpExpr *) node);
1319  ((OpExpr *) node)->opfuncid);
1320  }
1321  else if (IsA(node, DistinctExpr))
1322  {
1323  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1325  ((DistinctExpr *) node)->opfuncid);
1326  }
1327  else if (IsA(node, NullIfExpr))
1328  {
1329  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1331  ((NullIfExpr *) node)->opfuncid);
1332  }
1333  else if (IsA(node, ScalarArrayOpExpr))
1334  {
1337  ((ScalarArrayOpExpr *) node)->opfuncid);
1338  }
1339  else if (IsA(node, ArrayCoerceExpr))
1340  {
1341  if (OidIsValid(((ArrayCoerceExpr *) node)->elemfuncid))
1343  ((ArrayCoerceExpr *) node)->elemfuncid);
1344  }
1345  else if (IsA(node, Const))
1346  {
1347  Const *con = (Const *) node;
1348 
1349  /* Check for regclass reference */
1350  if (ISREGCLASSCONST(con))
1351  root->glob->relationOids =
1352  lappend_oid(root->glob->relationOids,
1354  }
1355  else if (IsA(node, GroupingFunc))
1356  {
1357  GroupingFunc *g = (GroupingFunc *) node;
1358  AttrNumber *grouping_map = root->grouping_map;
1359 
1360  /* If there are no grouping sets, we don't need this. */
1361 
1362  Assert(grouping_map || g->cols == NIL);
1363 
1364  if (grouping_map)
1365  {
1366  ListCell *lc;
1367  List *cols = NIL;
1368 
1369  foreach(lc, g->refs)
1370  {
1371  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1372  }
1373 
1374  Assert(!g->cols || equal(cols, g->cols));
1375 
1376  if (!g->cols)
1377  g->cols = cols;
1378  }
1379  }
1380 }
Datum constvalue
Definition: primnodes.h:174
#define NIL
Definition: pg_list.h:69
#define ISREGCLASSCONST(con)
Definition: setrefs.c:77
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
List * refs
Definition: primnodes.h:321
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
#define DatumGetObjectId(X)
Definition: postgres.h:508
AttrNumber * grouping_map
Definition: relation.h:279
List * lappend_oid(List *list, Oid datum)
Definition: list.c:164
#define OidIsValid(objectId)
Definition: c.h:534
#define lfirst_int(lc)
Definition: pg_list.h:107
PlannerGlobal * glob
Definition: relation.h:154
List * lappend_int(List *list, int datum)
Definition: list.c:146
List * cols
Definition: primnodes.h:322
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2437
#define Assert(condition)
Definition: c.h:671
List * relationOids
Definition: relation.h:110
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1622
Definition: pg_list.h:45
int16 AttrNumber
Definition: attnum.h:21
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1633
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 2126 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().

2132 {
2133  fix_join_expr_context context;
2134 
2135  context.root = root;
2136  context.outer_itlist = outer_itlist;
2137  context.inner_itlist = inner_itlist;
2138  context.acceptable_rel = acceptable_rel;
2139  context.rtoffset = rtoffset;
2140  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2141 }
indexed_tlist * inner_itlist
Definition: setrefs.c:57
Definition: nodes.h:508
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2144
PlannerInfo * root
Definition: setrefs.c:55
indexed_tlist * outer_itlist
Definition: setrefs.c:56
Definition: pg_list.h:45
static Node * fix_join_expr_mutator ( Node node,
fix_join_expr_context context 
)
static

Definition at line 2144 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_non_vars, indexed_tlist::has_ph_vars, fix_join_expr_context::inner_itlist, INNER_VAR, IsA, NULL, 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().

2145 {
2146  Var *newvar;
2147 
2148  if (node == NULL)
2149  return NULL;
2150  if (IsA(node, Var))
2151  {
2152  Var *var = (Var *) node;
2153 
2154  /* Look for the var in the input tlists, first in the outer */
2155  if (context->outer_itlist)
2156  {
2157  newvar = search_indexed_tlist_for_var(var,
2158  context->outer_itlist,
2159  OUTER_VAR,
2160  context->rtoffset);
2161  if (newvar)
2162  return (Node *) newvar;
2163  }
2164 
2165  /* then in the inner. */
2166  if (context->inner_itlist)
2167  {
2168  newvar = search_indexed_tlist_for_var(var,
2169  context->inner_itlist,
2170  INNER_VAR,
2171  context->rtoffset);
2172  if (newvar)
2173  return (Node *) newvar;
2174  }
2175 
2176  /* If it's for acceptable_rel, adjust and return it */
2177  if (var->varno == context->acceptable_rel)
2178  {
2179  var = copyVar(var);
2180  var->varno += context->rtoffset;
2181  if (var->varnoold > 0)
2182  var->varnoold += context->rtoffset;
2183  return (Node *) var;
2184  }
2185 
2186  /* No referent found for Var */
2187  elog(ERROR, "variable not found in subplan target lists");
2188  }
2189  if (IsA(node, PlaceHolderVar))
2190  {
2191  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2192 
2193  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2194  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2195  {
2196  newvar = search_indexed_tlist_for_non_var((Node *) phv,
2197  context->outer_itlist,
2198  OUTER_VAR);
2199  if (newvar)
2200  return (Node *) newvar;
2201  }
2202  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2203  {
2204  newvar = search_indexed_tlist_for_non_var((Node *) phv,
2205  context->inner_itlist,
2206  INNER_VAR);
2207  if (newvar)
2208  return (Node *) newvar;
2209  }
2210 
2211  /* If not supplied by input plans, evaluate the contained expr */
2212  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2213  }
2214  if (IsA(node, Param))
2215  return fix_param_node(context->root, (Param *) node);
2216  /* Try matching more complex expressions too, if tlists have any */
2217  if (context->outer_itlist && context->outer_itlist->has_non_vars)
2218  {
2219  newvar = search_indexed_tlist_for_non_var(node,
2220  context->outer_itlist,
2221  OUTER_VAR);
2222  if (newvar)
2223  return (Node *) newvar;
2224  }
2225  if (context->inner_itlist && context->inner_itlist->has_non_vars)
2226  {
2227  newvar = search_indexed_tlist_for_non_var(node,
2228  context->inner_itlist,
2229  INNER_VAR);
2230  if (newvar)
2231  return (Node *) newvar;
2232  }
2233  fix_expr_common(context->root, node);
2234  return expression_tree_mutator(node,
2236  (void *) context);
2237 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
indexed_tlist * inner_itlist
Definition: setrefs.c:57
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2397
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1391
Definition: nodes.h:508
Definition: primnodes.h:141
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2144
Index varnoold
Definition: primnodes.h:154
bool has_ph_vars
Definition: setrefs.c:42
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1740
static Var * copyVar(Var *var)
Definition: setrefs.c:1275
PlannerInfo * root
Definition: setrefs.c:55
Index varno
Definition: primnodes.h:144
bool has_non_vars
Definition: setrefs.c:43
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1297
#define INNER_VAR
Definition: primnodes.h:131
#define NULL
Definition: c.h:226
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:1981
indexed_tlist * outer_itlist
Definition: setrefs.c:56
#define elog
Definition: elog.h:219
#define OUTER_VAR
Definition: primnodes.h:132
static Var * search_indexed_tlist_for_non_var(Node *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2021
static Node* fix_param_node ( PlannerInfo root,
Param p 
)
static

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

1392 {
1393  if (p->paramkind == PARAM_MULTIEXPR)
1394  {
1395  int subqueryid = p->paramid >> 16;
1396  int colno = p->paramid & 0xFFFF;
1397  List *params;
1398 
1399  if (subqueryid <= 0 ||
1400  subqueryid > list_length(root->multiexpr_params))
1401  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1402  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1403  if (colno <= 0 || colno > list_length(params))
1404  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1405  return copyObject(list_nth(params, colno - 1));
1406  }
1407  return copyObject(p);
1408 }
ParamKind paramkind
Definition: primnodes.h:222
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
List * multiexpr_params
Definition: relation.h:229
#define ERROR
Definition: elog.h:43
void * list_nth(const List *list, int n)
Definition: list.c:410
int paramid
Definition: primnodes.h:223
static int list_length(const List *l)
Definition: pg_list.h:89
#define elog
Definition: elog.h:219
Definition: pg_list.h:45
static Node * fix_scan_expr ( PlannerInfo root,
Node node,
int  rtoffset 
)
static

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

1422 {
1423  fix_scan_expr_context context;
1424 
1425  context.root = root;
1426  context.rtoffset = rtoffset;
1427 
1428  if (rtoffset != 0 ||
1429  root->multiexpr_params != NIL ||
1430  root->glob->lastPHId != 0 ||
1431  root->minmax_aggs != NIL)
1432  {
1433  return fix_scan_expr_mutator(node, &context);
1434  }
1435  else
1436  {
1437  /*
1438  * If rtoffset == 0, we don't need to change any Vars, and if there
1439  * are no MULTIEXPR subqueries then we don't need to replace
1440  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1441  * we won't need to remove them, and if there are no minmax Aggrefs we
1442  * won't need to replace them. Then it's OK to just scribble on the
1443  * input node tree instead of copying (since the only change, filling
1444  * in any unset opfuncid fields, is harmless). This saves just enough
1445  * cycles to be noticeable on trivial queries.
1446  */
1447  (void) fix_scan_expr_walker(node, &context);
1448  return node;
1449  }
1450 }
#define NIL
Definition: pg_list.h:69
PlannerInfo * root
Definition: setrefs.c:49
List * minmax_aggs
Definition: relation.h:280
List * multiexpr_params
Definition: relation.h:229
PlannerGlobal * glob
Definition: relation.h:154
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1522
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1453
Index lastPHId
Definition: relation.h:116
static Node * fix_scan_expr_mutator ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1453 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, NULL, 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().

1454 {
1455  if (node == NULL)
1456  return NULL;
1457  if (IsA(node, Var))
1458  {
1459  Var *var = copyVar((Var *) node);
1460 
1461  Assert(var->varlevelsup == 0);
1462 
1463  /*
1464  * We should not see any Vars marked INNER_VAR or OUTER_VAR. But an
1465  * indexqual expression could contain INDEX_VAR Vars.
1466  */
1467  Assert(var->varno != INNER_VAR);
1468  Assert(var->varno != OUTER_VAR);
1469  if (!IS_SPECIAL_VARNO(var->varno))
1470  var->varno += context->rtoffset;
1471  if (var->varnoold > 0)
1472  var->varnoold += context->rtoffset;
1473  return (Node *) var;
1474  }
1475  if (IsA(node, Param))
1476  return fix_param_node(context->root, (Param *) node);
1477  if (IsA(node, Aggref))
1478  {
1479  Aggref *aggref = (Aggref *) node;
1480 
1481  /* See if the Aggref should be replaced by a Param */
1482  if (context->root->minmax_aggs != NIL &&
1483  list_length(aggref->args) == 1)
1484  {
1485  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1486  ListCell *lc;
1487 
1488  foreach(lc, context->root->minmax_aggs)
1489  {
1490  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1491 
1492  if (mminfo->aggfnoid == aggref->aggfnoid &&
1493  equal(mminfo->target, curTarget->expr))
1494  return (Node *) copyObject(mminfo->param);
1495  }
1496  }
1497  /* If no match, just fall through to process it normally */
1498  }
1499  if (IsA(node, CurrentOfExpr))
1500  {
1501  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1502 
1503  Assert(cexpr->cvarno != INNER_VAR);
1504  Assert(cexpr->cvarno != OUTER_VAR);
1505  if (!IS_SPECIAL_VARNO(cexpr->cvarno))
1506  cexpr->cvarno += context->rtoffset;
1507  return (Node *) cexpr;
1508  }
1509  if (IsA(node, PlaceHolderVar))
1510  {
1511  /* At scan level, we should always just evaluate the contained expr */
1512  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1513 
1514  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1515  }
1516  fix_expr_common(context->root, node);
1518  (void *) context);
1519 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Index varlevelsup
Definition: primnodes.h:151
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2397
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1391
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
Param * param
Definition: relation.h:1956
PlannerInfo * root
Definition: setrefs.c:49
Definition: nodes.h:508
List * args
Definition: primnodes.h:279
List * minmax_aggs
Definition: relation.h:280
Definition: primnodes.h:141
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
Index varnoold
Definition: primnodes.h:154
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:135
#define linitial(l)
Definition: pg_list.h:110
Expr * phexpr
Definition: relation.h:1740
static Var * copyVar(Var *var)
Definition: setrefs.c:1275
Index varno
Definition: primnodes.h:144
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1453
Oid aggfnoid
Definition: primnodes.h:272
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1297
#define INNER_VAR
Definition: primnodes.h:131
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
Expr * target
Definition: relation.h:1952
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
#define OUTER_VAR
Definition: primnodes.h:132
static bool fix_scan_expr_walker ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1522 of file setrefs.c.

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

Referenced by fix_scan_expr().

1523 {
1524  if (node == NULL)
1525  return false;
1526  Assert(!IsA(node, PlaceHolderVar));
1527  fix_expr_common(context->root, node);
1529  (void *) context);
1530 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
PlannerInfo * root
Definition: setrefs.c:49
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1522
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1297
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1852
static Node * fix_upper_expr ( PlannerInfo root,
Node node,
indexed_tlist subplan_itlist,
Index  newvarno,
int  rtoffset 
)
static

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

2275 {
2276  fix_upper_expr_context context;
2277 
2278  context.root = root;
2279  context.subplan_itlist = subplan_itlist;
2280  context.newvarno = newvarno;
2281  context.rtoffset = rtoffset;
2282  return fix_upper_expr_mutator(node, &context);
2283 }
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2286
PlannerInfo * root
Definition: setrefs.c:64
indexed_tlist * subplan_itlist
Definition: setrefs.c:65
static Node * fix_upper_expr_mutator ( Node node,
fix_upper_expr_context context 
)
static

Definition at line 2286 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_non_vars, indexed_tlist::has_ph_vars, IsA, lfirst, linitial, list_length(), PlannerInfo::minmax_aggs, fix_upper_expr_context::newvarno, NIL, NULL, 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().

2287 {
2288  Var *newvar;
2289 
2290  if (node == NULL)
2291  return NULL;
2292  if (IsA(node, Var))
2293  {
2294  Var *var = (Var *) node;
2295 
2296  newvar = search_indexed_tlist_for_var(var,
2297  context->subplan_itlist,
2298  context->newvarno,
2299  context->rtoffset);
2300  if (!newvar)
2301  elog(ERROR, "variable not found in subplan target list");
2302  return (Node *) newvar;
2303  }
2304  if (IsA(node, PlaceHolderVar))
2305  {
2306  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2307 
2308  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2309  if (context->subplan_itlist->has_ph_vars)
2310  {
2311  newvar = search_indexed_tlist_for_non_var((Node *) phv,
2312  context->subplan_itlist,
2313  context->newvarno);
2314  if (newvar)
2315  return (Node *) newvar;
2316  }
2317  /* If not supplied by input plan, evaluate the contained expr */
2318  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2319  }
2320  if (IsA(node, Param))
2321  return fix_param_node(context->root, (Param *) node);
2322  if (IsA(node, Aggref))
2323  {
2324  Aggref *aggref = (Aggref *) node;
2325 
2326  /* See if the Aggref should be replaced by a Param */
2327  if (context->root->minmax_aggs != NIL &&
2328  list_length(aggref->args) == 1)
2329  {
2330  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2331  ListCell *lc;
2332 
2333  foreach(lc, context->root->minmax_aggs)
2334  {
2335  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2336 
2337  if (mminfo->aggfnoid == aggref->aggfnoid &&
2338  equal(mminfo->target, curTarget->expr))
2339  return (Node *) copyObject(mminfo->param);
2340  }
2341  }
2342  /* If no match, just fall through to process it normally */
2343  }
2344  /* Try matching more complex expressions too, if tlist has any */
2345  if (context->subplan_itlist->has_non_vars)
2346  {
2347  newvar = search_indexed_tlist_for_non_var(node,
2348  context->subplan_itlist,
2349  context->newvarno);
2350  if (newvar)
2351  return (Node *) newvar;
2352  }
2353  fix_expr_common(context->root, node);
2354  return expression_tree_mutator(node,
2356  (void *) context);
2357 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2397
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1391
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
Param * param
Definition: relation.h:1956
Definition: nodes.h:508
List * args
Definition: primnodes.h:279
List * minmax_aggs
Definition: relation.h:280
Definition: primnodes.h:141
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
bool has_ph_vars
Definition: setrefs.c:42
#define linitial(l)
Definition: pg_list.h:110
#define ERROR
Definition: elog.h:43
Expr * phexpr
Definition: relation.h:1740
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2286
bool has_non_vars
Definition: setrefs.c:43
Oid aggfnoid
Definition: primnodes.h:272
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1297
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Expr * target
Definition: relation.h:1952
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:1981
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
PlannerInfo * root
Definition: setrefs.c:64
#define elog
Definition: elog.h:219
indexed_tlist * subplan_itlist
Definition: setrefs.c:65
static Var * search_indexed_tlist_for_non_var(Node *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2021
static bool flatten_rtes_walker ( Node node,
PlannerGlobal glob 
)
static

Definition at line 347 of file setrefs.c.

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

Referenced by flatten_unplanned_rtes().

348 {
349  if (node == NULL)
350  return false;
351  if (IsA(node, RangeTblEntry))
352  {
353  RangeTblEntry *rte = (RangeTblEntry *) node;
354 
355  /* As above, we need only save relation RTEs */
356  if (rte->rtekind == RTE_RELATION)
357  add_rte_to_flat_rtable(glob, rte);
358  return false;
359  }
360  if (IsA(node, Query))
361  {
362  /* Recurse into subselects */
363  return query_tree_walker((Query *) node,
365  (void *) glob,
367  }
369  (void *) glob);
370 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2238
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:383
#define QTW_EXAMINE_RTES
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:347
#define NULL
Definition: c.h:226
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1852
RTEKind rtekind
Definition: parsenodes.h:882
static void flatten_unplanned_rtes ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 337 of file setrefs.c.

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

Referenced by add_rtes_to_flat_rtable().

338 {
339  /* Use query_tree_walker to find all RTEs in the parse tree */
340  (void) query_tree_walker(rte->subquery,
342  (void *) glob,
344 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2238
#define QTW_EXAMINE_RTES
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:347
Query * subquery
Definition: parsenodes.h:900
void record_plan_function_dependency ( PlannerInfo root,
Oid  funcid 
)

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

2438 {
2439  /*
2440  * For performance reasons, we don't bother to track built-in functions;
2441  * we just assume they'll never change (or at least not in ways that'd
2442  * invalidate plans using them). For this purpose we can consider a
2443  * built-in function to be one with OID less than FirstBootstrapObjectId.
2444  * Note that the OID generator guarantees never to generate such an OID
2445  * after startup, even at OID wraparound.
2446  */
2447  if (funcid >= (Oid) FirstBootstrapObjectId)
2448  {
2449  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2450 
2451  /*
2452  * It would work to use any syscache on pg_proc, but the easiest is
2453  * PROCOID since we already have the function's OID at hand. Note
2454  * that plancache.c knows we use PROCOID.
2455  */
2456  inval_item->cacheId = PROCOID;
2457  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2458  ObjectIdGetDatum(funcid));
2459 
2460  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2461  }
2462 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:185
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:515
PlannerGlobal * glob
Definition: relation.h:154
#define FirstBootstrapObjectId
Definition: transam.h:93
List * lappend(List *list, void *datum)
Definition: list.c:128
List * invalItems
Definition: relation.h:112
uint32 hashValue
Definition: plannodes.h:964
#define makeNode(_type_)
Definition: nodes.h:556
static Var * search_indexed_tlist_for_non_var ( Node node,
indexed_tlist itlist,
Index  newvarno 
)
static

Definition at line 2021 of file setrefs.c.

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

Referenced by fix_join_expr_mutator(), and fix_upper_expr_mutator().

2023 {
2024  TargetEntry *tle;
2025 
2026  /*
2027  * If it's a simple Const, replacing it with a Var is silly, even if there
2028  * happens to be an identical Const below; a Var is more expensive to
2029  * execute than a Const. What's more, replacing it could confuse some
2030  * places in the executor that expect to see simple Consts for, eg,
2031  * dropped columns.
2032  */
2033  if (IsA(node, Const))
2034  return NULL;
2035 
2036  tle = tlist_member(node, itlist->tlist);
2037  if (tle)
2038  {
2039  /* Found a matching subplan output expression */
2040  Var *newvar;
2041 
2042  newvar = makeVarFromTargetEntry(newvarno, tle);
2043  newvar->varnoold = 0; /* wasn't ever a plain Var */
2044  newvar->varoattno = 0;
2045  return newvar;
2046  }
2047  return NULL; /* no match */
2048 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:104
Definition: primnodes.h:141
TargetEntry * tlist_member(Node *node, List *targetlist)
Definition: tlist.c:54
Index varnoold
Definition: primnodes.h:154
#define NULL
Definition: c.h:226
AttrNumber varoattno
Definition: primnodes.h:155
List * tlist
Definition: setrefs.c:40
static Var * search_indexed_tlist_for_sortgroupref ( Node node,
Index  sortgroupref,
indexed_tlist itlist,
Index  newvarno 
)
static

Definition at line 2062 of file setrefs.c.

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

Referenced by set_upper_references().

2066 {
2067  ListCell *lc;
2068 
2069  foreach(lc, itlist->tlist)
2070  {
2071  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2072 
2073  /* The equal() check should be redundant, but let's be paranoid */
2074  if (tle->ressortgroupref == sortgroupref &&
2075  equal(node, tle->expr))
2076  {
2077  /* Found a matching subplan output expression */
2078  Var *newvar;
2079 
2080  newvar = makeVarFromTargetEntry(newvarno, tle);
2081  newvar->varnoold = 0; /* wasn't ever a plain Var */
2082  newvar->varoattno = 0;
2083  return newvar;
2084  }
2085  }
2086  return NULL; /* no match */
2087 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:104
Definition: primnodes.h:141
Index varnoold
Definition: primnodes.h:154
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
AttrNumber varoattno
Definition: primnodes.h:155
Index ressortgroupref
Definition: primnodes.h:1333
List * tlist
Definition: setrefs.c:40
static Var * search_indexed_tlist_for_var ( Var var,
indexed_tlist itlist,
Index  newvarno,
int  rtoffset 
)
static

Definition at line 1981 of file setrefs.c.

References copyVar(), i, NULL, 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().

1983 {
1984  Index varno = var->varno;
1985  AttrNumber varattno = var->varattno;
1986  tlist_vinfo *vinfo;
1987  int i;
1988 
1989  vinfo = itlist->vars;
1990  i = itlist->num_vars;
1991  while (i-- > 0)
1992  {
1993  if (vinfo->varno == varno && vinfo->varattno == varattno)
1994  {
1995  /* Found a match */
1996  Var *newvar = copyVar(var);
1997 
1998  newvar->varno = newvarno;
1999  newvar->varattno = vinfo->resno;
2000  if (newvar->varnoold > 0)
2001  newvar->varnoold += rtoffset;
2002  return newvar;
2003  }
2004  vinfo++;
2005  }
2006  return NULL; /* no match */
2007 }
Index varno
Definition: setrefs.c:33
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:44
AttrNumber resno
Definition: setrefs.c:35
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
AttrNumber varattno
Definition: setrefs.c:34
Index varnoold
Definition: primnodes.h:154
int num_vars
Definition: setrefs.c:41
static Var * copyVar(Var *var)
Definition: setrefs.c:1275
Index varno
Definition: primnodes.h:144
unsigned int Index
Definition: c.h:362
#define NULL
Definition: c.h:226
int i
int16 AttrNumber
Definition: attnum.h:21
static void set_customscan_references ( PlannerInfo root,
CustomScan cscan,
int  rtoffset 
)
static

Definition at line 1200 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, NULL, pfree(), Scan::plan, Plan::qual, CustomScan::scan, Scan::scanrelid, set_plan_refs(), and Plan::targetlist.

Referenced by set_plan_refs().

1203 {
1204  ListCell *lc;
1205 
1206  /* Adjust scanrelid if it's valid */
1207  if (cscan->scan.scanrelid > 0)
1208  cscan->scan.scanrelid += rtoffset;
1209 
1210  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1211  {
1212  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1214 
1215  cscan->scan.plan.targetlist = (List *)
1216  fix_upper_expr(root,
1217  (Node *) cscan->scan.plan.targetlist,
1218  itlist,
1219  INDEX_VAR,
1220  rtoffset);
1221  cscan->scan.plan.qual = (List *)
1222  fix_upper_expr(root,
1223  (Node *) cscan->scan.plan.qual,
1224  itlist,
1225  INDEX_VAR,
1226  rtoffset);
1227  cscan->custom_exprs = (List *)
1228  fix_upper_expr(root,
1229  (Node *) cscan->custom_exprs,
1230  itlist,
1231  INDEX_VAR,
1232  rtoffset);
1233  pfree(itlist);
1234  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1235  cscan->custom_scan_tlist =
1236  fix_scan_list(root, cscan->custom_scan_tlist, rtoffset);
1237  }
1238  else
1239  {
1240  /* Adjust tlist, qual, custom_exprs in the standard way */
1241  cscan->scan.plan.targetlist =
1242  fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
1243  cscan->scan.plan.qual =
1244  fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
1245  cscan->custom_exprs =
1246  fix_scan_list(root, cscan->custom_exprs, rtoffset);
1247  }
1248 
1249  /* Adjust child plan-nodes recursively, if needed */
1250  foreach(lc, cscan->custom_plans)
1251  {
1252  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1253  }
1254 
1255  /* Adjust custom_relids if needed */
1256  if (rtoffset > 0)
1257  {
1258  Bitmapset *tempset = NULL;
1259  int x = -1;
1260 
1261  while ((x = bms_next_member(cscan->custom_relids, x)) >= 0)
1262  tempset = bms_add_member(tempset, x + rtoffset);
1263  cscan->custom_relids = tempset;
1264  }
1265 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
Index scanrelid
Definition: plannodes.h:306
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:907
Definition: nodes.h:508
List * custom_exprs
Definition: plannodes.h:586
List * custom_plans
Definition: plannodes.h:585
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:433
void pfree(void *pointer)
Definition: mcxt.c:992
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2270
Scan scan
Definition: plannodes.h:582
#define NULL
Definition: c.h:226
#define lfirst(lc)
Definition: pg_list.h:106
List * custom_scan_tlist
Definition: plannodes.h:588
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
Bitmapset * custom_relids
Definition: plannodes.h:590
List * targetlist
Definition: plannodes.h:129
#define INDEX_VAR
Definition: primnodes.h:133
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:81
static void set_dummy_tlist_references ( Plan plan,
int  rtoffset 
)
static

Definition at line 1814 of file setrefs.c.

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

Referenced by set_plan_refs().

1815 {
1816  List *output_targetlist;
1817  ListCell *l;
1818 
1819  output_targetlist = NIL;
1820  foreach(l, plan->targetlist)
1821  {
1822  TargetEntry *tle = (TargetEntry *) lfirst(l);
1823  Var *oldvar = (Var *) tle->expr;
1824  Var *newvar;
1825 
1826  /*
1827  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
1828  * as Consts, not Vars referencing Consts. Here, there's no speed
1829  * advantage to be had, but it makes EXPLAIN output look cleaner, and
1830  * again it avoids confusing the executor.
1831  */
1832  if (IsA(oldvar, Const))
1833  {
1834  /* just reuse the existing TLE node */
1835  output_targetlist = lappend(output_targetlist, tle);
1836  continue;
1837  }
1838 
1839  newvar = makeVar(OUTER_VAR,
1840  tle->resno,
1841  exprType((Node *) oldvar),
1842  exprTypmod((Node *) oldvar),
1843  exprCollation((Node *) oldvar),
1844  0);
1845  if (IsA(oldvar, Var))
1846  {
1847  newvar->varnoold = oldvar->varno + rtoffset;
1848  newvar->varoattno = oldvar->varattno;
1849  }
1850  else
1851  {
1852  newvar->varnoold = 0; /* wasn't ever a plain Var */
1853  newvar->varoattno = 0;
1854  }
1855 
1856  tle = flatCopyTargetEntry(tle);
1857  tle->expr = (Expr *) newvar;
1858  output_targetlist = lappend(output_targetlist, tle);
1859  }
1860  plan->targetlist = output_targetlist;
1861 
1862  /* We don't touch plan->qual here */
1863 }
#define NIL
Definition: pg_list.h:69
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:273
Definition: nodes.h:508
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
AttrNumber resno
Definition: primnodes.h:1331
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:268
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:67
List * lappend(List *list, void *datum)
Definition: list.c:128
Index varno
Definition: primnodes.h:144
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:42
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:745
List * targetlist
Definition: plannodes.h:129
Definition: pg_list.h:45
#define OUTER_VAR
Definition: primnodes.h:132
static void set_foreignscan_references ( PlannerInfo root,
ForeignScan fscan,
int  rtoffset 
)
static

Definition at line 1122 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, NULL, pfree(), Scan::plan, Plan::qual, ForeignScan::scan, Scan::scanrelid, and Plan::targetlist.

Referenced by set_plan_refs().

1125 {
1126  /* Adjust scanrelid if it's valid */
1127  if (fscan->scan.scanrelid > 0)
1128  fscan->scan.scanrelid += rtoffset;
1129 
1130  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1131  {
1132  /*
1133  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1134  * foreign scan tuple
1135  */
1137 
1138  fscan->scan.plan.targetlist = (List *)
1139  fix_upper_expr(root,
1140  (Node *) fscan->scan.plan.targetlist,
1141  itlist,
1142  INDEX_VAR,
1143  rtoffset);
1144  fscan->scan.plan.qual = (List *)
1145  fix_upper_expr(root,
1146  (Node *) fscan->scan.plan.qual,
1147  itlist,
1148  INDEX_VAR,
1149  rtoffset);
1150  fscan->fdw_exprs = (List *)
1151  fix_upper_expr(root,
1152  (Node *) fscan->fdw_exprs,
1153  itlist,
1154  INDEX_VAR,
1155  rtoffset);
1156  fscan->fdw_recheck_quals = (List *)
1157  fix_upper_expr(root,
1158  (Node *) fscan->fdw_recheck_quals,
1159  itlist,
1160  INDEX_VAR,
1161  rtoffset);
1162  pfree(itlist);
1163  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1164  fscan->fdw_scan_tlist =
1165  fix_scan_list(root, fscan->fdw_scan_tlist, rtoffset);
1166  }
1167  else
1168  {
1169  /*
1170  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1171  * way
1172  */
1173  fscan->scan.plan.targetlist =
1174  fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset);
1175  fscan->scan.plan.qual =
1176  fix_scan_list(root, fscan->scan.plan.qual, rtoffset);
1177  fscan->fdw_exprs =
1178  fix_scan_list(root, fscan->fdw_exprs, rtoffset);
1179  fscan->fdw_recheck_quals =
1180  fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
1181  }
1182 
1183  /* Adjust fs_relids if needed */
1184  if (rtoffset > 0)
1185  {
1186  Bitmapset *tempset = NULL;
1187  int x = -1;
1188 
1189  while ((x = bms_next_member(fscan->fs_relids, x)) >= 0)
1190  tempset = bms_add_member(tempset, x + rtoffset);
1191  fscan->fs_relids = tempset;
1192  }
1193 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
Index scanrelid
Definition: plannodes.h:306
List * fdw_exprs
Definition: plannodes.h:556
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:907
Definition: nodes.h:508
List * fdw_scan_tlist
Definition: plannodes.h:558
void pfree(void *pointer)
Definition: mcxt.c:992
List * fdw_recheck_quals
Definition: plannodes.h:559
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2270
#define NULL
Definition: c.h:226
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:668
List * targetlist
Definition: plannodes.h:129
#define INDEX_VAR
Definition: primnodes.h:133
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:81
Bitmapset * fs_relids
Definition: plannodes.h:561
static Plan * set_indexonlyscan_references ( PlannerInfo root,
IndexOnlyScan plan,
int  rtoffset 
)
static

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

957 {
958  indexed_tlist *index_itlist;
959 
960  index_itlist = build_tlist_index(plan->indextlist);
961 
962  plan->scan.scanrelid += rtoffset;
963  plan->scan.plan.targetlist = (List *)
964  fix_upper_expr(root,
965  (Node *) plan->scan.plan.targetlist,
966  index_itlist,
967  INDEX_VAR,
968  rtoffset);
969  plan->scan.plan.qual = (List *)
970  fix_upper_expr(root,
971  (Node *) plan->scan.plan.qual,
972  index_itlist,
973  INDEX_VAR,
974  rtoffset);
975  /* indexqual is already transformed to reference index columns */
976  plan->indexqual = fix_scan_list(root, plan->indexqual, rtoffset);
977  /* indexorderby is already transformed to reference index columns */
978  plan->indexorderby = fix_scan_list(root, plan->indexorderby, rtoffset);
979  /* indextlist must NOT be transformed to reference index columns */
980  plan->indextlist = fix_scan_list(root, plan->indextlist, rtoffset);
981 
982  pfree(index_itlist);
983 
984  return (Plan *) plan;
985 }
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
Index scanrelid
Definition: plannodes.h:306
Definition: nodes.h:508
void pfree(void *pointer)
Definition: mcxt.c:992
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2270
List * indextlist
Definition: plannodes.h:398
List * indexorderby
Definition: plannodes.h:397
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
List * indexqual
Definition: plannodes.h:396
List * targetlist
Definition: plannodes.h:129
#define INDEX_VAR
Definition: primnodes.h:133
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:81
static void set_join_references ( PlannerInfo root,
Join join,
int  rtoffset 
)
static

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

1542 {
1543  Plan *outer_plan = join->plan.lefttree;
1544  Plan *inner_plan = join->plan.righttree;
1545  indexed_tlist *outer_itlist;
1546  indexed_tlist *inner_itlist;
1547 
1548  outer_itlist = build_tlist_index(outer_plan->targetlist);
1549  inner_itlist = build_tlist_index(inner_plan->targetlist);
1550 
1551  /*
1552  * First process the joinquals (including merge or hash clauses). These
1553  * are logically below the join so they can always use all values
1554  * available from the input tlists. It's okay to also handle
1555  * NestLoopParams now, because those couldn't refer to nullable
1556  * subexpressions.
1557  */
1558  join->joinqual = fix_join_expr(root,
1559  join->joinqual,
1560  outer_itlist,
1561  inner_itlist,
1562  (Index) 0,
1563  rtoffset);
1564 
1565  /* Now do join-type-specific stuff */
1566  if (IsA(join, NestLoop))
1567  {
1568  NestLoop *nl = (NestLoop *) join;
1569  ListCell *lc;
1570 
1571  foreach(lc, nl->nestParams)
1572  {
1573  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1574 
1575  nlp->paramval = (Var *) fix_upper_expr(root,
1576  (Node *) nlp->paramval,
1577  outer_itlist,
1578  OUTER_VAR,
1579  rtoffset);
1580  /* Check we replaced any PlaceHolderVar with simple Var */
1581  if (!(IsA(nlp->paramval, Var) &&
1582  nlp->paramval->varno == OUTER_VAR))
1583  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
1584  }
1585  }
1586  else if (IsA(join, MergeJoin))
1587  {
1588  MergeJoin *mj = (MergeJoin *) join;
1589 
1590  mj->mergeclauses = fix_join_expr(root,
1591  mj->mergeclauses,
1592  outer_itlist,
1593  inner_itlist,
1594  (Index) 0,
1595  rtoffset);
1596  }
1597  else if (IsA(join, HashJoin))
1598  {
1599  HashJoin *hj = (HashJoin *) join;
1600 
1601  hj->hashclauses = fix_join_expr(root,
1602  hj->hashclauses,
1603  outer_itlist,
1604  inner_itlist,
1605  (Index) 0,
1606  rtoffset);
1607  }
1608 
1609  /*
1610  * Now we need to fix up the targetlist and qpqual, which are logically
1611  * above the join. This means they should not re-use any input expression
1612  * that was computed in the nullable side of an outer join. Vars and
1613  * PlaceHolderVars are fine, so we can implement this restriction just by
1614  * clearing has_non_vars in the indexed_tlist structs.
1615  *
1616  * XXX This is a grotty workaround for the fact that we don't clearly
1617  * distinguish between a Var appearing below an outer join and the "same"
1618  * Var appearing above it. If we did, we'd not need to hack the matching
1619  * rules this way.
1620  */
1621  switch (join->jointype)
1622  {
1623  case JOIN_LEFT:
1624  case JOIN_SEMI:
1625  case JOIN_ANTI:
1626  inner_itlist->has_non_vars = false;
1627  break;
1628  case JOIN_RIGHT:
1629  outer_itlist->has_non_vars = false;
1630  break;
1631  case JOIN_FULL:
1632  outer_itlist->has_non_vars = false;
1633  inner_itlist->has_non_vars = false;
1634  break;
1635  default:
1636  break;
1637  }
1638 
1639  join->plan.targetlist = fix_join_expr(root,
1640  join->plan.targetlist,
1641  outer_itlist,
1642  inner_itlist,
1643  (Index) 0,
1644  rtoffset);
1645  join->plan.qual = fix_join_expr(root,
1646  join->plan.qual,
1647  outer_itlist,
1648  inner_itlist,
1649  (Index) 0,
1650  rtoffset);
1651 
1652  pfree(outer_itlist);
1653  pfree(inner_itlist);
1654 }
List * qual
Definition: plannodes.h:130
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
List * nestParams
Definition: plannodes.h:637
List * hashclauses
Definition: plannodes.h:676
Definition: nodes.h:508
Definition: primnodes.h:141
List * mergeclauses
Definition: plannodes.h:661
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:2126
JoinType jointype
Definition: plannodes.h:619
struct Plan * righttree
Definition: plannodes.h:132
void pfree(void *pointer)
Definition: mcxt.c:992
Var * paramval
Definition: plannodes.h:644
#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:2270
Index varno
Definition: primnodes.h:144
bool has_non_vars
Definition: setrefs.c:43
unsigned int Index
Definition: c.h:362
#define lfirst(lc)
Definition: pg_list.h:106
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
struct Plan * lefttree
Definition: plannodes.h:131
List * targetlist
Definition: plannodes.h:129
#define elog
Definition: elog.h:219
#define OUTER_VAR
Definition: primnodes.h:132
List * joinqual
Definition: plannodes.h:620
Plan plan
Definition: plannodes.h:618
Plan* set_plan_references ( PlannerInfo root,
Plan plan 
)

Definition at line 209 of file setrefs.c.

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

Referenced by set_subqueryscan_references(), and standard_planner().

210 {
211  PlannerGlobal *glob = root->glob;
212  int rtoffset = list_length(glob->finalrtable);
213  ListCell *lc;
214 
215  /*
216  * Add all the query's RTEs to the flattened rangetable. The live ones
217  * will have their rangetable indexes increased by rtoffset. (Additional
218  * RTEs, not referenced by the Plan tree, might get added after those.)
219  */
220  add_rtes_to_flat_rtable(root, false);
221 
222  /*
223  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
224  */
225  foreach(lc, root->rowMarks)
226  {
228  PlanRowMark *newrc;
229 
230  /* flat copy is enough since all fields are scalars */
231  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
232  memcpy(newrc, rc, sizeof(PlanRowMark));
233 
234  /* adjust indexes ... but *not* the rowmarkId */
235  newrc->rti += rtoffset;
236  newrc->prti += rtoffset;
237 
238  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
239  }
240 
241  /* Now fix the Plan tree */
242  return set_plan_refs(root, plan, rtoffset);
243 }
List * rowMarks
Definition: relation.h:251
#define castNode(_type_, nodeptr)
Definition: nodes.h:577
Index prti
Definition: plannodes.h:941
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:433
PlannerGlobal * glob
Definition: relation.h:154
List * lappend(List *list, void *datum)
Definition: list.c:128
Index rti
Definition: plannodes.h:940
#define lfirst(lc)
Definition: pg_list.h:106
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:251
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:891
List * finalrowmarks
Definition: relation.h:106
static Plan * set_plan_refs ( PlannerInfo root,
Plan plan,
int  rtoffset 
)
static

Definition at line 433 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(), 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, NULL, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, 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, ModifyTable::rowMarks, LockRows::rowMarks, PlanRowMark::rti, SampleScan::scan, IndexScan::scan, BitmapIndexScan::scan, BitmapHeapScan::scan, TidScan::scan, FunctionScan::scan, ValuesScan::scan, CteScan::scan, WorkTableScan::scan, Scan::scanrelid, set_customscan_references(), set_dummy_tlist_references(), set_foreignscan_references(), set_indexonlyscan_references(), set_join_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_Group, T_Hash, T_HashJoin, T_IndexOnlyScan, T_IndexScan, T_Limit, T_LockRows, T_Material, T_MergeAppend, T_MergeJoin, T_ModifyTable, T_NestLoop, T_ProjectSet, T_RecursiveUnion, T_Result, T_SampleScan, T_SeqScan, T_SetOp, T_Sort, T_SubqueryScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, T_WorkTableScan, SampleScan::tablesample, Plan::targetlist, TidScan::tidquals, ValuesScan::values_lists, and ModifyTable::withCheckOptionLists.

Referenced by set_customscan_references(), and set_plan_references().

434 {
435  ListCell *l;
436 
437  if (plan == NULL)
438  return NULL;
439 
440  /* Assign this node a unique ID. */
441  plan->plan_node_id = root->glob->lastPlanNodeId++;
442 
443  /*
444  * Plan-type-specific fixes
445  */
446  switch (nodeTag(plan))
447  {
448  case T_SeqScan:
449  {
450  SeqScan *splan = (SeqScan *) plan;
451 
452  splan->scanrelid += rtoffset;
453  splan->plan.targetlist =
454  fix_scan_list(root, splan->plan.targetlist, rtoffset);
455  splan->plan.qual =
456  fix_scan_list(root, splan->plan.qual, rtoffset);
457  }
458  break;
459  case T_SampleScan:
460  {
461  SampleScan *splan = (SampleScan *) plan;
462 
463  splan->scan.scanrelid += rtoffset;
464  splan->scan.plan.targetlist =
465  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
466  splan->scan.plan.qual =
467  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
468  splan->tablesample = (TableSampleClause *)
469  fix_scan_expr(root, (Node *) splan->tablesample, rtoffset);
470  }
471  break;
472  case T_IndexScan:
473  {
474  IndexScan *splan = (IndexScan *) plan;
475 
476  splan->scan.scanrelid += rtoffset;
477  splan->scan.plan.targetlist =
478  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
479  splan->scan.plan.qual =
480  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
481  splan->indexqual =
482  fix_scan_list(root, splan->indexqual, rtoffset);
483  splan->indexqualorig =
484  fix_scan_list(root, splan->indexqualorig, rtoffset);
485  splan->indexorderby =
486  fix_scan_list(root, splan->indexorderby, rtoffset);
487  splan->indexorderbyorig =
488  fix_scan_list(root, splan->indexorderbyorig, rtoffset);
489  }
490  break;
491  case T_IndexOnlyScan:
492  {
493  IndexOnlyScan *splan = (IndexOnlyScan *) plan;
494 
495  return set_indexonlyscan_references(root, splan, rtoffset);
496  }
497  break;
498  case T_BitmapIndexScan:
499  {
500  BitmapIndexScan *splan = (BitmapIndexScan *) plan;
501 
502  splan->scan.scanrelid += rtoffset;
503  /* no need to fix targetlist and qual */
504  Assert(splan->scan.plan.targetlist == NIL);
505  Assert(splan->scan.plan.qual == NIL);
506  splan->indexqual =
507  fix_scan_list(root, splan->indexqual, rtoffset);
508  splan->indexqualorig =
509  fix_scan_list(root, splan->indexqualorig, rtoffset);
510  }
511  break;
512  case T_BitmapHeapScan:
513  {
514  BitmapHeapScan *splan = (BitmapHeapScan *) plan;
515 
516  splan->scan.scanrelid += rtoffset;
517  splan->scan.plan.targetlist =
518  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
519  splan->scan.plan.qual =
520  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
521  splan->bitmapqualorig =
522  fix_scan_list(root, splan->bitmapqualorig, rtoffset);
523  }
524  break;
525  case T_TidScan:
526  {
527  TidScan *splan = (TidScan *) plan;
528 
529  splan->scan.scanrelid += rtoffset;
530  splan->scan.plan.targetlist =
531  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
532  splan->scan.plan.qual =
533  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
534  splan->tidquals =
535  fix_scan_list(root, splan->tidquals, rtoffset);
536  }
537  break;
538  case T_SubqueryScan:
539  /* Needs special treatment, see comments below */
540  return set_subqueryscan_references(root,
541  (SubqueryScan *) plan,
542  rtoffset);
543  case T_FunctionScan:
544  {
545  FunctionScan *splan = (FunctionScan *) plan;
546 
547  splan->scan.scanrelid += rtoffset;
548  splan->scan.plan.targetlist =
549  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
550  splan->scan.plan.qual =
551  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
552  splan->functions =
553  fix_scan_list(root, splan->functions, rtoffset);
554  }
555  break;
556  case T_ValuesScan:
557  {
558  ValuesScan *splan = (ValuesScan *) plan;
559 
560  splan->scan.scanrelid += rtoffset;
561  splan->scan.plan.targetlist =
562  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
563  splan->scan.plan.qual =
564  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
565  splan->values_lists =
566  fix_scan_list(root, splan->values_lists, rtoffset);
567  }
568  break;
569  case T_CteScan:
570  {
571  CteScan *splan = (CteScan *) plan;
572 
573  splan->scan.scanrelid += rtoffset;
574  splan->scan.plan.targetlist =
575  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
576  splan->scan.plan.qual =
577  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
578  }
579  break;
580  case T_WorkTableScan:
581  {
582  WorkTableScan *splan = (WorkTableScan *) plan;
583 
584  splan->scan.scanrelid += rtoffset;
585  splan->scan.plan.targetlist =
586  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
587  splan->scan.plan.qual =
588  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
589  }
590  break;
591  case T_ForeignScan:
592  set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
593  break;
594  case T_CustomScan:
595  set_customscan_references(root, (CustomScan *) plan, rtoffset);
596  break;
597 
598  case T_NestLoop:
599  case T_MergeJoin:
600  case T_HashJoin:
601  set_join_references(root, (Join *) plan, rtoffset);
602  break;
603 
604  case T_Gather:
605  set_upper_references(root, plan, rtoffset);
606  break;
607 
608  case T_Hash:
609  case T_Material:
610  case T_Sort:
611  case T_Unique:
612  case T_SetOp:
613 
614  /*
615  * These plan types don't actually bother to evaluate their
616  * targetlists, because they just return their unmodified input
617  * tuples. Even though the targetlist won't be used by the
618  * executor, we fix it up for possible use by EXPLAIN (not to
619  * mention ease of debugging --- wrong varnos are very confusing).
620  */
621  set_dummy_tlist_references(plan, rtoffset);
622 
623  /*
624  * Since these plan types don't check quals either, we should not
625  * find any qual expression attached to them.
626  */
627  Assert(plan->qual == NIL);
628  break;
629  case T_LockRows:
630  {
631  LockRows *splan = (LockRows *) plan;
632 
633  /*
634  * Like the plan types above, LockRows doesn't evaluate its
635  * tlist or quals. But we have to fix up the RT indexes in
636  * its rowmarks.
637  */
638  set_dummy_tlist_references(plan, rtoffset);
639  Assert(splan->plan.qual == NIL);
640 
641  foreach(l, splan->rowMarks)
642  {
643  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
644 
645  rc->rti += rtoffset;
646  rc->prti += rtoffset;
647  }
648  }
649  break;
650  case T_Limit:
651  {
652  Limit *splan = (Limit *) plan;
653 
654  /*
655  * Like the plan types above, Limit doesn't evaluate its tlist
656  * or quals. It does have live expressions for limit/offset,
657  * however; and those cannot contain subplan variable refs, so
658  * fix_scan_expr works for them.
659  */
660  set_dummy_tlist_references(plan, rtoffset);
661  Assert(splan->plan.qual == NIL);
662 
663  splan->limitOffset =
664  fix_scan_expr(root, splan->limitOffset, rtoffset);
665  splan->limitCount =
666  fix_scan_expr(root, splan->limitCount, rtoffset);
667  }
668  break;
669  case T_Agg:
670  {
671  Agg *agg = (Agg *) plan;
672 
673  /*
674  * If this node is combining partial-aggregation results, we
675  * must convert its Aggrefs to contain references to the
676  * partial-aggregate subexpressions that will be available
677  * from the child plan node.
678  */
679  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
680  {
681  plan->targetlist = (List *)
683  NULL);
684  plan->qual = (List *)
686  NULL);
687  }
688 
689  set_upper_references(root, plan, rtoffset);
690  }
691  break;
692  case T_Group:
693  set_upper_references(root, plan, rtoffset);
694  break;
695  case T_WindowAgg:
696  {
697  WindowAgg *wplan = (WindowAgg *) plan;
698 
699  set_upper_references(root, plan, rtoffset);
700 
701  /*
702  * Like Limit node limit/offset expressions, WindowAgg has
703  * frame offset expressions, which cannot contain subplan
704  * variable refs, so fix_scan_expr works for them.
705  */
706  wplan->startOffset =
707  fix_scan_expr(root, wplan->startOffset, rtoffset);
708  wplan->endOffset =
709  fix_scan_expr(root, wplan->endOffset, rtoffset);
710  }
711  break;
712  case T_Result:
713  {
714  Result *splan = (Result *) plan;
715 
716  /*
717  * Result may or may not have a subplan; if not, it's more
718  * like a scan node than an upper node.
719  */
720  if (splan->plan.lefttree != NULL)
721  set_upper_references(root, plan, rtoffset);
722  else
723  {
724  splan->plan.targetlist =
725  fix_scan_list(root, splan->plan.targetlist, rtoffset);
726  splan->plan.qual =
727  fix_scan_list(root, splan->plan.qual, rtoffset);
728  }
729  /* resconstantqual can't contain any subplan variable refs */
730  splan->resconstantqual =
731  fix_scan_expr(root, splan->resconstantqual, rtoffset);
732  }
733  break;
734  case T_ProjectSet:
735  set_upper_references(root, plan, rtoffset);
736  break;
737  case T_ModifyTable:
738  {
739  ModifyTable *splan = (ModifyTable *) plan;
740 
741  Assert(splan->plan.targetlist == NIL);
742  Assert(splan->plan.qual == NIL);
743 
744  splan->withCheckOptionLists =
745  fix_scan_list(root, splan->withCheckOptionLists, rtoffset);
746 
747  if (splan->returningLists)
748  {
749  List *newRL = NIL;
750  ListCell *lcrl,
751  *lcrr,
752  *lcp;
753 
754  /*
755  * Pass each per-subplan returningList through
756  * set_returning_clause_references().
757  */
759  Assert(list_length(splan->returningLists) == list_length(splan->plans));
760  forthree(lcrl, splan->returningLists,
761  lcrr, splan->resultRelations,
762  lcp, splan->plans)
763  {
764  List *rlist = (List *) lfirst(lcrl);
765  Index resultrel = lfirst_int(lcrr);
766  Plan *subplan = (Plan *) lfirst(lcp);
767 
768  rlist = set_returning_clause_references(root,
769  rlist,
770  subplan,
771  resultrel,
772  rtoffset);
773  newRL = lappend(newRL, rlist);
774  }
775  splan->returningLists = newRL;
776 
777  /*
778  * Set up the visible plan targetlist as being the same as
779  * the first RETURNING list. This is for the use of
780  * EXPLAIN; the executor won't pay any attention to the
781  * targetlist. We postpone this step until here so that
782  * we don't have to do set_returning_clause_references()
783  * twice on identical targetlists.
784  */
785  splan->plan.targetlist = copyObject(linitial(newRL));
786  }
787 
788  /*
789  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
790  * join', where the inner side is the EXCLUDED tuple.
791  * Therefore use fix_join_expr to setup the relevant variables
792  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
793  * those are already used by RETURNING and it seems better to
794  * be non-conflicting.
795  */
796  if (splan->onConflictSet)
797  {
798  indexed_tlist *itlist;
799 
800  itlist = build_tlist_index(splan->exclRelTlist);
801 
802  splan->onConflictSet =
803  fix_join_expr(root, splan->onConflictSet,
804  NULL, itlist,
806  rtoffset);
807 
808  splan->onConflictWhere = (Node *)
809  fix_join_expr(root, (List *) splan->onConflictWhere,
810  NULL, itlist,
812  rtoffset);
813 
814  pfree(itlist);
815 
816  splan->exclRelTlist =
817  fix_scan_list(root, splan->exclRelTlist, rtoffset);
818  }
819 
820  splan->nominalRelation += rtoffset;
821  splan->exclRelRTI += rtoffset;
822 
823  foreach(l, splan->resultRelations)
824  {
825  lfirst_int(l) += rtoffset;
826  }
827  foreach(l, splan->rowMarks)
828  {
829  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
830 
831  rc->rti += rtoffset;
832  rc->prti += rtoffset;
833  }
834  foreach(l, splan->plans)
835  {
836  lfirst(l) = set_plan_refs(root,
837  (Plan *) lfirst(l),
838  rtoffset);
839  }
840 
841  /*
842  * Append this ModifyTable node's final result relation RT
843  * index(es) to the global list for the plan, and set its
844  * resultRelIndex to reflect their starting position in the
845  * global list.
846  */
848  root->glob->resultRelations =
850  list_copy(splan->resultRelations));
851  }
852  break;
853  case T_Append:
854  {
855  Append *splan = (Append *) plan;
856 
857  /*
858  * Append, like Sort et al, doesn't actually evaluate its
859  * targetlist or check quals.
860  */
861  set_dummy_tlist_references(plan, rtoffset);
862  Assert(splan->plan.qual == NIL);
863  foreach(l, splan->appendplans)
864  {
865  lfirst(l) = set_plan_refs(root,
866  (Plan *) lfirst(l),
867  rtoffset);
868  }
869  }
870  break;
871  case T_MergeAppend:
872  {
873  MergeAppend *splan = (MergeAppend *) plan;
874 
875  /*
876  * MergeAppend, like Sort et al, doesn't actually evaluate its
877  * targetlist or check quals.
878  */
879  set_dummy_tlist_references(plan, rtoffset);
880  Assert(splan->plan.qual == NIL);
881  foreach(l, splan->mergeplans)
882  {
883  lfirst(l) = set_plan_refs(root,
884  (Plan *) lfirst(l),
885  rtoffset);
886  }
887  }
888  break;
889  case T_RecursiveUnion:
890  /* This doesn't evaluate targetlist or check quals either */
891  set_dummy_tlist_references(plan, rtoffset);
892  Assert(plan->qual == NIL);
893  break;
894  case T_BitmapAnd:
895  {
896  BitmapAnd *splan = (BitmapAnd *) plan;
897 
898  /* BitmapAnd works like Append, but has no tlist */
899  Assert(splan->plan.targetlist == NIL);
900  Assert(splan->plan.qual == NIL);
901  foreach(l, splan->bitmapplans)
902  {
903  lfirst(l) = set_plan_refs(root,
904  (Plan *) lfirst(l),
905  rtoffset);
906  }
907  }
908  break;
909  case T_BitmapOr:
910  {
911  BitmapOr *splan = (BitmapOr *) plan;
912 
913  /* BitmapOr works like Append, but has no tlist */
914  Assert(splan->plan.targetlist == NIL);
915  Assert(splan->plan.qual == NIL);
916  foreach(l, splan->bitmapplans)
917  {
918  lfirst(l) = set_plan_refs(root,
919  (Plan *) lfirst(l),
920  rtoffset);
921  }
922  }
923  break;
924  default:
925  elog(ERROR, "unrecognized node type: %d",
926  (int) nodeTag(plan));
927  break;
928  }
929 
930  /*
931  * Now recurse into child plans, if any
932  *
933  * NOTE: it is essential that we recurse into child plans AFTER we set
934  * subplan references in this plan's tlist and quals. If we did the
935  * reference-adjustments bottom-up, then we would fail to match this
936  * plan's var nodes against the already-modified nodes of the children.
937  */
938  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
939  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
940 
941  return plan;
942 }
List * bitmapplans
Definition: plannodes.h:281
#define NIL
Definition: pg_list.h:69
Plan plan
Definition: plannodes.h:175
List * qual
Definition: plannodes.h:130
Definition: nodes.h:75
Plan plan
Definition: plannodes.h:305
Plan plan
Definition: plannodes.h:851
Index nominalRelation
Definition: plannodes.h:204
Definition: nodes.h:77
Index scanrelid
Definition: plannodes.h:306
Plan plan
Definition: plannodes.h:837
List * withCheckOptionLists
Definition: plannodes.h:208
List * functions
Definition: plannodes.h:484
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset)
Definition: setrefs.c:1541
int resultRelIndex
Definition: plannodes.h:206
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:183
int lastPlanNodeId
Definition: relation.h:120
List * indexqual
Definition: plannodes.h:423
List * tidquals
Definition: plannodes.h:452
int plan_node_id
Definition: plannodes.h:128
List * resultRelations
Definition: relation.h:108
List * indexqualorig
Definition: plannodes.h:368
struct TableSampleClause * tablesample
Definition: plannodes.h:323
List * list_copy(const List *oldlist)
Definition: list.c:1160
Definition: nodes.h:508
Definition: nodes.h:48
Index prti
Definition: plannodes.h:941
List * list_concat(List *list1, List *list2)
Definition: list.c:321
List * values_lists
Definition: plannodes.h:495
Definition: nodes.h:73
Scan scan
Definition: plannodes.h:494
Node * limitOffset
Definition: plannodes.h:852
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:759
List * plans
Definition: plannodes.h:207
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:433
List * onConflictSet
Definition: plannodes.h:216
List * resultRelations
Definition: plannodes.h:205
static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, int rtoffset)
Definition: setrefs.c:1122
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:2126
void * copyObject(const void *from)
Definition: copyfuncs.c:4475
List * appendplans
Definition: plannodes.h:230
#define linitial_int(l)
Definition: pg_list.h:111
Node * startOffset
Definition: plannodes.h:760
Node * resconstantqual
Definition: plannodes.h:176
List * rowMarks
Definition: plannodes.h:212
struct Plan * righttree
Definition: plannodes.h:132
void pfree(void *pointer)
Definition: mcxt.c:992
#define linitial(l)
Definition: pg_list.h:110
Definition: nodes.h:45
#define ERROR
Definition: elog.h:43
List * indexorderbyorig
Definition: plannodes.h:370
#define lfirst_int(lc)
Definition: pg_list.h:107
Scan scan
Definition: plannodes.h:321
Scan scan
Definition: plannodes.h:504
Node * limitCount
Definition: plannodes.h:853
Scan scan
Definition: plannodes.h:365
Definition: nodes.h:74
PlannerGlobal * glob
Definition: relation.h:154
Node * endOffset
Definition: plannodes.h:761
static SPIPlanPtr splan
Definition: regress.c:461
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1200
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:995
List * indexqual
Definition: plannodes.h:367
List * bitmapqualorig
Definition: plannodes.h:439
List * lappend(List *list, void *datum)
Definition: list.c:128
Plan plan
Definition: plannodes.h:294
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:954
List * bitmapplans
Definition: plannodes.h:295
static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1675
unsigned int Index
Definition: c.h:362
Definition: nodes.h:79
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:1745
Index rti
Definition: plannodes.h:940
List * indexorderby
Definition: plannodes.h:369
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
AggSplit aggsplit
Definition: plannodes.h:734
List * rowMarks
Definition: plannodes.h:838
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
Scan scan
Definition: plannodes.h:451
static int list_length(const List *l)
Definition: pg_list.h:89
struct Plan * lefttree
Definition: plannodes.h:131
List * indexqualorig
Definition: plannodes.h:424
#define nodeTag(nodeptr)
Definition: nodes.h:513
List * targetlist
Definition: plannodes.h:129
Definition: nodes.h:80
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2388
List * mergeplans
Definition: plannodes.h:241
Definition: nodes.h:78
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
Definition: setrefs.c:1421
List * returningLists
Definition: plannodes.h:209
Plan plan
Definition: plannodes.h:280
Definition: plannodes.h:730
#define elog
Definition: elog.h:219
Index exclRelRTI
Definition: plannodes.h:218
Definition: pg_list.h:45
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:81
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:1814
List * exclRelTlist
Definition: plannodes.h:219
Plan plan
Definition: plannodes.h:229
Node * onConflictWhere
Definition: plannodes.h:217
Definition: nodes.h:82
static List * set_returning_clause_references ( PlannerInfo root,
List rlist,
Plan topplan,
Index  resultRelation,
int  rtoffset 
)
static

Definition at line 2388 of file setrefs.c.

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

Referenced by set_plan_refs().

2393 {
2394  indexed_tlist *itlist;
2395 
2396  /*
2397  * We can perform the desired Var fixup by abusing the fix_join_expr
2398  * machinery that formerly handled inner indexscan fixup. We search the
2399  * top plan's targetlist for Vars of non-result relations, and use
2400  * fix_join_expr to convert RETURNING Vars into references to those tlist
2401  * entries, while leaving result-rel Vars as-is.
2402  *
2403  * PlaceHolderVars will also be sought in the targetlist, but no
2404  * more-complex expressions will be. Note that it is not possible for a
2405  * PlaceHolderVar to refer to the result relation, since the result is
2406  * never below an outer join. If that case could happen, we'd have to be
2407  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2408  * expression instead.
2409  */
2410  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2411 
2412  rlist = fix_join_expr(root,
2413  rlist,
2414  itlist,
2415  NULL,
2416  resultRelation,
2417  rtoffset);
2418 
2419  pfree(itlist);
2420 
2421  return rlist;
2422 }
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:2126
void pfree(void *pointer)
Definition: mcxt.c:992
#define NULL
Definition: c.h:226
static indexed_tlist * build_tlist_index_other_vars(List *tlist, Index ignore_rel)
Definition: setrefs.c:1930
List * targetlist
Definition: plannodes.h:129
static Plan * set_subqueryscan_references ( PlannerInfo root,
SubqueryScan plan,
int  rtoffset 
)
static

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

998 {
999  RelOptInfo *rel;
1000  Plan *result;
1001 
1002  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1003  rel = find_base_rel(root, plan->scan.scanrelid);
1004 
1005  /* Recursively process the subplan */
1006  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1007 
1008  if (trivial_subqueryscan(plan))
1009  {
1010  /*
1011  * We can omit the SubqueryScan node and just pull up the subplan.
1012  */
1013  ListCell *lp,
1014  *lc;
1015 
1016  result = plan->subplan;
1017 
1018  /* We have to be sure we don't lose any initplans */
1019  result->initPlan = list_concat(plan->scan.plan.initPlan,
1020  result->initPlan);
1021 
1022  /*
1023  * We also have to transfer the SubqueryScan's result-column names
1024  * into the subplan, else columns sent to client will be improperly
1025  * labeled if this is the topmost plan level. Copy the "source
1026  * column" information too.
1027  */
1028  forboth(lp, plan->scan.plan.targetlist, lc, result->targetlist)
1029  {
1030  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1031  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1032 
1033  ctle->resname = ptle->resname;
1034  ctle->resorigtbl = ptle->resorigtbl;
1035  ctle->resorigcol = ptle->resorigcol;
1036  }
1037  }
1038  else
1039  {
1040  /*
1041  * Keep the SubqueryScan node. We have to do the processing that
1042  * set_plan_references would otherwise have done on it. Notice we do
1043  * not do set_upper_references() here, because a SubqueryScan will
1044  * always have been created with correct references to its subplan's
1045  * outputs to begin with.
1046  */
1047  plan->scan.scanrelid += rtoffset;
1048  plan->scan.plan.targetlist =
1049  fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
1050  plan->scan.plan.qual =
1051  fix_scan_list(root, plan->scan.plan.qual, rtoffset);
1052 
1053  result = (Plan *) plan;
1054  }
1055 
1056  return result;
1057 }
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
Index scanrelid
Definition: plannodes.h:306
Oid resorigtbl
Definition: primnodes.h:1335
List * list_concat(List *list1, List *list2)
Definition: list.c:321
char * resname
Definition: primnodes.h:1332
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1067
PlannerInfo * subroot
Definition: relation.h:531
#define lfirst(lc)
Definition: pg_list.h:106
List * targetlist
Definition: plannodes.h:129
AttrNumber resorigcol
Definition: primnodes.h:1336
List * initPlan
Definition: plannodes.h:133
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:209
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:219
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:81
Plan * subplan
Definition: plannodes.h:474
static void set_upper_references ( PlannerInfo root,
Plan plan,
int  rtoffset 
)
static

Definition at line 1675 of file setrefs.c.

References build_tlist_index(), TargetEntry::expr, fix_upper_expr(), flatCopyTargetEntry(), IsA, 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().

1676 {
1677  Plan *subplan = plan->lefttree;
1678  indexed_tlist *subplan_itlist;
1679  List *output_targetlist;
1680  ListCell *l;
1681 
1682  subplan_itlist = build_tlist_index(subplan->targetlist);
1683 
1684  output_targetlist = NIL;
1685  foreach(l, plan->targetlist)
1686  {
1687  TargetEntry *tle = (TargetEntry *) lfirst(l);
1688  Node *newexpr;
1689 
1690  /* If it's a non-Var sort/group item, first try to match by sortref */
1691  if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var))
1692  {
1693  newexpr = (Node *)
1695  tle->ressortgroupref,
1696  subplan_itlist,
1697  OUTER_VAR);
1698  if (!newexpr)
1699  newexpr = fix_upper_expr(root,
1700  (Node *) tle->expr,
1701  subplan_itlist,
1702  OUTER_VAR,
1703  rtoffset);
1704  }
1705  else
1706  newexpr = fix_upper_expr(root,
1707  (Node *) tle->expr,
1708  subplan_itlist,
1709  OUTER_VAR,
1710  rtoffset);
1711  tle = flatCopyTargetEntry(tle);
1712  tle->expr = (Expr *) newexpr;
1713  output_targetlist = lappend(output_targetlist, tle);
1714  }
1715  plan->targetlist = output_targetlist;
1716 
1717  plan->qual = (List *)
1718  fix_upper_expr(root,
1719  (Node *) plan->qual,
1720  subplan_itlist,
1721  OUTER_VAR,
1722  rtoffset);
1723 
1724  pfree(subplan_itlist);
1725 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:130
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
static Var * search_indexed_tlist_for_sortgroupref(Node *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2062
Definition: nodes.h:508
Definition: primnodes.h:141
void pfree(void *pointer)
Definition: mcxt.c:992
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:268
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2270
List * lappend(List *list, void *datum)
Definition: list.c:128
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:1880
struct Plan * lefttree
Definition: plannodes.h:131
List * targetlist
Definition: plannodes.h:129
Index ressortgroupref
Definition: primnodes.h:1333
Definition: pg_list.h:45
#define OUTER_VAR
Definition: primnodes.h:132
static bool trivial_subqueryscan ( SubqueryScan plan)
static

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

1068 {
1069  int attrno;
1070  ListCell *lp,
1071  *lc;
1072 
1073  if (plan->scan.plan.qual != NIL)
1074  return false;
1075 
1076  if (list_length(plan->scan.plan.targetlist) !=
1077  list_length(plan->subplan->targetlist))
1078  return false; /* tlists not same length */
1079 
1080  attrno = 1;
1081  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1082  {
1083  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1084  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1085 
1086  if (ptle->resjunk != ctle->resjunk)
1087  return false; /* tlist doesn't match junk status */
1088 
1089  /*
1090  * We accept either a Var referencing the corresponding element of the
1091  * subplan tlist, or a Const equaling the subplan element. See
1092  * generate_setop_tlist() for motivation.
1093  */
1094  if (ptle->expr && IsA(ptle->expr, Var))
1095  {
1096  Var *var = (Var *) ptle->expr;
1097 
1098  Assert(var->varno == plan->scan.scanrelid);
1099  Assert(var->varlevelsup == 0);
1100  if (var->varattno != attrno)
1101  return false; /* out of order */
1102  }
1103  else if (ptle->expr && IsA(ptle->expr, Const))
1104  {
1105  if (!equal(ptle->expr, ctle->expr))
1106  return false;
1107  }
1108  else
1109  return false;
1110 
1111  attrno++;
1112  }
1113 
1114  return true;
1115 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:130
Plan plan
Definition: plannodes.h:305
#define IsA(nodeptr, _type_)
Definition: nodes.h:559
Index varlevelsup
Definition: primnodes.h:151
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:174
Index scanrelid
Definition: plannodes.h:306
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:2870
AttrNumber varattno
Definition: primnodes.h:146
Definition: primnodes.h:141
bool resjunk
Definition: primnodes.h:1337
Index varno
Definition: primnodes.h:144
#define Assert(condition)
Definition: c.h:671
#define lfirst(lc)
Definition: pg_list.h:106
Expr * expr
Definition: primnodes.h:1330
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:129
Plan * subplan
Definition: plannodes.h:474