PostgreSQL Source Code  git master
setrefs.c File Reference
#include "postgres.h"
#include "access/transam.h"
#include "catalog/pg_type.h"
#include "nodes/makefuncs.h"
#include "nodes/nodeFuncs.h"
#include "optimizer/optimizer.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 NUM_EXEC_TLIST(parentplan)   ((parentplan)->plan_rows)
 
#define NUM_EXEC_QUAL(parentplan)   ((parentplan)->plan_rows * 2.0)
 
#define ISREGCLASSCONST(con)
 
#define fix_scan_list(root, lst, rtoffset, num_exec)   ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset, num_exec))
 

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 Planclean_up_removed_plan_level (Plan *parent, Plan *child)
 
static void set_foreignscan_references (PlannerInfo *root, ForeignScan *fscan, int rtoffset)
 
static void set_customscan_references (PlannerInfo *root, CustomScan *cscan, int rtoffset)
 
static Planset_append_references (PlannerInfo *root, Append *aplan, int rtoffset)
 
static Planset_mergeappend_references (PlannerInfo *root, MergeAppend *mplan, int rtoffset)
 
static void set_hash_references (PlannerInfo *root, Plan *plan, int rtoffset)
 
static Relids offset_relid_set (Relids relids, int rtoffset)
 
static Nodefix_scan_expr (PlannerInfo *root, Node *node, int rtoffset, double num_exec)
 
static Nodefix_scan_expr_mutator (Node *node, fix_scan_expr_context *context)
 
static bool fix_scan_expr_walker (Node *node, fix_scan_expr_context *context)
 
static void set_join_references (PlannerInfo *root, Join *join, int rtoffset)
 
static void set_upper_references (PlannerInfo *root, Plan *plan, int rtoffset)
 
static void set_param_references (PlannerInfo *root, Plan *plan)
 
static Nodeconvert_combining_aggrefs (Node *node, void *context)
 
static void set_dummy_tlist_references (Plan *plan, int rtoffset)
 
static indexed_tlistbuild_tlist_index (List *tlist)
 
static Varsearch_indexed_tlist_for_var (Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
 
static Varsearch_indexed_tlist_for_non_var (Expr *node, indexed_tlist *itlist, Index newvarno)
 
static Varsearch_indexed_tlist_for_sortgroupref (Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
 
static Listfix_join_expr (PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset, double num_exec)
 
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, double num_exec)
 
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)
 
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 Nodefix_alternative_subplan (PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
 
static indexed_tlistbuild_tlist_index_other_vars (List *tlist, Index ignore_rel)
 
void record_plan_function_dependency (PlannerInfo *root, Oid funcid)
 
void record_plan_type_dependency (PlannerInfo *root, Oid typid)
 
void extract_query_dependencies (Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
 
bool extract_query_dependencies_walker (Node *node, PlannerInfo *context)
 

Macro Definition Documentation

◆ fix_scan_list

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

◆ ISREGCLASSCONST

#define ISREGCLASSCONST (   con)
Value:
(((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
!(con)->constisnull)

Definition at line 100 of file setrefs.c.

Referenced by fix_expr_common().

◆ NUM_EXEC_QUAL

#define NUM_EXEC_QUAL (   parentplan)    ((parentplan)->plan_rows * 2.0)

◆ NUM_EXEC_TLIST

Function Documentation

◆ add_rte_to_flat_rtable()

static void add_rte_to_flat_rtable ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 446 of file setrefs.c.

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

Referenced by add_rtes_to_flat_rtable(), and flatten_rtes_walker().

447 {
448  RangeTblEntry *newrte;
449 
450  /* flat copy to duplicate all the scalar fields */
451  newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
452  memcpy(newrte, rte, sizeof(RangeTblEntry));
453 
454  /* zap unneeded sub-structure */
455  newrte->tablesample = NULL;
456  newrte->subquery = NULL;
457  newrte->joinaliasvars = NIL;
458  newrte->joinleftcols = NIL;
459  newrte->joinrightcols = NIL;
460  newrte->functions = NIL;
461  newrte->tablefunc = NULL;
462  newrte->values_lists = NIL;
463  newrte->coltypes = NIL;
464  newrte->coltypmods = NIL;
465  newrte->colcollations = NIL;
466  newrte->securityQuals = NIL;
467 
468  glob->finalrtable = lappend(glob->finalrtable, newrte);
469 
470  /*
471  * Check for RT index overflow; it's very unlikely, but if it did happen,
472  * the executor would get confused by varnos that match the special varno
473  * values.
474  */
476  ereport(ERROR,
477  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
478  errmsg("too many range table entries")));
479 
480  /*
481  * If it's a plain relation RTE, add the table to relationOids.
482  *
483  * We do this even though the RTE might be unreferenced in the plan tree;
484  * this would correspond to cases such as views that were expanded, child
485  * tables that were eliminated by constraint exclusion, etc. Schema
486  * invalidation on such a rel must still force rebuilding of the plan.
487  *
488  * Note we don't bother to avoid making duplicate list entries. We could,
489  * but it would probably cost more cycles than it would save.
490  */
491  if (newrte->rtekind == RTE_RELATION)
492  glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
493 }
#define NIL
Definition: pg_list.h:65
List * joinaliasvars
Definition: parsenodes.h:1052
List * securityQuals
Definition: parsenodes.h:1126
List * coltypmods
Definition: parsenodes.h:1103
int errcode(int sqlerrcode)
Definition: elog.c:610
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
List * colcollations
Definition: parsenodes.h:1104
List * values_lists
Definition: parsenodes.h:1075
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:175
#define ERROR
Definition: elog.h:43
TableFunc * tablefunc
Definition: parsenodes.h:1070
List * joinrightcols
Definition: parsenodes.h:1054
List * lappend(List *list, void *datum)
Definition: list.c:321
#define ereport(elevel,...)
Definition: elog.h:144
List * joinleftcols
Definition: parsenodes.h:1053
List * functions
Definition: parsenodes.h:1064
static int list_length(const List *l)
Definition: pg_list.h:149
List * relationOids
Definition: pathnodes.h:125
RTEKind rtekind
Definition: parsenodes.h:977
List * finalrtable
Definition: pathnodes.h:117
Query * subquery
Definition: parsenodes.h:1012
void * palloc(Size size)
Definition: mcxt.c:950
int errmsg(const char *fmt,...)
Definition: elog.c:821
List * coltypes
Definition: parsenodes.h:1102
struct TableSampleClause * tablesample
Definition: parsenodes.h:1007

◆ add_rtes_to_flat_rtable()

static void add_rtes_to_flat_rtable ( PlannerInfo root,
bool  recursing 
)
static

Definition at line 314 of file setrefs.c.

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

Referenced by set_plan_references().

315 {
316  PlannerGlobal *glob = root->glob;
317  Index rti;
318  ListCell *lc;
319 
320  /*
321  * Add the query's own RTEs to the flattened rangetable.
322  *
323  * At top level, we must add all RTEs so that their indexes in the
324  * flattened rangetable match up with their original indexes. When
325  * recursing, we only care about extracting relation RTEs.
326  */
327  foreach(lc, root->parse->rtable)
328  {
329  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
330 
331  if (!recursing || rte->rtekind == RTE_RELATION)
332  add_rte_to_flat_rtable(glob, rte);
333  }
334 
335  /*
336  * If there are any dead subqueries, they are not referenced in the Plan
337  * tree, so we must add RTEs contained in them to the flattened rtable
338  * separately. (If we failed to do this, the executor would not perform
339  * expected permission checks for tables mentioned in such subqueries.)
340  *
341  * Note: this pass over the rangetable can't be combined with the previous
342  * one, because that would mess up the numbering of the live RTEs in the
343  * flattened rangetable.
344  */
345  rti = 1;
346  foreach(lc, root->parse->rtable)
347  {
348  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
349 
350  /*
351  * We should ignore inheritance-parent RTEs: their contents have been
352  * pulled up into our rangetable already. Also ignore any subquery
353  * RTEs without matching RelOptInfos, as they likewise have been
354  * pulled up.
355  */
356  if (rte->rtekind == RTE_SUBQUERY && !rte->inh &&
357  rti < root->simple_rel_array_size)
358  {
359  RelOptInfo *rel = root->simple_rel_array[rti];
360 
361  if (rel != NULL)
362  {
363  Assert(rel->relid == rti); /* sanity check on array */
364 
365  /*
366  * The subquery might never have been planned at all, if it
367  * was excluded on the basis of self-contradictory constraints
368  * in our query level. In this case apply
369  * flatten_unplanned_rtes.
370  *
371  * If it was planned but the result rel is dummy, we assume
372  * that it has been omitted from our plan tree (see
373  * set_subquery_pathlist), and recurse to pull up its RTEs.
374  *
375  * Otherwise, it should be represented by a SubqueryScan node
376  * somewhere in our plan tree, and we'll pull up its RTEs when
377  * we process that plan node.
378  *
379  * However, if we're recursing, then we should pull up RTEs
380  * whether the subquery is dummy or not, because we've found
381  * that some upper query level is treating this one as dummy,
382  * and so we won't scan this level's plan tree at all.
383  */
384  if (rel->subroot == NULL)
385  flatten_unplanned_rtes(glob, rte);
386  else if (recursing ||
388  UPPERREL_FINAL, NULL)))
389  add_rtes_to_flat_rtable(rel->subroot, true);
390  }
391  }
392  rti++;
393  }
394 }
Query * parse
Definition: pathnodes.h:177
static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:400
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:446
struct RelOptInfo ** simple_rel_array
Definition: pathnodes.h:201
PlannerInfo * subroot
Definition: pathnodes.h:708
List * rtable
Definition: parsenodes.h:137
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:1417
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1192
PlannerGlobal * glob
Definition: pathnodes.h:179
Index relid
Definition: pathnodes.h:692
unsigned int Index
Definition: c.h:483
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:314
RTEKind rtekind
Definition: parsenodes.h:977

◆ build_tlist_index()

static indexed_tlist * build_tlist_index ( List tlist)
static

Definition at line 2314 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_hash_references(), set_indexonlyscan_references(), set_join_references(), set_plan_refs(), and set_upper_references().

2315 {
2316  indexed_tlist *itlist;
2317  tlist_vinfo *vinfo;
2318  ListCell *l;
2319 
2320  /* Create data structure with enough slots for all tlist entries */
2321  itlist = (indexed_tlist *)
2323  list_length(tlist) * sizeof(tlist_vinfo));
2324 
2325  itlist->tlist = tlist;
2326  itlist->has_ph_vars = false;
2327  itlist->has_non_vars = false;
2328 
2329  /* Find the Vars and fill in the index array */
2330  vinfo = itlist->vars;
2331  foreach(l, tlist)
2332  {
2333  TargetEntry *tle = (TargetEntry *) lfirst(l);
2334 
2335  if (tle->expr && IsA(tle->expr, Var))
2336  {
2337  Var *var = (Var *) tle->expr;
2338 
2339  vinfo->varno = var->varno;
2340  vinfo->varattno = var->varattno;
2341  vinfo->resno = tle->resno;
2342  vinfo++;
2343  }
2344  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2345  itlist->has_ph_vars = true;
2346  else
2347  itlist->has_non_vars = true;
2348  }
2349 
2350  itlist->num_vars = (vinfo - itlist->vars);
2351 
2352  return itlist;
2353 }
Index varno
Definition: setrefs.c:34
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
AttrNumber varattno
Definition: setrefs.c:35
bool has_ph_vars
Definition: setrefs.c:43
int num_vars
Definition: setrefs.c:42
AttrNumber resno
Definition: primnodes.h:1411
Index varno
Definition: primnodes.h:184
bool has_non_vars
Definition: setrefs.c:44
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:950
Definition: regcomp.c:224
#define offsetof(type, field)
Definition: c.h:669
List * tlist
Definition: setrefs.c:41

◆ build_tlist_index_other_vars()

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

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

2365 {
2366  indexed_tlist *itlist;
2367  tlist_vinfo *vinfo;
2368  ListCell *l;
2369 
2370  /* Create data structure with enough slots for all tlist entries */
2371  itlist = (indexed_tlist *)
2373  list_length(tlist) * sizeof(tlist_vinfo));
2374 
2375  itlist->tlist = tlist;
2376  itlist->has_ph_vars = false;
2377  itlist->has_non_vars = false;
2378 
2379  /* Find the desired Vars and fill in the index array */
2380  vinfo = itlist->vars;
2381  foreach(l, tlist)
2382  {
2383  TargetEntry *tle = (TargetEntry *) lfirst(l);
2384 
2385  if (tle->expr && IsA(tle->expr, Var))
2386  {
2387  Var *var = (Var *) tle->expr;
2388 
2389  if (var->varno != ignore_rel)
2390  {
2391  vinfo->varno = var->varno;
2392  vinfo->varattno = var->varattno;
2393  vinfo->resno = tle->resno;
2394  vinfo++;
2395  }
2396  }
2397  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2398  itlist->has_ph_vars = true;
2399  }
2400 
2401  itlist->num_vars = (vinfo - itlist->vars);
2402 
2403  return itlist;
2404 }
Index varno
Definition: setrefs.c:34
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
AttrNumber varattno
Definition: setrefs.c:35
bool has_ph_vars
Definition: setrefs.c:43
int num_vars
Definition: setrefs.c:42
AttrNumber resno
Definition: primnodes.h:1411
Index varno
Definition: primnodes.h:184
bool has_non_vars
Definition: setrefs.c:44
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:950
Definition: regcomp.c:224
#define offsetof(type, field)
Definition: c.h:669
List * tlist
Definition: setrefs.c:41

◆ clean_up_removed_plan_level()

static Plan * clean_up_removed_plan_level ( Plan parent,
Plan child 
)
static

Definition at line 1221 of file setrefs.c.

References apply_tlist_labeling(), Plan::initPlan, list_concat(), and Plan::targetlist.

Referenced by set_append_references(), set_mergeappend_references(), and set_subqueryscan_references().

1222 {
1223  /* We have to be sure we don't lose any initplans */
1224  child->initPlan = list_concat(parent->initPlan,
1225  child->initPlan);
1226 
1227  /*
1228  * We also have to transfer the parent's column labeling info into the
1229  * child, else columns sent to client will be improperly labeled if this
1230  * is the topmost plan level. resjunk and so on may be important too.
1231  */
1232  apply_tlist_labeling(child->targetlist, parent->targetlist);
1233 
1234  return child;
1235 }
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:340
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
List * targetlist
Definition: plannodes.h:136
List * initPlan
Definition: plannodes.h:140

◆ convert_combining_aggrefs()

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

Definition at line 2178 of file setrefs.c.

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

Referenced by set_plan_refs().

2179 {
2180  if (node == NULL)
2181  return NULL;
2182  if (IsA(node, Aggref))
2183  {
2184  Aggref *orig_agg = (Aggref *) node;
2185  Aggref *child_agg;
2186  Aggref *parent_agg;
2187 
2188  /* Assert we've not chosen to partial-ize any unsupported cases */
2189  Assert(orig_agg->aggorder == NIL);
2190  Assert(orig_agg->aggdistinct == NIL);
2191 
2192  /*
2193  * Since aggregate calls can't be nested, we needn't recurse into the
2194  * arguments. But for safety, flat-copy the Aggref node itself rather
2195  * than modifying it in-place.
2196  */
2197  child_agg = makeNode(Aggref);
2198  memcpy(child_agg, orig_agg, sizeof(Aggref));
2199 
2200  /*
2201  * For the parent Aggref, we want to copy all the fields of the
2202  * original aggregate *except* the args list, which we'll replace
2203  * below, and the aggfilter expression, which should be applied only
2204  * by the child not the parent. Rather than explicitly knowing about
2205  * all the other fields here, we can momentarily modify child_agg to
2206  * provide a suitable source for copyObject.
2207  */
2208  child_agg->args = NIL;
2209  child_agg->aggfilter = NULL;
2210  parent_agg = copyObject(child_agg);
2211  child_agg->args = orig_agg->args;
2212  child_agg->aggfilter = orig_agg->aggfilter;
2213 
2214  /*
2215  * Now, set up child_agg to represent the first phase of partial
2216  * aggregation. For now, assume serialization is required.
2217  */
2219 
2220  /*
2221  * And set up parent_agg to represent the second phase.
2222  */
2223  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
2224  1, NULL, false));
2226 
2227  return (Node *) parent_agg;
2228  }
2230  (void *) context);
2231 }
List * aggdistinct
Definition: primnodes.h:321
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:5415
Definition: nodes.h:528
List * args
Definition: primnodes.h:319
#define list_make1(x1)
Definition: pg_list.h:206
List * aggorder
Definition: primnodes.h:320
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:2178
#define makeNode(_type_)
Definition: nodes.h:576
#define Assert(condition)
Definition: c.h:746
Expr * aggfilter
Definition: primnodes.h:322
#define copyObject(obj)
Definition: nodes.h:644

◆ copyVar()

static Var* copyVar ( Var var)
inlinestatic

Definition at line 1576 of file setrefs.c.

References palloc().

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

1577 {
1578  Var *newvar = (Var *) palloc(sizeof(Var));
1579 
1580  *newvar = *var;
1581  return newvar;
1582 }
Definition: primnodes.h:181
void * palloc(Size size)
Definition: mcxt.c:950

◆ extract_query_dependencies()

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

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

2974 {
2975  PlannerGlobal glob;
2976  PlannerInfo root;
2977 
2978  /* Make up dummy planner state so we can use this module's machinery */
2979  MemSet(&glob, 0, sizeof(glob));
2980  glob.type = T_PlannerGlobal;
2981  glob.relationOids = NIL;
2982  glob.invalItems = NIL;
2983  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2984  glob.dependsOnRole = false;
2985 
2986  MemSet(&root, 0, sizeof(root));
2987  root.type = T_PlannerInfo;
2988  root.glob = &glob;
2989 
2990  (void) extract_query_dependencies_walker(query, &root);
2991 
2992  *relationOids = glob.relationOids;
2993  *invalItems = glob.invalItems;
2994  *hasRowSecurity = glob.dependsOnRole;
2995 }
#define NIL
Definition: pg_list.h:65
#define MemSet(start, val, len)
Definition: c.h:950
bool dependsOnRole
Definition: pathnodes.h:139
PlannerGlobal * glob
Definition: pathnodes.h:179
List * invalItems
Definition: pathnodes.h:127
NodeTag type
Definition: pathnodes.h:175
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3006
NodeTag type
Definition: pathnodes.h:107
List * relationOids
Definition: pathnodes.h:125

◆ extract_query_dependencies_walker()

bool extract_query_dependencies_walker ( Node node,
PlannerInfo context 
)

Definition at line 3006 of file setrefs.c.

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

Referenced by expression_planner_with_deps(), extract_query_dependencies(), and extract_query_dependencies_walker().

3007 {
3008  if (node == NULL)
3009  return false;
3010  Assert(!IsA(node, PlaceHolderVar));
3011  if (IsA(node, Query))
3012  {
3013  Query *query = (Query *) node;
3014  ListCell *lc;
3015 
3016  if (query->commandType == CMD_UTILITY)
3017  {
3018  /*
3019  * Ignore utility statements, except those (such as EXPLAIN) that
3020  * contain a parsed-but-not-planned query.
3021  */
3022  query = UtilityContainsQuery(query->utilityStmt);
3023  if (query == NULL)
3024  return false;
3025  }
3026 
3027  /* Remember if any Query has RLS quals applied by rewriter */
3028  if (query->hasRowSecurity)
3029  context->glob->dependsOnRole = true;
3030 
3031  /* Collect relation OIDs in this Query's rtable */
3032  foreach(lc, query->rtable)
3033  {
3034  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3035 
3036  if (rte->rtekind == RTE_RELATION)
3037  context->glob->relationOids =
3038  lappend_oid(context->glob->relationOids, rte->relid);
3039  else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
3040  OidIsValid(rte->relid))
3041  context->glob->relationOids =
3042  lappend_oid(context->glob->relationOids,
3043  rte->relid);
3044  }
3045 
3046  /* And recurse into the query's subexpressions */
3048  (void *) context, 0);
3049  }
3050  /* Extract function dependencies and check for regclass Consts */
3051  fix_expr_common(context, node);
3053  (void *) context);
3054 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Node * utilityStmt
Definition: parsenodes.h:120
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:652
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2110
bool dependsOnRole
Definition: pathnodes.h:139
List * rtable
Definition: parsenodes.h:137
PlannerGlobal * glob
Definition: pathnodes.h:179
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3006
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1598
CmdType commandType
Definition: parsenodes.h:112
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
List * relationOids
Definition: pathnodes.h:125
RTEKind rtekind
Definition: parsenodes.h:977
bool hasRowSecurity
Definition: parsenodes.h:133

◆ fix_alternative_subplan()

static Node* fix_alternative_subplan ( PlannerInfo root,
AlternativeSubPlan asplan,
double  num_exec 
)
static

Definition at line 1718 of file setrefs.c.

References Assert, PlannerInfo::glob, lfirst, list_nth_cell(), NIL, SubPlan::per_call_cost, SubPlan::plan_id, SubPlan::startup_cost, PlannerGlobal::subplans, and AlternativeSubPlan::subplans.

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

1720 {
1721  SubPlan *bestplan = NULL;
1722  Cost bestcost = 0;
1723  ListCell *lc;
1724 
1725  /*
1726  * Compute the estimated cost of each subplan assuming num_exec
1727  * executions, and keep the cheapest one. Replace discarded subplans with
1728  * NULL pointers in the global subplans list. In event of exact equality
1729  * of estimates, we prefer the later plan; this is a bit arbitrary, but in
1730  * current usage it biases us to break ties against fast-start subplans.
1731  */
1732  Assert(asplan->subplans != NIL);
1733 
1734  foreach(lc, asplan->subplans)
1735  {
1736  SubPlan *curplan = (SubPlan *) lfirst(lc);
1737  Cost curcost;
1738 
1739  curcost = curplan->startup_cost + num_exec * curplan->per_call_cost;
1740  if (bestplan == NULL)
1741  {
1742  bestplan = curplan;
1743  bestcost = curcost;
1744  }
1745  else if (curcost <= bestcost)
1746  {
1747  /* drop old bestplan */
1748  ListCell *lc2 = list_nth_cell(root->glob->subplans,
1749  bestplan->plan_id - 1);
1750 
1751  lfirst(lc2) = NULL;
1752  bestplan = curplan;
1753  bestcost = curcost;
1754  }
1755  else
1756  {
1757  /* drop curplan */
1758  ListCell *lc2 = list_nth_cell(root->glob->subplans,
1759  curplan->plan_id - 1);
1760 
1761  lfirst(lc2) = NULL;
1762  }
1763  }
1764 
1765  return (Node *) bestplan;
1766 }
#define NIL
Definition: pg_list.h:65
int plan_id
Definition: primnodes.h:709
static ListCell * list_nth_cell(const List *list, int n)
Definition: pg_list.h:244
Definition: nodes.h:528
List * subplans
Definition: pathnodes.h:111
PlannerGlobal * glob
Definition: pathnodes.h:179
Cost per_call_cost
Definition: primnodes.h:733
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
Cost startup_cost
Definition: primnodes.h:732
double Cost
Definition: nodes.h:662

◆ fix_expr_common()

static void fix_expr_common ( PlannerInfo root,
Node node 
)
static

Definition at line 1598 of file setrefs.c.

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

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

1599 {
1600  /* We assume callers won't call us on a NULL pointer */
1601  if (IsA(node, Aggref))
1602  {
1604  ((Aggref *) node)->aggfnoid);
1605  }
1606  else if (IsA(node, WindowFunc))
1607  {
1609  ((WindowFunc *) node)->winfnoid);
1610  }
1611  else if (IsA(node, FuncExpr))
1612  {
1614  ((FuncExpr *) node)->funcid);
1615  }
1616  else if (IsA(node, OpExpr))
1617  {
1618  set_opfuncid((OpExpr *) node);
1620  ((OpExpr *) node)->opfuncid);
1621  }
1622  else if (IsA(node, DistinctExpr))
1623  {
1624  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1626  ((DistinctExpr *) node)->opfuncid);
1627  }
1628  else if (IsA(node, NullIfExpr))
1629  {
1630  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1632  ((NullIfExpr *) node)->opfuncid);
1633  }
1634  else if (IsA(node, ScalarArrayOpExpr))
1635  {
1638  ((ScalarArrayOpExpr *) node)->opfuncid);
1639  }
1640  else if (IsA(node, Const))
1641  {
1642  Const *con = (Const *) node;
1643 
1644  /* Check for regclass reference */
1645  if (ISREGCLASSCONST(con))
1646  root->glob->relationOids =
1647  lappend_oid(root->glob->relationOids,
1649  }
1650  else if (IsA(node, GroupingFunc))
1651  {
1652  GroupingFunc *g = (GroupingFunc *) node;
1653  AttrNumber *grouping_map = root->grouping_map;
1654 
1655  /* If there are no grouping sets, we don't need this. */
1656 
1657  Assert(grouping_map || g->cols == NIL);
1658 
1659  if (grouping_map)
1660  {
1661  ListCell *lc;
1662  List *cols = NIL;
1663 
1664  foreach(lc, g->refs)
1665  {
1666  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1667  }
1668 
1669  Assert(!g->cols || equal(cols, g->cols));
1670 
1671  if (!g->cols)
1672  g->cols = cols;
1673  }
1674  }
1675 }
Datum constvalue
Definition: primnodes.h:214
#define NIL
Definition: pg_list.h:65
#define ISREGCLASSCONST(con)
Definition: setrefs.c:100
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
List * refs
Definition: primnodes.h:361
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
#define DatumGetObjectId(X)
Definition: postgres.h:500
AttrNumber * grouping_map
Definition: pathnodes.h:326
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define lfirst_int(lc)
Definition: pg_list.h:170
PlannerGlobal * glob
Definition: pathnodes.h:179
List * lappend_int(List *list, int datum)
Definition: list.c:339
List * cols
Definition: primnodes.h:362
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2889
#define Assert(condition)
Definition: c.h:746
List * relationOids
Definition: pathnodes.h:125
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1667
Definition: pg_list.h:50
int16 AttrNumber
Definition: attnum.h:21
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1678

◆ fix_join_expr()

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

Definition at line 2560 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::num_exec, 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().

2567 {
2568  fix_join_expr_context context;
2569 
2570  context.root = root;
2571  context.outer_itlist = outer_itlist;
2572  context.inner_itlist = inner_itlist;
2573  context.acceptable_rel = acceptable_rel;
2574  context.rtoffset = rtoffset;
2575  context.num_exec = num_exec;
2576  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2577 }
indexed_tlist * inner_itlist
Definition: setrefs.c:59
Definition: nodes.h:528
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2580
PlannerInfo * root
Definition: setrefs.c:57
indexed_tlist * outer_itlist
Definition: setrefs.c:58
Definition: pg_list.h:50

◆ fix_join_expr_mutator()

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

Definition at line 2580 of file setrefs.c.

References fix_join_expr_context::acceptable_rel, copyVar(), elog, ERROR, expression_tree_mutator(), fix_alternative_subplan(), 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, fix_join_expr_context::num_exec, 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::varnosyn.

Referenced by fix_join_expr().

2581 {
2582  Var *newvar;
2583 
2584  if (node == NULL)
2585  return NULL;
2586  if (IsA(node, Var))
2587  {
2588  Var *var = (Var *) node;
2589 
2590  /* Look for the var in the input tlists, first in the outer */
2591  if (context->outer_itlist)
2592  {
2593  newvar = search_indexed_tlist_for_var(var,
2594  context->outer_itlist,
2595  OUTER_VAR,
2596  context->rtoffset);
2597  if (newvar)
2598  return (Node *) newvar;
2599  }
2600 
2601  /* then in the inner. */
2602  if (context->inner_itlist)
2603  {
2604  newvar = search_indexed_tlist_for_var(var,
2605  context->inner_itlist,
2606  INNER_VAR,
2607  context->rtoffset);
2608  if (newvar)
2609  return (Node *) newvar;
2610  }
2611 
2612  /* If it's for acceptable_rel, adjust and return it */
2613  if (var->varno == context->acceptable_rel)
2614  {
2615  var = copyVar(var);
2616  var->varno += context->rtoffset;
2617  if (var->varnosyn > 0)
2618  var->varnosyn += context->rtoffset;
2619  return (Node *) var;
2620  }
2621 
2622  /* No referent found for Var */
2623  elog(ERROR, "variable not found in subplan target lists");
2624  }
2625  if (IsA(node, PlaceHolderVar))
2626  {
2627  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2628 
2629  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2630  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2631  {
2632  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2633  context->outer_itlist,
2634  OUTER_VAR);
2635  if (newvar)
2636  return (Node *) newvar;
2637  }
2638  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2639  {
2640  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2641  context->inner_itlist,
2642  INNER_VAR);
2643  if (newvar)
2644  return (Node *) newvar;
2645  }
2646 
2647  /* If not supplied by input plans, evaluate the contained expr */
2648  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2649  }
2650  /* Try matching more complex expressions too, if tlists have any */
2651  if (context->outer_itlist && context->outer_itlist->has_non_vars)
2652  {
2653  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2654  context->outer_itlist,
2655  OUTER_VAR);
2656  if (newvar)
2657  return (Node *) newvar;
2658  }
2659  if (context->inner_itlist && context->inner_itlist->has_non_vars)
2660  {
2661  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2662  context->inner_itlist,
2663  INNER_VAR);
2664  if (newvar)
2665  return (Node *) newvar;
2666  }
2667  /* Special cases (apply only AFTER failing to match to lower tlist) */
2668  if (IsA(node, Param))
2669  return fix_param_node(context->root, (Param *) node);
2670  if (IsA(node, AlternativeSubPlan))
2672  (AlternativeSubPlan *) node,
2673  context->num_exec),
2674  context);
2675  fix_expr_common(context->root, node);
2676  return expression_tree_mutator(node,
2678  (void *) context);
2679 }
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1718
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
indexed_tlist * inner_itlist
Definition: setrefs.c:59
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1686
Definition: nodes.h:528
Definition: primnodes.h:181
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2580
bool has_ph_vars
Definition: setrefs.c:43
#define ERROR
Definition: elog.h:43
static Var * copyVar(Var *var)
Definition: setrefs.c:1576
PlannerInfo * root
Definition: setrefs.c:57
Index varnosyn
Definition: primnodes.h:194
Index varno
Definition: primnodes.h:184
bool has_non_vars
Definition: setrefs.c:44
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2455
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1598
#define INNER_VAR
Definition: primnodes.h:171
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2415
#define elog(elevel,...)
Definition: elog.h:214
indexed_tlist * outer_itlist
Definition: setrefs.c:58
#define OUTER_VAR
Definition: primnodes.h:172

◆ fix_param_node()

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

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

1687 {
1688  if (p->paramkind == PARAM_MULTIEXPR)
1689  {
1690  int subqueryid = p->paramid >> 16;
1691  int colno = p->paramid & 0xFFFF;
1692  List *params;
1693 
1694  if (subqueryid <= 0 ||
1695  subqueryid > list_length(root->multiexpr_params))
1696  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1697  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1698  if (colno <= 0 || colno > list_length(params))
1699  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1700  return copyObject(list_nth(params, colno - 1));
1701  }
1702  return (Node *) copyObject(p);
1703 }
ParamKind paramkind
Definition: primnodes.h:262
Definition: nodes.h:528
List * multiexpr_params
Definition: pathnodes.h:261
#define ERROR
Definition: elog.h:43
static void * list_nth(const List *list, int n)
Definition: pg_list.h:266
int paramid
Definition: primnodes.h:263
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:214
#define copyObject(obj)
Definition: nodes.h:644
Definition: pg_list.h:50

◆ fix_scan_expr()

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

Definition at line 1780 of file setrefs.c.

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

Referenced by set_plan_refs().

1781 {
1782  fix_scan_expr_context context;
1783 
1784  context.root = root;
1785  context.rtoffset = rtoffset;
1786  context.num_exec = num_exec;
1787 
1788  if (rtoffset != 0 ||
1789  root->multiexpr_params != NIL ||
1790  root->glob->lastPHId != 0 ||
1791  root->minmax_aggs != NIL ||
1792  root->hasAlternativeSubPlans)
1793  {
1794  return fix_scan_expr_mutator(node, &context);
1795  }
1796  else
1797  {
1798  /*
1799  * If rtoffset == 0, we don't need to change any Vars, and if there
1800  * are no MULTIEXPR subqueries then we don't need to replace
1801  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1802  * we won't need to remove them, and if there are no minmax Aggrefs we
1803  * won't need to replace them, and if there are no AlternativeSubPlans
1804  * we won't need to remove them. Then it's OK to just scribble on the
1805  * input node tree instead of copying (since the only change, filling
1806  * in any unset opfuncid fields, is harmless). This saves just enough
1807  * cycles to be noticeable on trivial queries.
1808  */
1809  (void) fix_scan_expr_walker(node, &context);
1810  return node;
1811  }
1812 }
#define NIL
Definition: pg_list.h:65
PlannerInfo * root
Definition: setrefs.c:50
List * minmax_aggs
Definition: pathnodes.h:327
List * multiexpr_params
Definition: pathnodes.h:261
bool hasAlternativeSubPlans
Definition: pathnodes.h:348
PlannerGlobal * glob
Definition: pathnodes.h:179
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1889
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1815
Index lastPHId
Definition: pathnodes.h:131

◆ fix_scan_expr_mutator()

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

Definition at line 1815 of file setrefs.c.

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

Referenced by fix_scan_expr().

1816 {
1817  if (node == NULL)
1818  return NULL;
1819  if (IsA(node, Var))
1820  {
1821  Var *var = copyVar((Var *) node);
1822 
1823  Assert(var->varlevelsup == 0);
1824 
1825  /*
1826  * We should not see any Vars marked INNER_VAR or OUTER_VAR. But an
1827  * indexqual expression could contain INDEX_VAR Vars.
1828  */
1829  Assert(var->varno != INNER_VAR);
1830  Assert(var->varno != OUTER_VAR);
1831  if (!IS_SPECIAL_VARNO(var->varno))
1832  var->varno += context->rtoffset;
1833  if (var->varnosyn > 0)
1834  var->varnosyn += context->rtoffset;
1835  return (Node *) var;
1836  }
1837  if (IsA(node, Param))
1838  return fix_param_node(context->root, (Param *) node);
1839  if (IsA(node, Aggref))
1840  {
1841  Aggref *aggref = (Aggref *) node;
1842 
1843  /* See if the Aggref should be replaced by a Param */
1844  if (context->root->minmax_aggs != NIL &&
1845  list_length(aggref->args) == 1)
1846  {
1847  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1848  ListCell *lc;
1849 
1850  foreach(lc, context->root->minmax_aggs)
1851  {
1852  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1853 
1854  if (mminfo->aggfnoid == aggref->aggfnoid &&
1855  equal(mminfo->target, curTarget->expr))
1856  return (Node *) copyObject(mminfo->param);
1857  }
1858  }
1859  /* If no match, just fall through to process it normally */
1860  }
1861  if (IsA(node, CurrentOfExpr))
1862  {
1863  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1864 
1865  Assert(cexpr->cvarno != INNER_VAR);
1866  Assert(cexpr->cvarno != OUTER_VAR);
1867  if (!IS_SPECIAL_VARNO(cexpr->cvarno))
1868  cexpr->cvarno += context->rtoffset;
1869  return (Node *) cexpr;
1870  }
1871  if (IsA(node, PlaceHolderVar))
1872  {
1873  /* At scan level, we should always just evaluate the contained expr */
1874  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1875 
1876  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1877  }
1878  if (IsA(node, AlternativeSubPlan))
1880  (AlternativeSubPlan *) node,
1881  context->num_exec),
1882  context);
1883  fix_expr_common(context->root, node);
1885  (void *) context);
1886 }
#define NIL
Definition: pg_list.h:65
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1718
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Index varlevelsup
Definition: primnodes.h:191
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1686
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
Param * param
Definition: pathnodes.h:2328
PlannerInfo * root
Definition: setrefs.c:50
Definition: nodes.h:528
List * args
Definition: primnodes.h:319
List * minmax_aggs
Definition: pathnodes.h:327
Definition: primnodes.h:181
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:175
#define linitial(l)
Definition: pg_list.h:174
static Var * copyVar(Var *var)
Definition: setrefs.c:1576
Index varnosyn
Definition: primnodes.h:194
Index varno
Definition: primnodes.h:184
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1815
Oid aggfnoid
Definition: primnodes.h:312
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1598
#define INNER_VAR
Definition: primnodes.h:171
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
Expr * target
Definition: pathnodes.h:2324
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
#define copyObject(obj)
Definition: nodes.h:644
#define OUTER_VAR
Definition: primnodes.h:172

◆ fix_scan_expr_walker()

static bool fix_scan_expr_walker ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1889 of file setrefs.c.

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

Referenced by fix_scan_expr().

1890 {
1891  if (node == NULL)
1892  return false;
1893  Assert(!IsA(node, PlaceHolderVar));
1894  Assert(!IsA(node, AlternativeSubPlan));
1895  fix_expr_common(context->root, node);
1897  (void *) context);
1898 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
PlannerInfo * root
Definition: setrefs.c:50
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1889
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1598
#define Assert(condition)
Definition: c.h:746
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888

◆ fix_upper_expr()

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

Definition at line 2713 of file setrefs.c.

References fix_upper_expr_mutator(), fix_upper_expr_context::newvarno, fix_upper_expr_context::num_exec, 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_hash_references(), set_indexonlyscan_references(), set_join_references(), and set_upper_references().

2719 {
2720  fix_upper_expr_context context;
2721 
2722  context.root = root;
2723  context.subplan_itlist = subplan_itlist;
2724  context.newvarno = newvarno;
2725  context.rtoffset = rtoffset;
2726  context.num_exec = num_exec;
2727  return fix_upper_expr_mutator(node, &context);
2728 }
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2731
PlannerInfo * root
Definition: setrefs.c:67
indexed_tlist * subplan_itlist
Definition: setrefs.c:68

◆ fix_upper_expr_mutator()

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

Definition at line 2731 of file setrefs.c.

References Aggref::aggfnoid, MinMaxAggInfo::aggfnoid, Aggref::args, copyObject, elog, equal(), ERROR, TargetEntry::expr, expression_tree_mutator(), fix_alternative_subplan(), 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, fix_upper_expr_context::num_exec, 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().

2732 {
2733  Var *newvar;
2734 
2735  if (node == NULL)
2736  return NULL;
2737  if (IsA(node, Var))
2738  {
2739  Var *var = (Var *) node;
2740 
2741  newvar = search_indexed_tlist_for_var(var,
2742  context->subplan_itlist,
2743  context->newvarno,
2744  context->rtoffset);
2745  if (!newvar)
2746  elog(ERROR, "variable not found in subplan target list");
2747  return (Node *) newvar;
2748  }
2749  if (IsA(node, PlaceHolderVar))
2750  {
2751  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2752 
2753  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2754  if (context->subplan_itlist->has_ph_vars)
2755  {
2756  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2757  context->subplan_itlist,
2758  context->newvarno);
2759  if (newvar)
2760  return (Node *) newvar;
2761  }
2762  /* If not supplied by input plan, evaluate the contained expr */
2763  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2764  }
2765  /* Try matching more complex expressions too, if tlist has any */
2766  if (context->subplan_itlist->has_non_vars)
2767  {
2768  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2769  context->subplan_itlist,
2770  context->newvarno);
2771  if (newvar)
2772  return (Node *) newvar;
2773  }
2774  /* Special cases (apply only AFTER failing to match to lower tlist) */
2775  if (IsA(node, Param))
2776  return fix_param_node(context->root, (Param *) node);
2777  if (IsA(node, Aggref))
2778  {
2779  Aggref *aggref = (Aggref *) node;
2780 
2781  /* See if the Aggref should be replaced by a Param */
2782  if (context->root->minmax_aggs != NIL &&
2783  list_length(aggref->args) == 1)
2784  {
2785  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2786  ListCell *lc;
2787 
2788  foreach(lc, context->root->minmax_aggs)
2789  {
2790  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2791 
2792  if (mminfo->aggfnoid == aggref->aggfnoid &&
2793  equal(mminfo->target, curTarget->expr))
2794  return (Node *) copyObject(mminfo->param);
2795  }
2796  }
2797  /* If no match, just fall through to process it normally */
2798  }
2799  if (IsA(node, AlternativeSubPlan))
2801  (AlternativeSubPlan *) node,
2802  context->num_exec),
2803  context);
2804  fix_expr_common(context->root, node);
2805  return expression_tree_mutator(node,
2807  (void *) context);
2808 }
#define NIL
Definition: pg_list.h:65
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1718
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2565
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1686
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
Param * param
Definition: pathnodes.h:2328
Definition: nodes.h:528
List * args
Definition: primnodes.h:319
List * minmax_aggs
Definition: pathnodes.h:327
Definition: primnodes.h:181
bool has_ph_vars
Definition: setrefs.c:43
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:43
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2731
bool has_non_vars
Definition: setrefs.c:44
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2455
Oid aggfnoid
Definition: primnodes.h:312
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1598
#define lfirst(lc)
Definition: pg_list.h:169
Expr * target
Definition: pathnodes.h:2324
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2415
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:214
PlannerInfo * root
Definition: setrefs.c:67
#define copyObject(obj)
Definition: nodes.h:644
indexed_tlist * subplan_itlist
Definition: setrefs.c:68

◆ flatten_rtes_walker()

static bool flatten_rtes_walker ( Node node,
PlannerGlobal glob 
)
static

Definition at line 410 of file setrefs.c.

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

Referenced by flatten_unplanned_rtes().

411 {
412  if (node == NULL)
413  return false;
414  if (IsA(node, RangeTblEntry))
415  {
416  RangeTblEntry *rte = (RangeTblEntry *) node;
417 
418  /* As above, we need only save relation RTEs */
419  if (rte->rtekind == RTE_RELATION)
420  add_rte_to_flat_rtable(glob, rte);
421  return false;
422  }
423  if (IsA(node, Query))
424  {
425  /* Recurse into subselects */
426  return query_tree_walker((Query *) node,
428  (void *) glob,
430  }
432  (void *) glob);
433 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
#define QTW_EXAMINE_RTES_BEFORE
Definition: nodeFuncs.h:25
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:446
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:410
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1888
RTEKind rtekind
Definition: parsenodes.h:977

◆ flatten_unplanned_rtes()

static void flatten_unplanned_rtes ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

Definition at line 400 of file setrefs.c.

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

Referenced by add_rtes_to_flat_rtable().

401 {
402  /* Use query_tree_walker to find all RTEs in the parse tree */
403  (void) query_tree_walker(rte->subquery,
405  (void *) glob,
407 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2322
#define QTW_EXAMINE_RTES_BEFORE
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:410
Query * subquery
Definition: parsenodes.h:1012

◆ offset_relid_set()

static Relids offset_relid_set ( Relids  relids,
int  rtoffset 
)
static

Definition at line 1554 of file setrefs.c.

References bms_add_member(), and bms_next_member().

Referenced by set_append_references(), set_customscan_references(), set_foreignscan_references(), and set_mergeappend_references().

1555 {
1556  Relids result = NULL;
1557  int rtindex;
1558 
1559  /* If there's no offset to apply, we needn't recompute the value */
1560  if (rtoffset == 0)
1561  return relids;
1562  rtindex = -1;
1563  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
1564  result = bms_add_member(result, rtindex + rtoffset);
1565  return result;
1566 }
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736

◆ record_plan_function_dependency()

void record_plan_function_dependency ( PlannerInfo root,
Oid  funcid 
)

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

2890 {
2891  /*
2892  * For performance reasons, we don't bother to track built-in functions;
2893  * we just assume they'll never change (or at least not in ways that'd
2894  * invalidate plans using them). For this purpose we can consider a
2895  * built-in function to be one with OID less than FirstBootstrapObjectId.
2896  * Note that the OID generator guarantees never to generate such an OID
2897  * after startup, even at OID wraparound.
2898  */
2899  if (funcid >= (Oid) FirstBootstrapObjectId)
2900  {
2901  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2902 
2903  /*
2904  * It would work to use any syscache on pg_proc, but the easiest is
2905  * PROCOID since we already have the function's OID at hand. Note
2906  * that plancache.c knows we use PROCOID.
2907  */
2908  inval_item->cacheId = PROCOID;
2909  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2910  ObjectIdGetDatum(funcid));
2911 
2912  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2913  }
2914 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
PlannerGlobal * glob
Definition: pathnodes.h:179
#define FirstBootstrapObjectId
Definition: transam.h:189
List * lappend(List *list, void *datum)
Definition: list.c:321
List * invalItems
Definition: pathnodes.h:127
uint32 hashValue
Definition: plannodes.h:1248
#define makeNode(_type_)
Definition: nodes.h:576

◆ record_plan_type_dependency()

void record_plan_type_dependency ( PlannerInfo root,
Oid  typid 
)

Definition at line 2929 of file setrefs.c.

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

Referenced by eval_const_expressions_mutator().

2930 {
2931  /*
2932  * As in record_plan_function_dependency, ignore the possibility that
2933  * someone would change a built-in domain.
2934  */
2935  if (typid >= (Oid) FirstBootstrapObjectId)
2936  {
2937  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2938 
2939  /*
2940  * It would work to use any syscache on pg_type, but the easiest is
2941  * TYPEOID since we already have the type's OID at hand. Note that
2942  * plancache.c knows we use TYPEOID.
2943  */
2944  inval_item->cacheId = TYPEOID;
2945  inval_item->hashValue = GetSysCacheHashValue1(TYPEOID,
2946  ObjectIdGetDatum(typid));
2947 
2948  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2949  }
2950 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
PlannerGlobal * glob
Definition: pathnodes.h:179
#define FirstBootstrapObjectId
Definition: transam.h:189
List * lappend(List *list, void *datum)
Definition: list.c:321
List * invalItems
Definition: pathnodes.h:127
uint32 hashValue
Definition: plannodes.h:1248
#define makeNode(_type_)
Definition: nodes.h:576

◆ search_indexed_tlist_for_non_var()

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

Definition at line 2455 of file setrefs.c.

References IsA, makeVarFromTargetEntry(), indexed_tlist::tlist, tlist_member(), Var::varattnosyn, and Var::varnosyn.

Referenced by fix_join_expr_mutator(), and fix_upper_expr_mutator().

2457 {
2458  TargetEntry *tle;
2459 
2460  /*
2461  * If it's a simple Const, replacing it with a Var is silly, even if there
2462  * happens to be an identical Const below; a Var is more expensive to
2463  * execute than a Const. What's more, replacing it could confuse some
2464  * places in the executor that expect to see simple Consts for, eg,
2465  * dropped columns.
2466  */
2467  if (IsA(node, Const))
2468  return NULL;
2469 
2470  tle = tlist_member(node, itlist->tlist);
2471  if (tle)
2472  {
2473  /* Found a matching subplan output expression */
2474  Var *newvar;
2475 
2476  newvar = makeVarFromTargetEntry(newvarno, tle);
2477  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2478  newvar->varattnosyn = 0;
2479  return newvar;
2480  }
2481  return NULL; /* no match */
2482 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:103
Definition: primnodes.h:181
Index varnosyn
Definition: primnodes.h:194
AttrNumber varattnosyn
Definition: primnodes.h:195
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:73
List * tlist
Definition: setrefs.c:41

◆ search_indexed_tlist_for_sortgroupref()

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

Definition at line 2495 of file setrefs.c.

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

Referenced by set_upper_references().

2499 {
2500  ListCell *lc;
2501 
2502  foreach(lc, itlist->tlist)
2503  {
2504  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2505 
2506  /* The equal() check should be redundant, but let's be paranoid */
2507  if (tle->ressortgroupref == sortgroupref &&
2508  equal(node, tle->expr))
2509  {
2510  /* Found a matching subplan output expression */
2511  Var *newvar;
2512 
2513  newvar = makeVarFromTargetEntry(newvarno, tle);
2514  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2515  newvar->varattnosyn = 0;
2516  return newvar;
2517  }
2518  }
2519  return NULL; /* no match */
2520 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:103
Definition: primnodes.h:181
Index varnosyn
Definition: primnodes.h:194
AttrNumber varattnosyn
Definition: primnodes.h:195
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
Index ressortgroupref
Definition: primnodes.h:1413
List * tlist
Definition: setrefs.c:41

◆ search_indexed_tlist_for_var()

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

Definition at line 2415 of file setrefs.c.

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

Referenced by fix_join_expr_mutator(), and fix_upper_expr_mutator().

2417 {
2418  Index varno = var->varno;
2419  AttrNumber varattno = var->varattno;
2420  tlist_vinfo *vinfo;
2421  int i;
2422 
2423  vinfo = itlist->vars;
2424  i = itlist->num_vars;
2425  while (i-- > 0)
2426  {
2427  if (vinfo->varno == varno && vinfo->varattno == varattno)
2428  {
2429  /* Found a match */
2430  Var *newvar = copyVar(var);
2431 
2432  newvar->varno = newvarno;
2433  newvar->varattno = vinfo->resno;
2434  if (newvar->varnosyn > 0)
2435  newvar->varnosyn += rtoffset;
2436  return newvar;
2437  }
2438  vinfo++;
2439  }
2440  return NULL; /* no match */
2441 }
Index varno
Definition: setrefs.c:34
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
AttrNumber varattno
Definition: setrefs.c:35
int num_vars
Definition: setrefs.c:42
static Var * copyVar(Var *var)
Definition: setrefs.c:1576
Index varnosyn
Definition: primnodes.h:194
Index varno
Definition: primnodes.h:184
unsigned int Index
Definition: c.h:483
int i
int16 AttrNumber
Definition: attnum.h:21

◆ set_append_references()

static Plan * set_append_references ( PlannerInfo root,
Append aplan,
int  rtoffset 
)
static

Definition at line 1397 of file setrefs.c.

References Append::appendplans, Assert, clean_up_removed_plan_level(), Plan::lefttree, lfirst, linitial, list_length(), NIL, offset_relid_set(), Append::plan, Plan::qual, Plan::righttree, PartitionedRelPruneInfo::rtindex, set_dummy_tlist_references(), and set_plan_refs().

Referenced by set_plan_refs().

1400 {
1401  ListCell *l;
1402 
1403  /*
1404  * Append, like Sort et al, doesn't actually evaluate its targetlist or
1405  * check quals. If it's got exactly one child plan, then it's not doing
1406  * anything useful at all, and we can strip it out.
1407  */
1408  Assert(aplan->plan.qual == NIL);
1409 
1410  /* First, we gotta recurse on the children */
1411  foreach(l, aplan->appendplans)
1412  {
1413  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1414  }
1415 
1416  /* Now, if there's just one, forget the Append and return that child */
1417  if (list_length(aplan->appendplans) == 1)
1418  return clean_up_removed_plan_level((Plan *) aplan,
1419  (Plan *) linitial(aplan->appendplans));
1420 
1421  /*
1422  * Otherwise, clean up the Append as needed. It's okay to do this after
1423  * recursing to the children, because set_dummy_tlist_references doesn't
1424  * look at those.
1425  */
1426  set_dummy_tlist_references((Plan *) aplan, rtoffset);
1427 
1428  aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
1429 
1430  if (aplan->part_prune_info)
1431  {
1432  foreach(l, aplan->part_prune_info->prune_infos)
1433  {
1434  List *prune_infos = lfirst(l);
1435  ListCell *l2;
1436 
1437  foreach(l2, prune_infos)
1438  {
1439  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1440 
1441  pinfo->rtindex += rtoffset;
1442  }
1443  }
1444  }
1445 
1446  /* We don't need to recurse to lefttree or righttree ... */
1447  Assert(aplan->plan.lefttree == NULL);
1448  Assert(aplan->plan.righttree == NULL);
1449 
1450  return (Plan *) aplan;
1451 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1554
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:499
List * appendplans
Definition: plannodes.h:247
struct Plan * righttree
Definition: plannodes.h:139
#define linitial(l)
Definition: pg_list.h:174
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1221
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
struct Plan * lefttree
Definition: plannodes.h:138
Definition: pg_list.h:50
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2247
Plan plan
Definition: plannodes.h:245

◆ set_customscan_references()

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

Definition at line 1324 of file setrefs.c.

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

Referenced by set_plan_refs().

1327 {
1328  ListCell *lc;
1329 
1330  /* Adjust scanrelid if it's valid */
1331  if (cscan->scan.scanrelid > 0)
1332  cscan->scan.scanrelid += rtoffset;
1333 
1334  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1335  {
1336  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1338 
1339  cscan->scan.plan.targetlist = (List *)
1340  fix_upper_expr(root,
1341  (Node *) cscan->scan.plan.targetlist,
1342  itlist,
1343  INDEX_VAR,
1344  rtoffset,
1345  NUM_EXEC_TLIST((Plan *) cscan));
1346  cscan->scan.plan.qual = (List *)
1347  fix_upper_expr(root,
1348  (Node *) cscan->scan.plan.qual,
1349  itlist,
1350  INDEX_VAR,
1351  rtoffset,
1352  NUM_EXEC_QUAL((Plan *) cscan));
1353  cscan->custom_exprs = (List *)
1354  fix_upper_expr(root,
1355  (Node *) cscan->custom_exprs,
1356  itlist,
1357  INDEX_VAR,
1358  rtoffset,
1359  NUM_EXEC_QUAL((Plan *) cscan));
1360  pfree(itlist);
1361  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1362  cscan->custom_scan_tlist =
1363  fix_scan_list(root, cscan->custom_scan_tlist,
1364  rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
1365  }
1366  else
1367  {
1368  /* Adjust tlist, qual, custom_exprs in the standard way */
1369  cscan->scan.plan.targetlist =
1370  fix_scan_list(root, cscan->scan.plan.targetlist,
1371  rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
1372  cscan->scan.plan.qual =
1373  fix_scan_list(root, cscan->scan.plan.qual,
1374  rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
1375  cscan->custom_exprs =
1376  fix_scan_list(root, cscan->custom_exprs,
1377  rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
1378  }
1379 
1380  /* Adjust child plan-nodes recursively, if needed */
1381  foreach(lc, cscan->custom_plans)
1382  {
1383  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1384  }
1385 
1386  cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
1387 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:336
Index scanrelid
Definition: plannodes.h:337
Definition: nodes.h:528
List * custom_exprs
Definition: plannodes.h:646
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1554
List * custom_plans
Definition: plannodes.h:645
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:499
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
Scan scan
Definition: plannodes.h:642
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define lfirst(lc)
Definition: pg_list.h:169
List * custom_scan_tlist
Definition: plannodes.h:648
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
Bitmapset * custom_relids
Definition: plannodes.h:649
List * targetlist
Definition: plannodes.h:136
#define INDEX_VAR
Definition: primnodes.h:173
Definition: pg_list.h:50

◆ set_dummy_tlist_references()

static void set_dummy_tlist_references ( Plan plan,
int  rtoffset 
)
static

Definition at line 2247 of file setrefs.c.

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

Referenced by set_append_references(), set_hash_references(), set_mergeappend_references(), and set_plan_refs().

2248 {
2249  List *output_targetlist;
2250  ListCell *l;
2251 
2252  output_targetlist = NIL;
2253  foreach(l, plan->targetlist)
2254  {
2255  TargetEntry *tle = (TargetEntry *) lfirst(l);
2256  Var *oldvar = (Var *) tle->expr;
2257  Var *newvar;
2258 
2259  /*
2260  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
2261  * as Consts, not Vars referencing Consts. Here, there's no speed
2262  * advantage to be had, but it makes EXPLAIN output look cleaner, and
2263  * again it avoids confusing the executor.
2264  */
2265  if (IsA(oldvar, Const))
2266  {
2267  /* just reuse the existing TLE node */
2268  output_targetlist = lappend(output_targetlist, tle);
2269  continue;
2270  }
2271 
2272  newvar = makeVar(OUTER_VAR,
2273  tle->resno,
2274  exprType((Node *) oldvar),
2275  exprTypmod((Node *) oldvar),
2276  exprCollation((Node *) oldvar),
2277  0);
2278  if (IsA(oldvar, Var) &&
2279  oldvar->varnosyn > 0)
2280  {
2281  newvar->varnosyn = oldvar->varnosyn + rtoffset;
2282  newvar->varattnosyn = oldvar->varattnosyn;
2283  }
2284  else
2285  {
2286  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2287  newvar->varattnosyn = 0;
2288  }
2289 
2290  tle = flatCopyTargetEntry(tle);
2291  tle->expr = (Expr *) newvar;
2292  output_targetlist = lappend(output_targetlist, tle);
2293  }
2294  plan->targetlist = output_targetlist;
2295 
2296  /* We don't touch plan->qual here */
2297 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
Definition: nodes.h:528
Definition: primnodes.h:181
AttrNumber resno
Definition: primnodes.h:1411
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
List * lappend(List *list, void *datum)
Definition: list.c:321
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:768
List * targetlist
Definition: plannodes.h:136
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:172

◆ set_foreignscan_references()

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

Definition at line 1242 of file setrefs.c.

References build_tlist_index(), ForeignScan::fdw_scan_tlist, fix_scan_list, fix_upper_expr(), ForeignScan::fs_relids, INDEX_VAR, NIL, NUM_EXEC_QUAL, NUM_EXEC_TLIST, offset_relid_set(), pfree(), Scan::plan, Plan::qual, ForeignScan::resultRelation, ForeignScan::scan, Scan::scanrelid, and Plan::targetlist.

Referenced by set_plan_refs().

1245 {
1246  /* Adjust scanrelid if it's valid */
1247  if (fscan->scan.scanrelid > 0)
1248  fscan->scan.scanrelid += rtoffset;
1249 
1250  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1251  {
1252  /*
1253  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1254  * foreign scan tuple
1255  */
1257 
1258  fscan->scan.plan.targetlist = (List *)
1259  fix_upper_expr(root,
1260  (Node *) fscan->scan.plan.targetlist,
1261  itlist,
1262  INDEX_VAR,
1263  rtoffset,
1264  NUM_EXEC_TLIST((Plan *) fscan));
1265  fscan->scan.plan.qual = (List *)
1266  fix_upper_expr(root,
1267  (Node *) fscan->scan.plan.qual,
1268  itlist,
1269  INDEX_VAR,
1270  rtoffset,
1271  NUM_EXEC_QUAL((Plan *) fscan));
1272  fscan->fdw_exprs = (List *)
1273  fix_upper_expr(root,
1274  (Node *) fscan->fdw_exprs,
1275  itlist,
1276  INDEX_VAR,
1277  rtoffset,
1278  NUM_EXEC_QUAL((Plan *) fscan));
1279  fscan->fdw_recheck_quals = (List *)
1280  fix_upper_expr(root,
1281  (Node *) fscan->fdw_recheck_quals,
1282  itlist,
1283  INDEX_VAR,
1284  rtoffset,
1285  NUM_EXEC_QUAL((Plan *) fscan));
1286  pfree(itlist);
1287  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1288  fscan->fdw_scan_tlist =
1289  fix_scan_list(root, fscan->fdw_scan_tlist,
1290  rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
1291  }
1292  else
1293  {
1294  /*
1295  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1296  * way
1297  */
1298  fscan->scan.plan.targetlist =
1299  fix_scan_list(root, fscan->scan.plan.targetlist,
1300  rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
1301  fscan->scan.plan.qual =
1302  fix_scan_list(root, fscan->scan.plan.qual,
1303  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1304  fscan->fdw_exprs =
1305  fix_scan_list(root, fscan->fdw_exprs,
1306  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1307  fscan->fdw_recheck_quals =
1308  fix_scan_list(root, fscan->fdw_recheck_quals,
1309  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1310  }
1311 
1312  fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
1313 
1314  /* Adjust resultRelation if it's valid */
1315  if (fscan->resultRelation > 0)
1316  fscan->resultRelation += rtoffset;
1317 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:336
Index scanrelid
Definition: plannodes.h:337
List * fdw_exprs
Definition: plannodes.h:617
Definition: nodes.h:528
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
List * fdw_scan_tlist
Definition: plannodes.h:619
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1554
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
List * fdw_recheck_quals
Definition: plannodes.h:620
Index resultRelation
Definition: plannodes.h:615
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
List * targetlist
Definition: plannodes.h:136
#define INDEX_VAR
Definition: primnodes.h:173
Definition: pg_list.h:50
Bitmapset * fs_relids
Definition: plannodes.h:621

◆ set_hash_references()

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

Definition at line 1522 of file setrefs.c.

References Assert, build_tlist_index(), fix_upper_expr(), Hash::hashkeys, Plan::lefttree, NIL, NUM_EXEC_QUAL, OUTER_VAR, Plan::qual, set_dummy_tlist_references(), and Plan::targetlist.

Referenced by set_plan_refs().

1523 {
1524  Hash *hplan = (Hash *) plan;
1525  Plan *outer_plan = plan->lefttree;
1526  indexed_tlist *outer_itlist;
1527 
1528  /*
1529  * Hash's hashkeys are used when feeding tuples into the hashtable,
1530  * therefore have them reference Hash's outer plan (which itself is the
1531  * inner plan of the HashJoin).
1532  */
1533  outer_itlist = build_tlist_index(outer_plan->targetlist);
1534  hplan->hashkeys = (List *)
1535  fix_upper_expr(root,
1536  (Node *) hplan->hashkeys,
1537  outer_itlist,
1538  OUTER_VAR,
1539  rtoffset,
1540  NUM_EXEC_QUAL(plan));
1541 
1542  /* Hash doesn't project */
1543  set_dummy_tlist_references(plan, rtoffset);
1544 
1545  /* Hash nodes don't have their own quals */
1546  Assert(plan->qual == NIL);
1547 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
Definition: nodes.h:528
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
List * hashkeys
Definition: plannodes.h:930
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define Assert(condition)
Definition: c.h:746
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
struct Plan * lefttree
Definition: plannodes.h:138
List * targetlist
Definition: plannodes.h:136
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:172
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2247

◆ set_indexonlyscan_references()

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

Definition at line 1066 of file setrefs.c.

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

Referenced by set_plan_refs().

1069 {
1070  indexed_tlist *index_itlist;
1071 
1072  index_itlist = build_tlist_index(plan->indextlist);
1073 
1074  plan->scan.scanrelid += rtoffset;
1075  plan->scan.plan.targetlist = (List *)
1076  fix_upper_expr(root,
1077  (Node *) plan->scan.plan.targetlist,
1078  index_itlist,
1079  INDEX_VAR,
1080  rtoffset,
1081  NUM_EXEC_TLIST((Plan *) plan));
1082  plan->scan.plan.qual = (List *)
1083  fix_upper_expr(root,
1084  (Node *) plan->scan.plan.qual,
1085  index_itlist,
1086  INDEX_VAR,
1087  rtoffset,
1088  NUM_EXEC_QUAL((Plan *) plan));
1089  /* indexqual is already transformed to reference index columns */
1090  plan->indexqual = fix_scan_list(root, plan->indexqual,
1091  rtoffset, 1);
1092  /* indexorderby is already transformed to reference index columns */
1093  plan->indexorderby = fix_scan_list(root, plan->indexorderby,
1094  rtoffset, 1);
1095  /* indextlist must NOT be transformed to reference index columns */
1096  plan->indextlist = fix_scan_list(root, plan->indextlist,
1097  rtoffset, NUM_EXEC_TLIST((Plan *) plan));
1098 
1099  pfree(index_itlist);
1100 
1101  return (Plan *) plan;
1102 }
List * qual
Definition: plannodes.h:137
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:336
Index scanrelid
Definition: plannodes.h:337
Definition: nodes.h:528
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
List * indextlist
Definition: plannodes.h:429
List * indexorderby
Definition: plannodes.h:428
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
List * indexqual
Definition: plannodes.h:427
List * targetlist
Definition: plannodes.h:136
#define INDEX_VAR
Definition: primnodes.h:173
Definition: pg_list.h:50

◆ set_join_references()

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

Definition at line 1909 of file setrefs.c.

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

Referenced by set_plan_refs().

1910 {
1911  Plan *outer_plan = join->plan.lefttree;
1912  Plan *inner_plan = join->plan.righttree;
1913  indexed_tlist *outer_itlist;
1914  indexed_tlist *inner_itlist;
1915 
1916  outer_itlist = build_tlist_index(outer_plan->targetlist);
1917  inner_itlist = build_tlist_index(inner_plan->targetlist);
1918 
1919  /*
1920  * First process the joinquals (including merge or hash clauses). These
1921  * are logically below the join so they can always use all values
1922  * available from the input tlists. It's okay to also handle
1923  * NestLoopParams now, because those couldn't refer to nullable
1924  * subexpressions.
1925  */
1926  join->joinqual = fix_join_expr(root,
1927  join->joinqual,
1928  outer_itlist,
1929  inner_itlist,
1930  (Index) 0,
1931  rtoffset,
1932  NUM_EXEC_QUAL((Plan *) join));
1933 
1934  /* Now do join-type-specific stuff */
1935  if (IsA(join, NestLoop))
1936  {
1937  NestLoop *nl = (NestLoop *) join;
1938  ListCell *lc;
1939 
1940  foreach(lc, nl->nestParams)
1941  {
1942  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1943 
1944  nlp->paramval = (Var *) fix_upper_expr(root,
1945  (Node *) nlp->paramval,
1946  outer_itlist,
1947  OUTER_VAR,
1948  rtoffset,
1949  NUM_EXEC_TLIST(outer_plan));
1950  /* Check we replaced any PlaceHolderVar with simple Var */
1951  if (!(IsA(nlp->paramval, Var) &&
1952  nlp->paramval->varno == OUTER_VAR))
1953  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
1954  }
1955  }
1956  else if (IsA(join, MergeJoin))
1957  {
1958  MergeJoin *mj = (MergeJoin *) join;
1959 
1960  mj->mergeclauses = fix_join_expr(root,
1961  mj->mergeclauses,
1962  outer_itlist,
1963  inner_itlist,
1964  (Index) 0,
1965  rtoffset,
1966  NUM_EXEC_QUAL((Plan *) join));
1967  }
1968  else if (IsA(join, HashJoin))
1969  {
1970  HashJoin *hj = (HashJoin *) join;
1971 
1972  hj->hashclauses = fix_join_expr(root,
1973  hj->hashclauses,
1974  outer_itlist,
1975  inner_itlist,
1976  (Index) 0,
1977  rtoffset,
1978  NUM_EXEC_QUAL((Plan *) join));
1979 
1980  /*
1981  * HashJoin's hashkeys are used to look for matching tuples from its
1982  * outer plan (not the Hash node!) in the hashtable.
1983  */
1984  hj->hashkeys = (List *) fix_upper_expr(root,
1985  (Node *) hj->hashkeys,
1986  outer_itlist,
1987  OUTER_VAR,
1988  rtoffset,
1989  NUM_EXEC_QUAL((Plan *) join));
1990  }
1991 
1992  /*
1993  * Now we need to fix up the targetlist and qpqual, which are logically
1994  * above the join. This means they should not re-use any input expression
1995  * that was computed in the nullable side of an outer join. Vars and
1996  * PlaceHolderVars are fine, so we can implement this restriction just by
1997  * clearing has_non_vars in the indexed_tlist structs.
1998  *
1999  * XXX This is a grotty workaround for the fact that we don't clearly
2000  * distinguish between a Var appearing below an outer join and the "same"
2001  * Var appearing above it. If we did, we'd not need to hack the matching
2002  * rules this way.
2003  */
2004  switch (join->jointype)
2005  {
2006  case JOIN_LEFT:
2007  case JOIN_SEMI:
2008  case JOIN_ANTI:
2009  inner_itlist->has_non_vars = false;
2010  break;
2011  case JOIN_RIGHT:
2012  outer_itlist->has_non_vars = false;
2013  break;
2014  case JOIN_FULL:
2015  outer_itlist->has_non_vars = false;
2016  inner_itlist->has_non_vars = false;
2017  break;
2018  default:
2019  break;
2020  }
2021 
2022  join->plan.targetlist = fix_join_expr(root,
2023  join->plan.targetlist,
2024  outer_itlist,
2025  inner_itlist,
2026  (Index) 0,
2027  rtoffset,
2028  NUM_EXEC_TLIST((Plan *) join));
2029  join->plan.qual = fix_join_expr(root,
2030  join->plan.qual,
2031  outer_itlist,
2032  inner_itlist,
2033  (Index) 0,
2034  rtoffset,
2035  NUM_EXEC_QUAL((Plan *) join));
2036 
2037  pfree(outer_itlist);
2038  pfree(inner_itlist);
2039 }
List * qual
Definition: plannodes.h:137
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
List * nestParams
Definition: plannodes.h:703
List * hashkeys
Definition: plannodes.h:751
List * hashclauses
Definition: plannodes.h:743
Definition: nodes.h:528
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
Definition: primnodes.h:181
List * mergeclauses
Definition: plannodes.h:728
JoinType jointype
Definition: plannodes.h:684
struct Plan * righttree
Definition: plannodes.h:139
void pfree(void *pointer)
Definition: mcxt.c:1057
Var * paramval
Definition: plannodes.h:710
#define ERROR
Definition: elog.h:43
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
Index varno
Definition: primnodes.h:184
bool has_non_vars
Definition: setrefs.c:44
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
unsigned int Index
Definition: c.h:483
#define lfirst(lc)
Definition: pg_list.h:169
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
struct Plan * lefttree
Definition: plannodes.h:138
List * targetlist
Definition: plannodes.h:136
#define elog(elevel,...)
Definition: elog.h:214
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:172
List * joinqual
Definition: plannodes.h:686
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset, double num_exec)
Definition: setrefs.c:2560
Plan plan
Definition: plannodes.h:683

◆ set_mergeappend_references()

static Plan * set_mergeappend_references ( PlannerInfo root,
MergeAppend mplan,
int  rtoffset 
)
static

Definition at line 1461 of file setrefs.c.

References Assert, clean_up_removed_plan_level(), Plan::lefttree, lfirst, linitial, list_length(), MergeAppend::mergeplans, NIL, offset_relid_set(), MergeAppend::plan, Plan::qual, Plan::righttree, PartitionedRelPruneInfo::rtindex, set_dummy_tlist_references(), and set_plan_refs().

Referenced by set_plan_refs().

1464 {
1465  ListCell *l;
1466 
1467  /*
1468  * MergeAppend, like Sort et al, doesn't actually evaluate its targetlist
1469  * or check quals. If it's got exactly one child plan, then it's not
1470  * doing anything useful at all, and we can strip it out.
1471  */
1472  Assert(mplan->plan.qual == NIL);
1473 
1474  /* First, we gotta recurse on the children */
1475  foreach(l, mplan->mergeplans)
1476  {
1477  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1478  }
1479 
1480  /* Now, if there's just one, forget the MergeAppend and return that child */
1481  if (list_length(mplan->mergeplans) == 1)
1482  return clean_up_removed_plan_level((Plan *) mplan,
1483  (Plan *) linitial(mplan->mergeplans));
1484 
1485  /*
1486  * Otherwise, clean up the MergeAppend as needed. It's okay to do this
1487  * after recursing to the children, because set_dummy_tlist_references
1488  * doesn't look at those.
1489  */
1490  set_dummy_tlist_references((Plan *) mplan, rtoffset);
1491 
1492  mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
1493 
1494  if (mplan->part_prune_info)
1495  {
1496  foreach(l, mplan->part_prune_info->prune_infos)
1497  {
1498  List *prune_infos = lfirst(l);
1499  ListCell *l2;
1500 
1501  foreach(l2, prune_infos)
1502  {
1503  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1504 
1505  pinfo->rtindex += rtoffset;
1506  }
1507  }
1508  }
1509 
1510  /* We don't need to recurse to lefttree or righttree ... */
1511  Assert(mplan->plan.lefttree == NULL);
1512  Assert(mplan->plan.righttree == NULL);
1513 
1514  return (Plan *) mplan;
1515 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1554
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:499
struct Plan * righttree
Definition: plannodes.h:139
#define linitial(l)
Definition: pg_list.h:174
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1221
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
static int list_length(const List *l)
Definition: pg_list.h:149
struct Plan * lefttree
Definition: plannodes.h:138
List * mergeplans
Definition: plannodes.h:268
Definition: pg_list.h:50
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2247

◆ set_param_references()

static void set_param_references ( PlannerInfo root,
Plan plan 
)
static

Definition at line 2123 of file setrefs.c.

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

Referenced by set_plan_refs().

2124 {
2125  Assert(IsA(plan, Gather) || IsA(plan, GatherMerge));
2126 
2127  if (plan->lefttree->extParam)
2128  {
2129  PlannerInfo *proot;
2130  Bitmapset *initSetParam = NULL;
2131  ListCell *l;
2132 
2133  for (proot = root; proot != NULL; proot = proot->parent_root)
2134  {
2135  foreach(l, proot->init_plans)
2136  {
2137  SubPlan *initsubplan = (SubPlan *) lfirst(l);
2138  ListCell *l2;
2139 
2140  foreach(l2, initsubplan->setParam)
2141  {
2142  initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
2143  }
2144  }
2145  }
2146 
2147  /*
2148  * Remember the list of all external initplan params that are used by
2149  * the children of Gather or Gather merge node.
2150  */
2151  if (IsA(plan, Gather))
2152  ((Gather *) plan)->initParam =
2153  bms_intersect(plan->lefttree->extParam, initSetParam);
2154  else
2155  ((GatherMerge *) plan)->initParam =
2156  bms_intersect(plan->lefttree->extParam, initSetParam);
2157  }
2158 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
PlannerInfo * parent_root
Definition: pathnodes.h:183
#define lfirst_int(lc)
Definition: pg_list.h:170
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:259
List * init_plans
Definition: pathnodes.h:257
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
List * setParam
Definition: primnodes.h:727
Bitmapset * extParam
Definition: plannodes.h:154
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
struct Plan * lefttree
Definition: plannodes.h:138

◆ set_plan_references()

Plan* set_plan_references ( PlannerInfo root,
Plan plan 
)

Definition at line 250 of file setrefs.c.

References add_rtes_to_flat_rtable(), PlannerInfo::append_rel_list, PlannerGlobal::appendRelations, AppendRelInfo::child_relid, PlannerGlobal::finalrowmarks, PlannerGlobal::finalrtable, PlannerInfo::glob, lappend(), lfirst_node, list_length(), NIL, palloc(), AppendRelInfo::parent_relid, PlanRowMark::prti, PlannerInfo::rowMarks, PlanRowMark::rti, set_plan_refs(), and AppendRelInfo::translated_vars.

Referenced by set_subqueryscan_references(), and standard_planner().

251 {
252  PlannerGlobal *glob = root->glob;
253  int rtoffset = list_length(glob->finalrtable);
254  ListCell *lc;
255 
256  /*
257  * Add all the query's RTEs to the flattened rangetable. The live ones
258  * will have their rangetable indexes increased by rtoffset. (Additional
259  * RTEs, not referenced by the Plan tree, might get added after those.)
260  */
261  add_rtes_to_flat_rtable(root, false);
262 
263  /*
264  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
265  */
266  foreach(lc, root->rowMarks)
267  {
269  PlanRowMark *newrc;
270 
271  /* flat copy is enough since all fields are scalars */
272  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
273  memcpy(newrc, rc, sizeof(PlanRowMark));
274 
275  /* adjust indexes ... but *not* the rowmarkId */
276  newrc->rti += rtoffset;
277  newrc->prti += rtoffset;
278 
279  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
280  }
281 
282  /*
283  * Adjust RT indexes of AppendRelInfos and add to final appendrels list.
284  * We assume the AppendRelInfos were built during planning and don't need
285  * to be copied.
286  */
287  foreach(lc, root->append_rel_list)
288  {
289  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
290 
291  /* adjust RT indexes */
292  appinfo->parent_relid += rtoffset;
293  appinfo->child_relid += rtoffset;
294 
295  /*
296  * Rather than adjust the translated_vars entries, just drop 'em.
297  * Neither the executor nor EXPLAIN currently need that data.
298  */
299  appinfo->translated_vars = NIL;
300 
301  glob->appendRelations = lappend(glob->appendRelations, appinfo);
302  }
303 
304  /* Now fix the Plan tree */
305  return set_plan_refs(root, plan, rtoffset);
306 }
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:290
List * appendRelations
Definition: pathnodes.h:123
Index prti
Definition: plannodes.h:1078
List * translated_vars
Definition: pathnodes.h:2256
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:499
#define lfirst_node(type, lc)
Definition: pg_list.h:172
PlannerGlobal * glob
Definition: pathnodes.h:179
List * lappend(List *list, void *datum)
Definition: list.c:321
List * append_rel_list
Definition: pathnodes.h:288
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:314
static int list_length(const List *l)
Definition: pg_list.h:149
List * finalrtable
Definition: pathnodes.h:117
void * palloc(Size size)
Definition: mcxt.c:950
Index child_relid
Definition: pathnodes.h:2229
Index parent_relid
Definition: pathnodes.h:2228
List * finalrowmarks
Definition: pathnodes.h:119

◆ set_plan_refs()

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

Definition at line 499 of file setrefs.c.

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

Referenced by set_append_references(), set_customscan_references(), set_mergeappend_references(), and set_plan_references().

500 {
501  ListCell *l;
502 
503  if (plan == NULL)
504  return NULL;
505 
506  /* Assign this node a unique ID. */
507  plan->plan_node_id = root->glob->lastPlanNodeId++;
508 
509  /*
510  * Plan-type-specific fixes
511  */
512  switch (nodeTag(plan))
513  {
514  case T_SeqScan:
515  {
516  SeqScan *splan = (SeqScan *) plan;
517 
518  splan->scanrelid += rtoffset;
519  splan->plan.targetlist =
520  fix_scan_list(root, splan->plan.targetlist,
521  rtoffset, NUM_EXEC_TLIST(plan));
522  splan->plan.qual =
523  fix_scan_list(root, splan->plan.qual,
524  rtoffset, NUM_EXEC_QUAL(plan));
525  }
526  break;
527  case T_SampleScan:
528  {
529  SampleScan *splan = (SampleScan *) plan;
530 
531  splan->scan.scanrelid += rtoffset;
532  splan->scan.plan.targetlist =
533  fix_scan_list(root, splan->scan.plan.targetlist,
534  rtoffset, NUM_EXEC_TLIST(plan));
535  splan->scan.plan.qual =
536  fix_scan_list(root, splan->scan.plan.qual,
537  rtoffset, NUM_EXEC_QUAL(plan));
538  splan->tablesample = (TableSampleClause *)
539  fix_scan_expr(root, (Node *) splan->tablesample,
540  rtoffset, 1);
541  }
542  break;
543  case T_IndexScan:
544  {
545  IndexScan *splan = (IndexScan *) plan;
546 
547  splan->scan.scanrelid += rtoffset;
548  splan->scan.plan.targetlist =
549  fix_scan_list(root, splan->scan.plan.targetlist,
550  rtoffset, NUM_EXEC_TLIST(plan));
551  splan->scan.plan.qual =
552  fix_scan_list(root, splan->scan.plan.qual,
553  rtoffset, NUM_EXEC_QUAL(plan));
554  splan->indexqual =
555  fix_scan_list(root, splan->indexqual,
556  rtoffset, 1);
557  splan->indexqualorig =
558  fix_scan_list(root, splan->indexqualorig,
559  rtoffset, NUM_EXEC_QUAL(plan));
560  splan->indexorderby =
561  fix_scan_list(root, splan->indexorderby,
562  rtoffset, 1);
563  splan->indexorderbyorig =
564  fix_scan_list(root, splan->indexorderbyorig,
565  rtoffset, NUM_EXEC_QUAL(plan));
566  }
567  break;
568  case T_IndexOnlyScan:
569  {
570  IndexOnlyScan *splan = (IndexOnlyScan *) plan;
571 
572  return set_indexonlyscan_references(root, splan, rtoffset);
573  }
574  break;
575  case T_BitmapIndexScan:
576  {
577  BitmapIndexScan *splan = (BitmapIndexScan *) plan;
578 
579  splan->scan.scanrelid += rtoffset;
580  /* no need to fix targetlist and qual */
581  Assert(splan->scan.plan.targetlist == NIL);
582  Assert(splan->scan.plan.qual == NIL);
583  splan->indexqual =
584  fix_scan_list(root, splan->indexqual, rtoffset, 1);
585  splan->indexqualorig =
586  fix_scan_list(root, splan->indexqualorig,
587  rtoffset, NUM_EXEC_QUAL(plan));
588  }
589  break;
590  case T_BitmapHeapScan:
591  {
592  BitmapHeapScan *splan = (BitmapHeapScan *) plan;
593 
594  splan->scan.scanrelid += rtoffset;
595  splan->scan.plan.targetlist =
596  fix_scan_list(root, splan->scan.plan.targetlist,
597  rtoffset, NUM_EXEC_TLIST(plan));
598  splan->scan.plan.qual =
599  fix_scan_list(root, splan->scan.plan.qual,
600  rtoffset, NUM_EXEC_QUAL(plan));
601  splan->bitmapqualorig =
602  fix_scan_list(root, splan->bitmapqualorig,
603  rtoffset, NUM_EXEC_QUAL(plan));
604  }
605  break;
606  case T_TidScan:
607  {
608  TidScan *splan = (TidScan *) plan;
609 
610  splan->scan.scanrelid += rtoffset;
611  splan->scan.plan.targetlist =
612  fix_scan_list(root, splan->scan.plan.targetlist,
613  rtoffset, NUM_EXEC_TLIST(plan));
614  splan->scan.plan.qual =
615  fix_scan_list(root, splan->scan.plan.qual,
616  rtoffset, NUM_EXEC_QUAL(plan));
617  splan->tidquals =
618  fix_scan_list(root, splan->tidquals,
619  rtoffset, 1);
620  }
621  break;
622  case T_SubqueryScan:
623  /* Needs special treatment, see comments below */
624  return set_subqueryscan_references(root,
625  (SubqueryScan *) plan,
626  rtoffset);
627  case T_FunctionScan:
628  {
629  FunctionScan *splan = (FunctionScan *) plan;
630 
631  splan->scan.scanrelid += rtoffset;
632  splan->scan.plan.targetlist =
633  fix_scan_list(root, splan->scan.plan.targetlist,
634  rtoffset, NUM_EXEC_TLIST(plan));
635  splan->scan.plan.qual =
636  fix_scan_list(root, splan->scan.plan.qual,
637  rtoffset, NUM_EXEC_QUAL(plan));
638  splan->functions =
639  fix_scan_list(root, splan->functions, rtoffset, 1);
640  }
641  break;
642  case T_TableFuncScan:
643  {
644  TableFuncScan *splan = (TableFuncScan *) plan;
645 
646  splan->scan.scanrelid += rtoffset;
647  splan->scan.plan.targetlist =
648  fix_scan_list(root, splan->scan.plan.targetlist,
649  rtoffset, NUM_EXEC_TLIST(plan));
650  splan->scan.plan.qual =
651  fix_scan_list(root, splan->scan.plan.qual,
652  rtoffset, NUM_EXEC_QUAL(plan));
653  splan->tablefunc = (TableFunc *)
654  fix_scan_expr(root, (Node *) splan->tablefunc,
655  rtoffset, 1);
656  }
657  break;
658  case T_ValuesScan:
659  {
660  ValuesScan *splan = (ValuesScan *) plan;
661 
662  splan->scan.scanrelid += rtoffset;
663  splan->scan.plan.targetlist =
664  fix_scan_list(root, splan->scan.plan.targetlist,
665  rtoffset, NUM_EXEC_TLIST(plan));
666  splan->scan.plan.qual =
667  fix_scan_list(root, splan->scan.plan.qual,
668  rtoffset, NUM_EXEC_QUAL(plan));
669  splan->values_lists =
670  fix_scan_list(root, splan->values_lists,
671  rtoffset, 1);
672  }
673  break;
674  case T_CteScan:
675  {
676  CteScan *splan = (CteScan *) plan;
677 
678  splan->scan.scanrelid += rtoffset;
679  splan->scan.plan.targetlist =
680  fix_scan_list(root, splan->scan.plan.targetlist,
681  rtoffset, NUM_EXEC_TLIST(plan));
682  splan->scan.plan.qual =
683  fix_scan_list(root, splan->scan.plan.qual,
684  rtoffset, NUM_EXEC_QUAL(plan));
685  }
686  break;
688  {
689  NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
690 
691  splan->scan.scanrelid += rtoffset;
692  splan->scan.plan.targetlist =
693  fix_scan_list(root, splan->scan.plan.targetlist,
694  rtoffset, NUM_EXEC_TLIST(plan));
695  splan->scan.plan.qual =
696  fix_scan_list(root, splan->scan.plan.qual,
697  rtoffset, NUM_EXEC_QUAL(plan));
698  }
699  break;
700  case T_WorkTableScan:
701  {
702  WorkTableScan *splan = (WorkTableScan *) plan;
703 
704  splan->scan.scanrelid += rtoffset;
705  splan->scan.plan.targetlist =
706  fix_scan_list(root, splan->scan.plan.targetlist,
707  rtoffset, NUM_EXEC_TLIST(plan));
708  splan->scan.plan.qual =
709  fix_scan_list(root, splan->scan.plan.qual,
710  rtoffset, NUM_EXEC_QUAL(plan));
711  }
712  break;
713  case T_ForeignScan:
714  set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
715  break;
716  case T_CustomScan:
717  set_customscan_references(root, (CustomScan *) plan, rtoffset);
718  break;
719 
720  case T_NestLoop:
721  case T_MergeJoin:
722  case T_HashJoin:
723  set_join_references(root, (Join *) plan, rtoffset);
724  break;
725 
726  case T_Gather:
727  case T_GatherMerge:
728  {
729  set_upper_references(root, plan, rtoffset);
730  set_param_references(root, plan);
731  }
732  break;
733 
734  case T_Hash:
735  set_hash_references(root, plan, rtoffset);
736  break;
737 
738  case T_Material:
739  case T_Sort:
740  case T_IncrementalSort:
741  case T_Unique:
742  case T_SetOp:
743 
744  /*
745  * These plan types don't actually bother to evaluate their
746  * targetlists, because they just return their unmodified input
747  * tuples. Even though the targetlist won't be used by the
748  * executor, we fix it up for possible use by EXPLAIN (not to
749  * mention ease of debugging --- wrong varnos are very confusing).
750  */
751  set_dummy_tlist_references(plan, rtoffset);
752 
753  /*
754  * Since these plan types don't check quals either, we should not
755  * find any qual expression attached to them.
756  */
757  Assert(plan->qual == NIL);
758  break;
759  case T_LockRows:
760  {
761  LockRows *splan = (LockRows *) plan;
762 
763  /*
764  * Like the plan types above, LockRows doesn't evaluate its
765  * tlist or quals. But we have to fix up the RT indexes in
766  * its rowmarks.
767  */
768  set_dummy_tlist_references(plan, rtoffset);
769  Assert(splan->plan.qual == NIL);
770 
771  foreach(l, splan->rowMarks)
772  {
773  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
774 
775  rc->rti += rtoffset;
776  rc->prti += rtoffset;
777  }
778  }
779  break;
780  case T_Limit:
781  {
782  Limit *splan = (Limit *) plan;
783 
784  /*
785  * Like the plan types above, Limit doesn't evaluate its tlist
786  * or quals. It does have live expressions for limit/offset,
787  * however; and those cannot contain subplan variable refs, so
788  * fix_scan_expr works for them.
789  */
790  set_dummy_tlist_references(plan, rtoffset);
791  Assert(splan->plan.qual == NIL);
792 
793  splan->limitOffset =
794  fix_scan_expr(root, splan->limitOffset, rtoffset, 1);
795  splan->limitCount =
796  fix_scan_expr(root, splan->limitCount, rtoffset, 1);
797  }
798  break;
799  case T_Agg:
800  {
801  Agg *agg = (Agg *) plan;
802 
803  /*
804  * If this node is combining partial-aggregation results, we
805  * must convert its Aggrefs to contain references to the
806  * partial-aggregate subexpressions that will be available
807  * from the child plan node.
808  */
809  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
810  {
811  plan->targetlist = (List *)
813  NULL);
814  plan->qual = (List *)
816  NULL);
817  }
818 
819  set_upper_references(root, plan, rtoffset);
820  }
821  break;
822  case T_Group:
823  set_upper_references(root, plan, rtoffset);
824  break;
825  case T_WindowAgg:
826  {
827  WindowAgg *wplan = (WindowAgg *) plan;
828 
829  set_upper_references(root, plan, rtoffset);
830 
831  /*
832  * Like Limit node limit/offset expressions, WindowAgg has
833  * frame offset expressions, which cannot contain subplan
834  * variable refs, so fix_scan_expr works for them.
835  */
836  wplan->startOffset =
837  fix_scan_expr(root, wplan->startOffset, rtoffset, 1);
838  wplan->endOffset =
839  fix_scan_expr(root, wplan->endOffset, rtoffset, 1);
840  }
841  break;
842  case T_Result:
843  {
844  Result *splan = (Result *) plan;
845 
846  /*
847  * Result may or may not have a subplan; if not, it's more
848  * like a scan node than an upper node.
849  */
850  if (splan->plan.lefttree != NULL)
851  set_upper_references(root, plan, rtoffset);
852  else
853  {
854  splan->plan.targetlist =
855  fix_scan_list(root, splan->plan.targetlist,
856  rtoffset, NUM_EXEC_TLIST(plan));
857  splan->plan.qual =
858  fix_scan_list(root, splan->plan.qual,
859  rtoffset, NUM_EXEC_QUAL(plan));
860  }
861  /* resconstantqual can't contain any subplan variable refs */
862  splan->resconstantqual =
863  fix_scan_expr(root, splan->resconstantqual, rtoffset, 1);
864  }
865  break;
866  case T_ProjectSet:
867  set_upper_references(root, plan, rtoffset);
868  break;
869  case T_ModifyTable:
870  {
871  ModifyTable *splan = (ModifyTable *) plan;
872 
873  Assert(splan->plan.targetlist == NIL);
874  Assert(splan->plan.qual == NIL);
875 
876  splan->withCheckOptionLists =
877  fix_scan_list(root, splan->withCheckOptionLists,
878  rtoffset, 1);
879 
880  if (splan->returningLists)
881  {
882  List *newRL = NIL;
883  ListCell *lcrl,
884  *lcrr,
885  *lcp;
886 
887  /*
888  * Pass each per-subplan returningList through
889  * set_returning_clause_references().
890  */
892  Assert(list_length(splan->returningLists) == list_length(splan->plans));
893  forthree(lcrl, splan->returningLists,
894  lcrr, splan->resultRelations,
895  lcp, splan->plans)
896  {
897  List *rlist = (List *) lfirst(lcrl);
898  Index resultrel = lfirst_int(lcrr);
899  Plan *subplan = (Plan *) lfirst(lcp);
900 
901  rlist = set_returning_clause_references(root,
902  rlist,
903  subplan,
904  resultrel,
905  rtoffset);
906  newRL = lappend(newRL, rlist);
907  }
908  splan->returningLists = newRL;
909 
910  /*
911  * Set up the visible plan targetlist as being the same as
912  * the first RETURNING list. This is for the use of
913  * EXPLAIN; the executor won't pay any attention to the
914  * targetlist. We postpone this step until here so that
915  * we don't have to do set_returning_clause_references()
916  * twice on identical targetlists.
917  */
918  splan->plan.targetlist = copyObject(linitial(newRL));
919  }
920 
921  /*
922  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
923  * join', where the inner side is the EXCLUDED tuple.
924  * Therefore use fix_join_expr to setup the relevant variables
925  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
926  * those are already used by RETURNING and it seems better to
927  * be non-conflicting.
928  */
929  if (splan->onConflictSet)
930  {
931  indexed_tlist *itlist;
932 
933  itlist = build_tlist_index(splan->exclRelTlist);
934 
935  splan->onConflictSet =
936  fix_join_expr(root, splan->onConflictSet,
937  NULL, itlist,
939  rtoffset, NUM_EXEC_QUAL(plan));
940 
941  splan->onConflictWhere = (Node *)
942  fix_join_expr(root, (List *) splan->onConflictWhere,
943  NULL, itlist,
945  rtoffset, NUM_EXEC_QUAL(plan));
946 
947  pfree(itlist);
948 
949  splan->exclRelTlist =
950  fix_scan_list(root, splan->exclRelTlist, rtoffset, 1);
951  }
952 
953  splan->nominalRelation += rtoffset;
954  if (splan->rootRelation)
955  splan->rootRelation += rtoffset;
956  splan->exclRelRTI += rtoffset;
957 
958  foreach(l, splan->resultRelations)
959  {
960  lfirst_int(l) += rtoffset;
961  }
962  foreach(l, splan->rowMarks)
963  {
964  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
965 
966  rc->rti += rtoffset;
967  rc->prti += rtoffset;
968  }
969  foreach(l, splan->plans)
970  {
971  lfirst(l) = set_plan_refs(root,
972  (Plan *) lfirst(l),
973  rtoffset);
974  }
975 
976  /*
977  * Append this ModifyTable node's final result relation RT
978  * index(es) to the global list for the plan.
979  */
980  root->glob->resultRelations =
982  splan->resultRelations);
983  if (splan->rootRelation)
984  {
985  root->glob->resultRelations =
987  splan->rootRelation);
988  }
989  }
990  break;
991  case T_Append:
992  /* Needs special treatment, see comments below */
993  return set_append_references(root,
994  (Append *) plan,
995  rtoffset);
996  case T_MergeAppend:
997  /* Needs special treatment, see comments below */
998  return set_mergeappend_references(root,
999  (MergeAppend *) plan,
1000  rtoffset);
1001  case T_RecursiveUnion:
1002  /* This doesn't evaluate targetlist or check quals either */
1003  set_dummy_tlist_references(plan, rtoffset);
1004  Assert(plan->qual == NIL);
1005  break;
1006  case T_BitmapAnd:
1007  {
1008  BitmapAnd *splan = (BitmapAnd *) plan;
1009 
1010  /* BitmapAnd works like Append, but has no tlist */
1011  Assert(splan->plan.targetlist == NIL);
1012  Assert(splan->plan.qual == NIL);
1013  foreach(l, splan->bitmapplans)
1014  {
1015  lfirst(l) = set_plan_refs(root,
1016  (Plan *) lfirst(l),
1017  rtoffset);
1018  }
1019  }
1020  break;
1021  case T_BitmapOr:
1022  {
1023  BitmapOr *splan = (BitmapOr *) plan;
1024 
1025  /* BitmapOr works like Append, but has no tlist */
1026  Assert(splan->plan.targetlist == NIL);
1027  Assert(splan->plan.qual == NIL);
1028  foreach(l, splan->bitmapplans)
1029  {
1030  lfirst(l) = set_plan_refs(root,
1031  (Plan *) lfirst(l),
1032  rtoffset);
1033  }
1034  }
1035  break;
1036  default:
1037  elog(ERROR, "unrecognized node type: %d",
1038  (int) nodeTag(plan));
1039  break;
1040  }
1041 
1042  /*
1043  * Now recurse into child plans, if any
1044  *
1045  * NOTE: it is essential that we recurse into child plans AFTER we set
1046  * subplan references in this plan's tlist and quals. If we did the
1047  * reference-adjustments bottom-up, then we would fail to match this
1048  * plan's var nodes against the already-modified nodes of the children.
1049  */
1050  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
1051  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1052 
1053  return plan;
1054 }
List * bitmapplans
Definition: plannodes.h:311
#define NIL
Definition: pg_list.h:65
Plan plan
Definition: plannodes.h:182
List * qual
Definition: plannodes.h:137
Definition: nodes.h:79
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:336
Plan plan
Definition: plannodes.h:982
Index nominalRelation
Definition: plannodes.h:217
Definition: nodes.h:81
Index scanrelid
Definition: plannodes.h:337
Plan plan
Definition: plannodes.h:968
List * withCheckOptionLists
Definition: plannodes.h:222
List * functions
Definition: plannodes.h:517
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset)
Definition: setrefs.c:1909
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:479
int lastPlanNodeId
Definition: pathnodes.h:135
List * indexqual
Definition: plannodes.h:455
List * tidquals
Definition: plannodes.h:485
TableFunc * tablefunc
Definition: plannodes.h:538
int plan_node_id
Definition: plannodes.h:135
List * resultRelations
Definition: pathnodes.h:121
List * indexqualorig
Definition: plannodes.h:399
struct TableSampleClause * tablesample
Definition: plannodes.h:354
Definition: nodes.h:528
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: nodes.h:49
Index prti
Definition: plannodes.h:1078
List * values_lists
Definition: plannodes.h:528
static void set_param_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:2123
Definition: nodes.h:76
Scan scan
Definition: plannodes.h:527
Node * limitOffset
Definition: plannodes.h:983
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:790
static Plan * set_append_references(PlannerInfo *root, Append *aplan, int rtoffset)
Definition: setrefs.c:1397
List * plans
Definition: plannodes.h:221
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:499
List * onConflictSet
Definition: plannodes.h:230
Index rootRelation
Definition: plannodes.h:218
List * resultRelations
Definition: plannodes.h:220
static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, int rtoffset)
Definition: setrefs.c:1242
#define linitial_int(l)
Definition: pg_list.h:175
Node * startOffset
Definition: plannodes.h:850
Node * resconstantqual
Definition: plannodes.h:183
List * rowMarks
Definition: plannodes.h:226
struct Plan * righttree
Definition: plannodes.h:139
void pfree(void *pointer)
Definition: mcxt.c:1057
#define linitial(l)
Definition: pg_list.h:174
Definition: nodes.h:46
#define ERROR
Definition: elog.h:43
List * indexorderbyorig
Definition: plannodes.h:401
#define lfirst_int(lc)
Definition: pg_list.h:170
Scan scan
Definition: plannodes.h:352
Scan scan
Definition: plannodes.h:547
Node * limitCount
Definition: plannodes.h:984
Scan scan
Definition: plannodes.h:396
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
Definition: nodes.h:78
PlannerGlobal * glob
Definition: pathnodes.h:179
Node * endOffset
Definition: plannodes.h:851
static SPIPlanPtr splan
Definition: regress.c:259
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1324
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:1112
List * indexqual
Definition: plannodes.h:398
List * bitmapqualorig
Definition: plannodes.h:471
List * lappend_int(List *list, int datum)
Definition: list.c:339
List * lappend(List *list, void *datum)
Definition: list.c:321
Plan plan
Definition: plannodes.h:324
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:1066
List * bitmapplans
Definition: plannodes.h:326
static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:2060
unsigned int Index
Definition: c.h:483
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
Definition: nodes.h:84
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:2178
List * indexorderby
Definition: plannodes.h:400
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
AggSplit aggsplit
Definition: plannodes.h:820
List * rowMarks
Definition: plannodes.h:969
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
Scan scan
Definition: plannodes.h:484
static int list_length(const List *l)
Definition: pg_list.h:149
struct Plan * lefttree
Definition: plannodes.h:138
List * indexqualorig
Definition: plannodes.h:456
#define nodeTag(nodeptr)
Definition: nodes.h:533
List * targetlist
Definition: plannodes.h:136
Definition: nodes.h:85
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2839
Definition: nodes.h:82
#define elog(elevel,...)
Definition: elog.h:214
List * returningLists
Definition: plannodes.h:223
Plan plan
Definition: plannodes.h:310
Definition: plannodes.h:816
#define copyObject(obj)
Definition: nodes.h:644
Index exclRelRTI
Definition: plannodes.h:232
static Plan * set_mergeappend_references(PlannerInfo *root, MergeAppend *mplan, int rtoffset)
Definition: setrefs.c:1461
Definition: pg_list.h:50
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset, double num_exec)
Definition: setrefs.c:1780
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2247
List * exclRelTlist
Definition: plannodes.h:233
static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1522
Node * onConflictWhere
Definition: plannodes.h:231
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset, double num_exec)
Definition: setrefs.c:2560
Definition: nodes.h:87

◆ set_returning_clause_references()

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

Definition at line 2839 of file setrefs.c.

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

Referenced by set_plan_refs().

2844 {
2845  indexed_tlist *itlist;
2846 
2847  /*
2848  * We can perform the desired Var fixup by abusing the fix_join_expr
2849  * machinery that formerly handled inner indexscan fixup. We search the
2850  * top plan's targetlist for Vars of non-result relations, and use
2851  * fix_join_expr to convert RETURNING Vars into references to those tlist
2852  * entries, while leaving result-rel Vars as-is.
2853  *
2854  * PlaceHolderVars will also be sought in the targetlist, but no
2855  * more-complex expressions will be. Note that it is not possible for a
2856  * PlaceHolderVar to refer to the result relation, since the result is
2857  * never below an outer join. If that case could happen, we'd have to be
2858  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2859  * expression instead.
2860  */
2861  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2862 
2863  rlist = fix_join_expr(root,
2864  rlist,
2865  itlist,
2866  NULL,
2867  resultRelation,
2868  rtoffset,
2869  NUM_EXEC_TLIST(topplan));
2870 
2871  pfree(itlist);
2872 
2873  return rlist;
2874 }
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static indexed_tlist * build_tlist_index_other_vars(List *tlist, Index ignore_rel)
Definition: setrefs.c:2364
List * targetlist
Definition: plannodes.h:136
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset, double num_exec)
Definition: setrefs.c:2560

◆ set_subqueryscan_references()

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

Definition at line 1112 of file setrefs.c.

References clean_up_removed_plan_level(), find_base_rel(), fix_scan_list, NUM_EXEC_QUAL, NUM_EXEC_TLIST, Scan::plan, Plan::qual, SubqueryScan::scan, Scan::scanrelid, set_plan_references(), SubqueryScan::subplan, RelOptInfo::subroot, Plan::targetlist, and trivial_subqueryscan().

Referenced by set_plan_refs().

1115 {
1116  RelOptInfo *rel;
1117  Plan *result;
1118 
1119  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1120  rel = find_base_rel(root, plan->scan.scanrelid);
1121 
1122  /* Recursively process the subplan */
1123  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1124 
1125  if (trivial_subqueryscan(plan))
1126  {
1127  /*
1128  * We can omit the SubqueryScan node and just pull up the subplan.
1129  */
1130  result = clean_up_removed_plan_level((Plan *) plan, plan->subplan);
1131  }
1132  else
1133  {
1134  /*
1135  * Keep the SubqueryScan node. We have to do the processing that
1136  * set_plan_references would otherwise have done on it. Notice we do
1137  * not do set_upper_references() here, because a SubqueryScan will
1138  * always have been created with correct references to its subplan's
1139  * outputs to begin with.
1140  */
1141  plan->scan.scanrelid += rtoffset;
1142  plan->scan.plan.targetlist =
1143  fix_scan_list(root, plan->scan.plan.targetlist,
1144  rtoffset, NUM_EXEC_TLIST((Plan *) plan));
1145  plan->scan.plan.qual =
1146  fix_scan_list(root, plan->scan.plan.qual,
1147  rtoffset, NUM_EXEC_QUAL((Plan *) plan));
1148 
1149  result = (Plan *) plan;
1150  }
1151 
1152  return result;
1153 }
List * qual
Definition: plannodes.h:137
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:336
Index scanrelid
Definition: plannodes.h:337
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1163
PlannerInfo * subroot
Definition: pathnodes.h:708
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1221
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
List * targetlist
Definition: plannodes.h:136
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:250
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:374
Plan * subplan
Definition: plannodes.h:507

◆ set_upper_references()

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

Definition at line 2060 of file setrefs.c.

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

Referenced by set_plan_refs().

2061 {
2062  Plan *subplan = plan->lefttree;
2063  indexed_tlist *subplan_itlist;
2064  List *output_targetlist;
2065  ListCell *l;
2066 
2067  subplan_itlist = build_tlist_index(subplan->targetlist);
2068 
2069  output_targetlist = NIL;
2070  foreach(l, plan->targetlist)
2071  {
2072  TargetEntry *tle = (TargetEntry *) lfirst(l);
2073  Node *newexpr;
2074 
2075  /* If it's a sort/group item, first try to match by sortref */
2076  if (tle->ressortgroupref != 0)
2077  {
2078  newexpr = (Node *)
2080  tle->ressortgroupref,
2081  subplan_itlist,
2082  OUTER_VAR);
2083  if (!newexpr)
2084  newexpr = fix_upper_expr(root,
2085  (Node *) tle->expr,
2086  subplan_itlist,
2087  OUTER_VAR,
2088  rtoffset,
2089  NUM_EXEC_TLIST(plan));
2090  }
2091  else
2092  newexpr = fix_upper_expr(root,
2093  (Node *) tle->expr,
2094  subplan_itlist,
2095  OUTER_VAR,
2096  rtoffset,
2097  NUM_EXEC_TLIST(plan));
2098  tle = flatCopyTargetEntry(tle);
2099  tle->expr = (Expr *) newexpr;
2100  output_targetlist = lappend(output_targetlist, tle);
2101  }
2102  plan->targetlist = output_targetlist;
2103 
2104  plan->qual = (List *)
2105  fix_upper_expr(root,
2106  (Node *) plan->qual,
2107  subplan_itlist,
2108  OUTER_VAR,
2109  rtoffset,
2110  NUM_EXEC_QUAL(plan));
2111 
2112  pfree(subplan_itlist);
2113 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
Definition: nodes.h:528
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2713
void pfree(void *pointer)
Definition: mcxt.c:1057
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
List * lappend(List *list, void *datum)
Definition: list.c:321
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2314
struct Plan * lefttree
Definition: plannodes.h:138
List * targetlist
Definition: plannodes.h:136
Index ressortgroupref
Definition: primnodes.h:1413
static Var * search_indexed_tlist_for_sortgroupref(Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2495
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:172

◆ trivial_subqueryscan()

static bool trivial_subqueryscan ( SubqueryScan plan)
static

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

1164 {
1165  int attrno;
1166  ListCell *lp,
1167  *lc;
1168 
1169  if (plan->scan.plan.qual != NIL)
1170  return false;
1171 
1172  if (list_length(plan->scan.plan.targetlist) !=
1173  list_length(plan->subplan->targetlist))
1174  return false; /* tlists not same length */
1175 
1176  attrno = 1;
1177  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1178  {
1179  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1180  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1181 
1182  if (ptle->resjunk != ctle->resjunk)
1183  return false; /* tlist doesn't match junk status */
1184 
1185  /*
1186  * We accept either a Var referencing the corresponding element of the
1187  * subplan tlist, or a Const equaling the subplan element. See
1188  * generate_setop_tlist() for motivation.
1189  */
1190  if (ptle->expr && IsA(ptle->expr, Var))
1191  {
1192  Var *var = (Var *) ptle->expr;
1193 
1194  Assert(var->varno == plan->scan.scanrelid);
1195  Assert(var->varlevelsup == 0);
1196  if (var->varattno != attrno)
1197  return false; /* out of order */
1198  }
1199  else if (ptle->expr && IsA(ptle->expr, Const))
1200  {
1201  if (!equal(ptle->expr, ctle->expr))
1202  return false;
1203  }
1204  else
1205  return false;
1206 
1207  attrno++;
1208  }
1209 
1210  return true;
1211 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:137
Plan plan
Definition: plannodes.h:336
#define IsA(nodeptr, _type_)
Definition: nodes.h:579
Index varlevelsup
Definition: primnodes.h:191
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:434
Index scanrelid
Definition: plannodes.h:337
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3032
AttrNumber varattno
Definition: primnodes.h:186
Definition: primnodes.h:181
bool resjunk
Definition: primnodes.h:1417
Index varno
Definition: primnodes.h:184
#define Assert(condition)
Definition: c.h:746
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1410
static int list_length(const List *l)
Definition: pg_list.h:149
List * targetlist
Definition: plannodes.h:136
Plan * subplan
Definition: plannodes.h:507