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, int newvarno, int rtoffset)
 
static Varsearch_indexed_tlist_for_non_var (Expr *node, indexed_tlist *itlist, int newvarno)
 
static Varsearch_indexed_tlist_for_sortgroupref (Expr *node, Index sortgroupref, indexed_tlist *itlist, int 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, int 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, int 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 483 of file setrefs.c.

References RangeTblEntry::colcollations, RangeTblEntry::coltypes, RangeTblEntry::coltypmods, PlannerGlobal::finalrtable, RangeTblEntry::functions, RangeTblEntry::join_using_alias, RangeTblEntry::joinaliasvars, RangeTblEntry::joinleftcols, RangeTblEntry::joinrightcols, lappend(), lappend_oid(), 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().

484 {
485  RangeTblEntry *newrte;
486 
487  /* flat copy to duplicate all the scalar fields */
488  newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
489  memcpy(newrte, rte, sizeof(RangeTblEntry));
490 
491  /* zap unneeded sub-structure */
492  newrte->tablesample = NULL;
493  newrte->subquery = NULL;
494  newrte->joinaliasvars = NIL;
495  newrte->joinleftcols = NIL;
496  newrte->joinrightcols = NIL;
497  newrte->join_using_alias = NULL;
498  newrte->functions = NIL;
499  newrte->tablefunc = NULL;
500  newrte->values_lists = NIL;
501  newrte->coltypes = NIL;
502  newrte->coltypmods = NIL;
503  newrte->colcollations = NIL;
504  newrte->securityQuals = NIL;
505 
506  glob->finalrtable = lappend(glob->finalrtable, newrte);
507 
508  /*
509  * If it's a plain relation RTE, add the table to relationOids.
510  *
511  * We do this even though the RTE might be unreferenced in the plan tree;
512  * this would correspond to cases such as views that were expanded, child
513  * tables that were eliminated by constraint exclusion, etc. Schema
514  * invalidation on such a rel must still force rebuilding of the plan.
515  *
516  * Note we don't bother to avoid making duplicate list entries. We could,
517  * but it would probably cost more cycles than it would save.
518  */
519  if (newrte->rtekind == RTE_RELATION)
520  glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
521 }
#define NIL
Definition: pg_list.h:65
List * joinaliasvars
Definition: parsenodes.h:1082
List * securityQuals
Definition: parsenodes.h:1163
List * coltypmods
Definition: parsenodes.h:1140
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
List * colcollations
Definition: parsenodes.h:1141
List * values_lists
Definition: parsenodes.h:1112
TableFunc * tablefunc
Definition: parsenodes.h:1107
List * joinrightcols
Definition: parsenodes.h:1084
List * lappend(List *list, void *datum)
Definition: list.c:336
List * joinleftcols
Definition: parsenodes.h:1083
Alias * join_using_alias
Definition: parsenodes.h:1091
List * functions
Definition: parsenodes.h:1101
List * relationOids
Definition: pathnodes.h:110
RTEKind rtekind
Definition: parsenodes.h:1007
List * finalrtable
Definition: pathnodes.h:102
Query * subquery
Definition: parsenodes.h:1042
void * palloc(Size size)
Definition: mcxt.c:1062
List * coltypes
Definition: parsenodes.h:1139
struct TableSampleClause * tablesample
Definition: parsenodes.h:1037

◆ add_rtes_to_flat_rtable()

static void add_rtes_to_flat_rtable ( PlannerInfo root,
bool  recursing 
)
static

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

352 {
353  PlannerGlobal *glob = root->glob;
354  Index rti;
355  ListCell *lc;
356 
357  /*
358  * Add the query's own RTEs to the flattened rangetable.
359  *
360  * At top level, we must add all RTEs so that their indexes in the
361  * flattened rangetable match up with their original indexes. When
362  * recursing, we only care about extracting relation RTEs.
363  */
364  foreach(lc, root->parse->rtable)
365  {
366  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
367 
368  if (!recursing || rte->rtekind == RTE_RELATION)
369  add_rte_to_flat_rtable(glob, rte);
370  }
371 
372  /*
373  * If there are any dead subqueries, they are not referenced in the Plan
374  * tree, so we must add RTEs contained in them to the flattened rtable
375  * separately. (If we failed to do this, the executor would not perform
376  * expected permission checks for tables mentioned in such subqueries.)
377  *
378  * Note: this pass over the rangetable can't be combined with the previous
379  * one, because that would mess up the numbering of the live RTEs in the
380  * flattened rangetable.
381  */
382  rti = 1;
383  foreach(lc, root->parse->rtable)
384  {
385  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
386 
387  /*
388  * We should ignore inheritance-parent RTEs: their contents have been
389  * pulled up into our rangetable already. Also ignore any subquery
390  * RTEs without matching RelOptInfos, as they likewise have been
391  * pulled up.
392  */
393  if (rte->rtekind == RTE_SUBQUERY && !rte->inh &&
394  rti < root->simple_rel_array_size)
395  {
396  RelOptInfo *rel = root->simple_rel_array[rti];
397 
398  if (rel != NULL)
399  {
400  Assert(rel->relid == rti); /* sanity check on array */
401 
402  /*
403  * The subquery might never have been planned at all, if it
404  * was excluded on the basis of self-contradictory constraints
405  * in our query level. In this case apply
406  * flatten_unplanned_rtes.
407  *
408  * If it was planned but the result rel is dummy, we assume
409  * that it has been omitted from our plan tree (see
410  * set_subquery_pathlist), and recurse to pull up its RTEs.
411  *
412  * Otherwise, it should be represented by a SubqueryScan node
413  * somewhere in our plan tree, and we'll pull up its RTEs when
414  * we process that plan node.
415  *
416  * However, if we're recursing, then we should pull up RTEs
417  * whether the subquery is dummy or not, because we've found
418  * that some upper query level is treating this one as dummy,
419  * and so we won't scan this level's plan tree at all.
420  */
421  if (rel->subroot == NULL)
422  flatten_unplanned_rtes(glob, rte);
423  else if (recursing ||
425  UPPERREL_FINAL, NULL)))
426  add_rtes_to_flat_rtable(rel->subroot, true);
427  }
428  }
429  rti++;
430  }
431 }
Query * parse
Definition: pathnodes.h:162
static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:437
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:483
struct RelOptInfo ** simple_rel_array
Definition: pathnodes.h:186
PlannerInfo * subroot
Definition: pathnodes.h:725
List * rtable
Definition: parsenodes.h:147
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:1466
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1210
PlannerGlobal * glob
Definition: pathnodes.h:164
Index relid
Definition: pathnodes.h:709
unsigned int Index
Definition: c.h:549
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:351
RTEKind rtekind
Definition: parsenodes.h:1007

◆ build_tlist_index()

static indexed_tlist * build_tlist_index ( List tlist)
static

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

2389 {
2390  indexed_tlist *itlist;
2391  tlist_vinfo *vinfo;
2392  ListCell *l;
2393 
2394  /* Create data structure with enough slots for all tlist entries */
2395  itlist = (indexed_tlist *)
2397  list_length(tlist) * sizeof(tlist_vinfo));
2398 
2399  itlist->tlist = tlist;
2400  itlist->has_ph_vars = false;
2401  itlist->has_non_vars = false;
2402 
2403  /* Find the Vars and fill in the index array */
2404  vinfo = itlist->vars;
2405  foreach(l, tlist)
2406  {
2407  TargetEntry *tle = (TargetEntry *) lfirst(l);
2408 
2409  if (tle->expr && IsA(tle->expr, Var))
2410  {
2411  Var *var = (Var *) tle->expr;
2412 
2413  vinfo->varno = var->varno;
2414  vinfo->varattno = var->varattno;
2415  vinfo->resno = tle->resno;
2416  vinfo++;
2417  }
2418  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2419  itlist->has_ph_vars = true;
2420  else
2421  itlist->has_non_vars = true;
2422  }
2423 
2424  itlist->num_vars = (vinfo - itlist->vars);
2425 
2426  return itlist;
2427 }
int varno
Definition: primnodes.h:189
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:191
Definition: primnodes.h:186
int varno
Definition: setrefs.c:34
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:1456
bool has_non_vars
Definition: setrefs.c:44
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
Definition: regcomp.c:237
#define offsetof(type, field)
Definition: c.h:727
List * tlist
Definition: setrefs.c:41

◆ build_tlist_index_other_vars()

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

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

2439 {
2440  indexed_tlist *itlist;
2441  tlist_vinfo *vinfo;
2442  ListCell *l;
2443 
2444  /* Create data structure with enough slots for all tlist entries */
2445  itlist = (indexed_tlist *)
2447  list_length(tlist) * sizeof(tlist_vinfo));
2448 
2449  itlist->tlist = tlist;
2450  itlist->has_ph_vars = false;
2451  itlist->has_non_vars = false;
2452 
2453  /* Find the desired Vars and fill in the index array */
2454  vinfo = itlist->vars;
2455  foreach(l, tlist)
2456  {
2457  TargetEntry *tle = (TargetEntry *) lfirst(l);
2458 
2459  if (tle->expr && IsA(tle->expr, Var))
2460  {
2461  Var *var = (Var *) tle->expr;
2462 
2463  if (var->varno != ignore_rel)
2464  {
2465  vinfo->varno = var->varno;
2466  vinfo->varattno = var->varattno;
2467  vinfo->resno = tle->resno;
2468  vinfo++;
2469  }
2470  }
2471  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2472  itlist->has_ph_vars = true;
2473  }
2474 
2475  itlist->num_vars = (vinfo - itlist->vars);
2476 
2477  return itlist;
2478 }
int varno
Definition: primnodes.h:189
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:191
Definition: primnodes.h:186
int varno
Definition: setrefs.c:34
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:1456
bool has_non_vars
Definition: setrefs.c:44
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
static int list_length(const List *l)
Definition: pg_list.h:149
void * palloc(Size size)
Definition: mcxt.c:1062
Definition: regcomp.c:237
#define offsetof(type, field)
Definition: c.h:727
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 1295 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().

1296 {
1297  /* We have to be sure we don't lose any initplans */
1298  child->initPlan = list_concat(parent->initPlan,
1299  child->initPlan);
1300 
1301  /*
1302  * We also have to transfer the parent's column labeling info into the
1303  * child, else columns sent to client will be improperly labeled if this
1304  * is the topmost plan level. resjunk and so on may be important too.
1305  */
1306  apply_tlist_labeling(child->targetlist, parent->targetlist);
1307 
1308  return child;
1309 }
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:307
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
List * targetlist
Definition: plannodes.h:141
List * initPlan
Definition: plannodes.h:145

◆ convert_combining_aggrefs()

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

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

2253 {
2254  if (node == NULL)
2255  return NULL;
2256  if (IsA(node, Aggref))
2257  {
2258  Aggref *orig_agg = (Aggref *) node;
2259  Aggref *child_agg;
2260  Aggref *parent_agg;
2261 
2262  /* Assert we've not chosen to partial-ize any unsupported cases */
2263  Assert(orig_agg->aggorder == NIL);
2264  Assert(orig_agg->aggdistinct == NIL);
2265 
2266  /*
2267  * Since aggregate calls can't be nested, we needn't recurse into the
2268  * arguments. But for safety, flat-copy the Aggref node itself rather
2269  * than modifying it in-place.
2270  */
2271  child_agg = makeNode(Aggref);
2272  memcpy(child_agg, orig_agg, sizeof(Aggref));
2273 
2274  /*
2275  * For the parent Aggref, we want to copy all the fields of the
2276  * original aggregate *except* the args list, which we'll replace
2277  * below, and the aggfilter expression, which should be applied only
2278  * by the child not the parent. Rather than explicitly knowing about
2279  * all the other fields here, we can momentarily modify child_agg to
2280  * provide a suitable source for copyObject.
2281  */
2282  child_agg->args = NIL;
2283  child_agg->aggfilter = NULL;
2284  parent_agg = copyObject(child_agg);
2285  child_agg->args = orig_agg->args;
2286  child_agg->aggfilter = orig_agg->aggfilter;
2287 
2288  /*
2289  * Now, set up child_agg to represent the first phase of partial
2290  * aggregation. For now, assume serialization is required.
2291  */
2293 
2294  /*
2295  * And set up parent_agg to represent the second phase.
2296  */
2297  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
2298  1, NULL, false));
2300 
2301  return (Node *) parent_agg;
2302  }
2304  (void *) context);
2305 }
List * aggdistinct
Definition: primnodes.h:332
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2598
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:5048
Definition: nodes.h:536
List * args
Definition: primnodes.h:330
#define list_make1(x1)
Definition: pg_list.h:206
List * aggorder
Definition: primnodes.h:331
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:2252
#define makeNode(_type_)
Definition: nodes.h:584
#define Assert(condition)
Definition: c.h:804
Expr * aggfilter
Definition: primnodes.h:333
#define copyObject(obj)
Definition: nodes.h:652

◆ copyVar()

static Var* copyVar ( Var var)
inlinestatic

Definition at line 1650 of file setrefs.c.

References palloc().

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

1651 {
1652  Var *newvar = (Var *) palloc(sizeof(Var));
1653 
1654  *newvar = *var;
1655  return newvar;
1656 }
Definition: primnodes.h:186
void * palloc(Size size)
Definition: mcxt.c:1062

◆ extract_query_dependencies()

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

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

3048 {
3049  PlannerGlobal glob;
3050  PlannerInfo root;
3051 
3052  /* Make up dummy planner state so we can use this module's machinery */
3053  MemSet(&glob, 0, sizeof(glob));
3054  glob.type = T_PlannerGlobal;
3055  glob.relationOids = NIL;
3056  glob.invalItems = NIL;
3057  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
3058  glob.dependsOnRole = false;
3059 
3060  MemSet(&root, 0, sizeof(root));
3061  root.type = T_PlannerInfo;
3062  root.glob = &glob;
3063 
3064  (void) extract_query_dependencies_walker(query, &root);
3065 
3066  *relationOids = glob.relationOids;
3067  *invalItems = glob.invalItems;
3068  *hasRowSecurity = glob.dependsOnRole;
3069 }
#define NIL
Definition: pg_list.h:65
#define MemSet(start, val, len)
Definition: c.h:1008
bool dependsOnRole
Definition: pathnodes.h:124
PlannerGlobal * glob
Definition: pathnodes.h:164
List * invalItems
Definition: pathnodes.h:112
NodeTag type
Definition: pathnodes.h:160
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3080
NodeTag type
Definition: pathnodes.h:92
List * relationOids
Definition: pathnodes.h:110

◆ extract_query_dependencies_walker()

bool extract_query_dependencies_walker ( Node node,
PlannerInfo context 
)

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

3081 {
3082  if (node == NULL)
3083  return false;
3084  Assert(!IsA(node, PlaceHolderVar));
3085  if (IsA(node, Query))
3086  {
3087  Query *query = (Query *) node;
3088  ListCell *lc;
3089 
3090  if (query->commandType == CMD_UTILITY)
3091  {
3092  /*
3093  * Ignore utility statements, except those (such as EXPLAIN) that
3094  * contain a parsed-but-not-planned query.
3095  */
3096  query = UtilityContainsQuery(query->utilityStmt);
3097  if (query == NULL)
3098  return false;
3099  }
3100 
3101  /* Remember if any Query has RLS quals applied by rewriter */
3102  if (query->hasRowSecurity)
3103  context->glob->dependsOnRole = true;
3104 
3105  /* Collect relation OIDs in this Query's rtable */
3106  foreach(lc, query->rtable)
3107  {
3108  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
3109 
3110  if (rte->rtekind == RTE_RELATION)
3111  context->glob->relationOids =
3112  lappend_oid(context->glob->relationOids, rte->relid);
3113  else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
3114  OidIsValid(rte->relid))
3115  context->glob->relationOids =
3116  lappend_oid(context->glob->relationOids,
3117  rte->relid);
3118  }
3119 
3120  /* And recurse into the query's subexpressions */
3122  (void *) context, 0);
3123  }
3124  /* Extract function dependencies and check for regclass Consts */
3125  fix_expr_common(context, node);
3127  (void *) context);
3128 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2355
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Node * utilityStmt
Definition: parsenodes.h:128
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2154
bool dependsOnRole
Definition: pathnodes.h:124
List * rtable
Definition: parsenodes.h:147
PlannerGlobal * glob
Definition: pathnodes.h:164
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:3080
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1672
CmdType commandType
Definition: parsenodes.h:120
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1904
List * relationOids
Definition: pathnodes.h:110
RTEKind rtekind
Definition: parsenodes.h:1007
bool hasRowSecurity
Definition: parsenodes.h:141

◆ fix_alternative_subplan()

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

Definition at line 1798 of file setrefs.c.

References Assert, PlannerInfo::isAltSubplan, PlannerInfo::isUsedSubplan, lfirst, NIL, SubPlan::per_call_cost, SubPlan::plan_id, SubPlan::startup_cost, and AlternativeSubPlan::subplans.

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

1800 {
1801  SubPlan *bestplan = NULL;
1802  Cost bestcost = 0;
1803  ListCell *lc;
1804 
1805  /*
1806  * Compute the estimated cost of each subplan assuming num_exec
1807  * executions, and keep the cheapest one. In event of exact equality of
1808  * estimates, we prefer the later plan; this is a bit arbitrary, but in
1809  * current usage it biases us to break ties against fast-start subplans.
1810  */
1811  Assert(asplan->subplans != NIL);
1812 
1813  foreach(lc, asplan->subplans)
1814  {
1815  SubPlan *curplan = (SubPlan *) lfirst(lc);
1816  Cost curcost;
1817 
1818  curcost = curplan->startup_cost + num_exec * curplan->per_call_cost;
1819  if (bestplan == NULL || curcost <= bestcost)
1820  {
1821  bestplan = curplan;
1822  bestcost = curcost;
1823  }
1824 
1825  /* Also mark all subplans that are in AlternativeSubPlans */
1826  root->isAltSubplan[curplan->plan_id - 1] = true;
1827  }
1828 
1829  /* Mark the subplan we selected */
1830  root->isUsedSubplan[bestplan->plan_id - 1] = true;
1831 
1832  return (Node *) bestplan;
1833 }
#define NIL
Definition: pg_list.h:65
int plan_id
Definition: primnodes.h:752
bool * isUsedSubplan
Definition: pathnodes.h:373
Definition: nodes.h:536
Cost per_call_cost
Definition: primnodes.h:776
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
bool * isAltSubplan
Definition: pathnodes.h:372
Cost startup_cost
Definition: primnodes.h:775
double Cost
Definition: nodes.h:670

◆ fix_expr_common()

static void fix_expr_common ( PlannerInfo root,
Node node 
)
static

Definition at line 1672 of file setrefs.c.

References Assert, GroupingFunc::cols, Const::constvalue, DatumGetObjectId, equal(), PlannerInfo::glob, PlannerInfo::grouping_map, ScalarArrayOpExpr::hashfuncid, IsA, ISREGCLASSCONST, lappend_int(), lappend_oid(), lfirst_int, ScalarArrayOpExpr::negfuncid, NIL, OidIsValid, ScalarArrayOpExpr::opfuncid, 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().

1673 {
1674  /* We assume callers won't call us on a NULL pointer */
1675  if (IsA(node, Aggref))
1676  {
1678  ((Aggref *) node)->aggfnoid);
1679  }
1680  else if (IsA(node, WindowFunc))
1681  {
1683  ((WindowFunc *) node)->winfnoid);
1684  }
1685  else if (IsA(node, FuncExpr))
1686  {
1688  ((FuncExpr *) node)->funcid);
1689  }
1690  else if (IsA(node, OpExpr))
1691  {
1692  set_opfuncid((OpExpr *) node);
1694  ((OpExpr *) node)->opfuncid);
1695  }
1696  else if (IsA(node, DistinctExpr))
1697  {
1698  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1700  ((DistinctExpr *) node)->opfuncid);
1701  }
1702  else if (IsA(node, NullIfExpr))
1703  {
1704  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1706  ((NullIfExpr *) node)->opfuncid);
1707  }
1708  else if (IsA(node, ScalarArrayOpExpr))
1709  {
1710  ScalarArrayOpExpr *saop = (ScalarArrayOpExpr *) node;
1711 
1712  set_sa_opfuncid(saop);
1714 
1715  if (!OidIsValid(saop->hashfuncid))
1717 
1718  if (!OidIsValid(saop->negfuncid))
1720  }
1721  else if (IsA(node, Const))
1722  {
1723  Const *con = (Const *) node;
1724 
1725  /* Check for regclass reference */
1726  if (ISREGCLASSCONST(con))
1727  root->glob->relationOids =
1728  lappend_oid(root->glob->relationOids,
1730  }
1731  else if (IsA(node, GroupingFunc))
1732  {
1733  GroupingFunc *g = (GroupingFunc *) node;
1734  AttrNumber *grouping_map = root->grouping_map;
1735 
1736  /* If there are no grouping sets, we don't need this. */
1737 
1738  Assert(grouping_map || g->cols == NIL);
1739 
1740  if (grouping_map)
1741  {
1742  ListCell *lc;
1743  List *cols = NIL;
1744 
1745  foreach(lc, g->refs)
1746  {
1747  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1748  }
1749 
1750  Assert(!g->cols || equal(cols, g->cols));
1751 
1752  if (!g->cols)
1753  g->cols = cols;
1754  }
1755  }
1756 }
Datum constvalue
Definition: primnodes.h:219
#define NIL
Definition: pg_list.h:65
#define ISREGCLASSCONST(con)
Definition: setrefs.c:100
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
List * refs
Definition: primnodes.h:374
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
#define DatumGetObjectId(X)
Definition: postgres.h:544
AttrNumber * grouping_map
Definition: pathnodes.h:332
List * lappend_oid(List *list, Oid datum)
Definition: list.c:372
#define OidIsValid(objectId)
Definition: c.h:710
#define lfirst_int(lc)
Definition: pg_list.h:170
PlannerGlobal * glob
Definition: pathnodes.h:164
List * lappend_int(List *list, int datum)
Definition: list.c:354
List * cols
Definition: primnodes.h:375
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2963
#define Assert(condition)
Definition: c.h:804
List * relationOids
Definition: pathnodes.h:110
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1683
Definition: pg_list.h:50
int16 AttrNumber
Definition: attnum.h:21
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1694

◆ 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 2634 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().

2641 {
2642  fix_join_expr_context context;
2643 
2644  context.root = root;
2645  context.outer_itlist = outer_itlist;
2646  context.inner_itlist = inner_itlist;
2647  context.acceptable_rel = acceptable_rel;
2648  context.rtoffset = rtoffset;
2649  context.num_exec = num_exec;
2650  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2651 }
indexed_tlist * inner_itlist
Definition: setrefs.c:59
Definition: nodes.h:536
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2654
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 2654 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().

2655 {
2656  Var *newvar;
2657 
2658  if (node == NULL)
2659  return NULL;
2660  if (IsA(node, Var))
2661  {
2662  Var *var = (Var *) node;
2663 
2664  /* Look for the var in the input tlists, first in the outer */
2665  if (context->outer_itlist)
2666  {
2667  newvar = search_indexed_tlist_for_var(var,
2668  context->outer_itlist,
2669  OUTER_VAR,
2670  context->rtoffset);
2671  if (newvar)
2672  return (Node *) newvar;
2673  }
2674 
2675  /* then in the inner. */
2676  if (context->inner_itlist)
2677  {
2678  newvar = search_indexed_tlist_for_var(var,
2679  context->inner_itlist,
2680  INNER_VAR,
2681  context->rtoffset);
2682  if (newvar)
2683  return (Node *) newvar;
2684  }
2685 
2686  /* If it's for acceptable_rel, adjust and return it */
2687  if (var->varno == context->acceptable_rel)
2688  {
2689  var = copyVar(var);
2690  var->varno += context->rtoffset;
2691  if (var->varnosyn > 0)
2692  var->varnosyn += context->rtoffset;
2693  return (Node *) var;
2694  }
2695 
2696  /* No referent found for Var */
2697  elog(ERROR, "variable not found in subplan target lists");
2698  }
2699  if (IsA(node, PlaceHolderVar))
2700  {
2701  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2702 
2703  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2704  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2705  {
2706  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2707  context->outer_itlist,
2708  OUTER_VAR);
2709  if (newvar)
2710  return (Node *) newvar;
2711  }
2712  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2713  {
2714  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2715  context->inner_itlist,
2716  INNER_VAR);
2717  if (newvar)
2718  return (Node *) newvar;
2719  }
2720 
2721  /* If not supplied by input plans, evaluate the contained expr */
2722  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2723  }
2724  /* Try matching more complex expressions too, if tlists have any */
2725  if (context->outer_itlist && context->outer_itlist->has_non_vars)
2726  {
2727  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2728  context->outer_itlist,
2729  OUTER_VAR);
2730  if (newvar)
2731  return (Node *) newvar;
2732  }
2733  if (context->inner_itlist && context->inner_itlist->has_non_vars)
2734  {
2735  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2736  context->inner_itlist,
2737  INNER_VAR);
2738  if (newvar)
2739  return (Node *) newvar;
2740  }
2741  /* Special cases (apply only AFTER failing to match to lower tlist) */
2742  if (IsA(node, Param))
2743  return fix_param_node(context->root, (Param *) node);
2744  if (IsA(node, AlternativeSubPlan))
2746  (AlternativeSubPlan *) node,
2747  context->num_exec),
2748  context);
2749  fix_expr_common(context->root, node);
2750  return expression_tree_mutator(node,
2752  (void *) context);
2753 }
int varno
Definition: primnodes.h:189
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1798
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
indexed_tlist * inner_itlist
Definition: setrefs.c:59
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2598
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1767
Definition: nodes.h:536
Definition: primnodes.h:186
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2654
bool has_ph_vars
Definition: setrefs.c:43
#define ERROR
Definition: elog.h:46
static Var * copyVar(Var *var)
Definition: setrefs.c:1650
PlannerInfo * root
Definition: setrefs.c:57
Index varnosyn
Definition: primnodes.h:199
bool has_non_vars
Definition: setrefs.c:44
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1672
#define INNER_VAR
Definition: primnodes.h:175
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, int newvarno)
Definition: setrefs.c:2529
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, int newvarno, int rtoffset)
Definition: setrefs.c:2489
#define elog(elevel,...)
Definition: elog.h:232
indexed_tlist * outer_itlist
Definition: setrefs.c:58
#define OUTER_VAR
Definition: primnodes.h:176

◆ fix_param_node()

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

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

1768 {
1769  if (p->paramkind == PARAM_MULTIEXPR)
1770  {
1771  int subqueryid = p->paramid >> 16;
1772  int colno = p->paramid & 0xFFFF;
1773  List *params;
1774 
1775  if (subqueryid <= 0 ||
1776  subqueryid > list_length(root->multiexpr_params))
1777  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1778  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1779  if (colno <= 0 || colno > list_length(params))
1780  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1781  return copyObject(list_nth(params, colno - 1));
1782  }
1783  return (Node *) copyObject(p);
1784 }
ParamKind paramkind
Definition: primnodes.h:267
Definition: nodes.h:536
List * multiexpr_params
Definition: pathnodes.h:246
#define ERROR
Definition: elog.h:46
static void * list_nth(const List *list, int n)
Definition: pg_list.h:278
int paramid
Definition: primnodes.h:268
static int list_length(const List *l)
Definition: pg_list.h:149
#define elog(elevel,...)
Definition: elog.h:232
#define copyObject(obj)
Definition: nodes.h:652
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 1854 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().

1855 {
1856  fix_scan_expr_context context;
1857 
1858  context.root = root;
1859  context.rtoffset = rtoffset;
1860  context.num_exec = num_exec;
1861 
1862  if (rtoffset != 0 ||
1863  root->multiexpr_params != NIL ||
1864  root->glob->lastPHId != 0 ||
1865  root->minmax_aggs != NIL ||
1866  root->hasAlternativeSubPlans)
1867  {
1868  return fix_scan_expr_mutator(node, &context);
1869  }
1870  else
1871  {
1872  /*
1873  * If rtoffset == 0, we don't need to change any Vars, and if there
1874  * are no MULTIEXPR subqueries then we don't need to replace
1875  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1876  * we won't need to remove them, and if there are no minmax Aggrefs we
1877  * won't need to replace them, and if there are no AlternativeSubPlans
1878  * we won't need to remove them. Then it's OK to just scribble on the
1879  * input node tree instead of copying (since the only change, filling
1880  * in any unset opfuncid fields, is harmless). This saves just enough
1881  * cycles to be noticeable on trivial queries.
1882  */
1883  (void) fix_scan_expr_walker(node, &context);
1884  return node;
1885  }
1886 }
#define NIL
Definition: pg_list.h:65
PlannerInfo * root
Definition: setrefs.c:50
List * minmax_aggs
Definition: pathnodes.h:333
List * multiexpr_params
Definition: pathnodes.h:246
bool hasAlternativeSubPlans
Definition: pathnodes.h:351
PlannerGlobal * glob
Definition: pathnodes.h:164
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1962
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1889
Index lastPHId
Definition: pathnodes.h:116

◆ fix_scan_expr_mutator()

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

Definition at line 1889 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, ROWID_VAR, fix_scan_expr_context::rtoffset, MinMaxAggInfo::target, Var::varlevelsup, Var::varno, and Var::varnosyn.

Referenced by fix_scan_expr().

1890 {
1891  if (node == NULL)
1892  return NULL;
1893  if (IsA(node, Var))
1894  {
1895  Var *var = copyVar((Var *) node);
1896 
1897  Assert(var->varlevelsup == 0);
1898 
1899  /*
1900  * We should not see Vars marked INNER_VAR, OUTER_VAR, or ROWID_VAR.
1901  * But an indexqual expression could contain INDEX_VAR Vars.
1902  */
1903  Assert(var->varno != INNER_VAR);
1904  Assert(var->varno != OUTER_VAR);
1905  Assert(var->varno != ROWID_VAR);
1906  if (!IS_SPECIAL_VARNO(var->varno))
1907  var->varno += context->rtoffset;
1908  if (var->varnosyn > 0)
1909  var->varnosyn += context->rtoffset;
1910  return (Node *) var;
1911  }
1912  if (IsA(node, Param))
1913  return fix_param_node(context->root, (Param *) node);
1914  if (IsA(node, Aggref))
1915  {
1916  Aggref *aggref = (Aggref *) node;
1917 
1918  /* See if the Aggref should be replaced by a Param */
1919  if (context->root->minmax_aggs != NIL &&
1920  list_length(aggref->args) == 1)
1921  {
1922  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1923  ListCell *lc;
1924 
1925  foreach(lc, context->root->minmax_aggs)
1926  {
1927  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1928 
1929  if (mminfo->aggfnoid == aggref->aggfnoid &&
1930  equal(mminfo->target, curTarget->expr))
1931  return (Node *) copyObject(mminfo->param);
1932  }
1933  }
1934  /* If no match, just fall through to process it normally */
1935  }
1936  if (IsA(node, CurrentOfExpr))
1937  {
1938  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1939 
1940  Assert(!IS_SPECIAL_VARNO(cexpr->cvarno));
1941  cexpr->cvarno += context->rtoffset;
1942  return (Node *) cexpr;
1943  }
1944  if (IsA(node, PlaceHolderVar))
1945  {
1946  /* At scan level, we should always just evaluate the contained expr */
1947  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1948 
1949  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1950  }
1951  if (IsA(node, AlternativeSubPlan))
1953  (AlternativeSubPlan *) node,
1954  context->num_exec),
1955  context);
1956  fix_expr_common(context->root, node);
1958  (void *) context);
1959 }
int varno
Definition: primnodes.h:189
#define NIL
Definition: pg_list.h:65
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1798
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Index varlevelsup
Definition: primnodes.h:196
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2598
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1767
#define ROWID_VAR
Definition: primnodes.h:178
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
Param * param
Definition: pathnodes.h:2434
PlannerInfo * root
Definition: setrefs.c:50
Definition: nodes.h:536
List * args
Definition: primnodes.h:330
List * minmax_aggs
Definition: pathnodes.h:333
Definition: primnodes.h:186
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:180
#define linitial(l)
Definition: pg_list.h:174
static Var * copyVar(Var *var)
Definition: setrefs.c:1650
Index varnosyn
Definition: primnodes.h:199
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1889
Oid aggfnoid
Definition: primnodes.h:323
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1672
#define INNER_VAR
Definition: primnodes.h:175
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Expr * target
Definition: pathnodes.h:2430
Expr * expr
Definition: primnodes.h:1455
static int list_length(const List *l)
Definition: pg_list.h:149
#define copyObject(obj)
Definition: nodes.h:652
#define OUTER_VAR
Definition: primnodes.h:176

◆ fix_scan_expr_walker()

static bool fix_scan_expr_walker ( Node node,
fix_scan_expr_context context 
)
static

Definition at line 1962 of file setrefs.c.

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

Referenced by fix_scan_expr().

1963 {
1964  if (node == NULL)
1965  return false;
1966  Assert(!(IsA(node, Var) && ((Var *) node)->varno == ROWID_VAR));
1967  Assert(!IsA(node, PlaceHolderVar));
1968  Assert(!IsA(node, AlternativeSubPlan));
1969  fix_expr_common(context->root, node);
1971  (void *) context);
1972 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
#define ROWID_VAR
Definition: primnodes.h:178
PlannerInfo * root
Definition: setrefs.c:50
Definition: primnodes.h:186
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1962
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1672
#define Assert(condition)
Definition: c.h:804
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1904

◆ fix_upper_expr()

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

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

2793 {
2794  fix_upper_expr_context context;
2795 
2796  context.root = root;
2797  context.subplan_itlist = subplan_itlist;
2798  context.newvarno = newvarno;
2799  context.rtoffset = rtoffset;
2800  context.num_exec = num_exec;
2801  return fix_upper_expr_mutator(node, &context);
2802 }
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2805
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 2805 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().

2806 {
2807  Var *newvar;
2808 
2809  if (node == NULL)
2810  return NULL;
2811  if (IsA(node, Var))
2812  {
2813  Var *var = (Var *) node;
2814 
2815  newvar = search_indexed_tlist_for_var(var,
2816  context->subplan_itlist,
2817  context->newvarno,
2818  context->rtoffset);
2819  if (!newvar)
2820  elog(ERROR, "variable not found in subplan target list");
2821  return (Node *) newvar;
2822  }
2823  if (IsA(node, PlaceHolderVar))
2824  {
2825  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2826 
2827  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2828  if (context->subplan_itlist->has_ph_vars)
2829  {
2830  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2831  context->subplan_itlist,
2832  context->newvarno);
2833  if (newvar)
2834  return (Node *) newvar;
2835  }
2836  /* If not supplied by input plan, evaluate the contained expr */
2837  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2838  }
2839  /* Try matching more complex expressions too, if tlist has any */
2840  if (context->subplan_itlist->has_non_vars)
2841  {
2842  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2843  context->subplan_itlist,
2844  context->newvarno);
2845  if (newvar)
2846  return (Node *) newvar;
2847  }
2848  /* Special cases (apply only AFTER failing to match to lower tlist) */
2849  if (IsA(node, Param))
2850  return fix_param_node(context->root, (Param *) node);
2851  if (IsA(node, Aggref))
2852  {
2853  Aggref *aggref = (Aggref *) node;
2854 
2855  /* See if the Aggref should be replaced by a Param */
2856  if (context->root->minmax_aggs != NIL &&
2857  list_length(aggref->args) == 1)
2858  {
2859  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2860  ListCell *lc;
2861 
2862  foreach(lc, context->root->minmax_aggs)
2863  {
2864  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2865 
2866  if (mminfo->aggfnoid == aggref->aggfnoid &&
2867  equal(mminfo->target, curTarget->expr))
2868  return (Node *) copyObject(mminfo->param);
2869  }
2870  }
2871  /* If no match, just fall through to process it normally */
2872  }
2873  if (IsA(node, AlternativeSubPlan))
2875  (AlternativeSubPlan *) node,
2876  context->num_exec),
2877  context);
2878  fix_expr_common(context->root, node);
2879  return expression_tree_mutator(node,
2881  (void *) context);
2882 }
#define NIL
Definition: pg_list.h:65
static Node * fix_alternative_subplan(PlannerInfo *root, AlternativeSubPlan *asplan, double num_exec)
Definition: setrefs.c:1798
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2598
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1767
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
Param * param
Definition: pathnodes.h:2434
Definition: nodes.h:536
List * args
Definition: primnodes.h:330
List * minmax_aggs
Definition: pathnodes.h:333
Definition: primnodes.h:186
bool has_ph_vars
Definition: setrefs.c:43
#define linitial(l)
Definition: pg_list.h:174
#define ERROR
Definition: elog.h:46
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2805
bool has_non_vars
Definition: setrefs.c:44
Oid aggfnoid
Definition: primnodes.h:323
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1672
#define lfirst(lc)
Definition: pg_list.h:169
Expr * target
Definition: pathnodes.h:2430
Expr * expr
Definition: primnodes.h:1455
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, int newvarno)
Definition: setrefs.c:2529
static int list_length(const List *l)
Definition: pg_list.h:149
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, int newvarno, int rtoffset)
Definition: setrefs.c:2489
#define elog(elevel,...)
Definition: elog.h:232
PlannerInfo * root
Definition: setrefs.c:67
#define copyObject(obj)
Definition: nodes.h:652
indexed_tlist * subplan_itlist
Definition: setrefs.c:68

◆ flatten_rtes_walker()

static bool flatten_rtes_walker ( Node node,
PlannerGlobal glob 
)
static

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

448 {
449  if (node == NULL)
450  return false;
451  if (IsA(node, RangeTblEntry))
452  {
453  RangeTblEntry *rte = (RangeTblEntry *) node;
454 
455  /* As above, we need only save relation RTEs */
456  if (rte->rtekind == RTE_RELATION)
457  add_rte_to_flat_rtable(glob, rte);
458  return false;
459  }
460  if (IsA(node, Query))
461  {
462  /* Recurse into subselects */
463  return query_tree_walker((Query *) node,
465  (void *) glob,
467  }
469  (void *) glob);
470 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2355
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
#define QTW_EXAMINE_RTES_BEFORE
Definition: nodeFuncs.h:25
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:483
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:447
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1904
RTEKind rtekind
Definition: parsenodes.h:1007

◆ flatten_unplanned_rtes()

static void flatten_unplanned_rtes ( PlannerGlobal glob,
RangeTblEntry rte 
)
static

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

438 {
439  /* Use query_tree_walker to find all RTEs in the parse tree */
440  (void) query_tree_walker(rte->subquery,
442  (void *) glob,
444 }
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2355
#define QTW_EXAMINE_RTES_BEFORE
Definition: nodeFuncs.h:25
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:447
Query * subquery
Definition: parsenodes.h:1042

◆ offset_relid_set()

static Relids offset_relid_set ( Relids  relids,
int  rtoffset 
)
static

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

1629 {
1630  Relids result = NULL;
1631  int rtindex;
1632 
1633  /* If there's no offset to apply, we needn't recompute the value */
1634  if (rtoffset == 0)
1635  return relids;
1636  rtindex = -1;
1637  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
1638  result = bms_add_member(result, rtindex + rtoffset);
1639  return result;
1640 }
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 2963 of file setrefs.c.

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

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

2964 {
2965  /*
2966  * For performance reasons, we don't bother to track built-in functions;
2967  * we just assume they'll never change (or at least not in ways that'd
2968  * invalidate plans using them). For this purpose we can consider a
2969  * built-in function to be one with OID less than FirstUnpinnedObjectId.
2970  * Note that the OID generator guarantees never to generate such an OID
2971  * after startup, even at OID wraparound.
2972  */
2973  if (funcid >= (Oid) FirstUnpinnedObjectId)
2974  {
2975  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2976 
2977  /*
2978  * It would work to use any syscache on pg_proc, but the easiest is
2979  * PROCOID since we already have the function's OID at hand. Note
2980  * that plancache.c knows we use PROCOID.
2981  */
2982  inval_item->cacheId = PROCOID;
2983  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2984  ObjectIdGetDatum(funcid));
2985 
2986  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2987  }
2988 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:202
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define FirstUnpinnedObjectId
Definition: transam.h:196
PlannerGlobal * glob
Definition: pathnodes.h:164
List * lappend(List *list, void *datum)
Definition: list.c:336
List * invalItems
Definition: pathnodes.h:112
uint32 hashValue
Definition: plannodes.h:1291
#define makeNode(_type_)
Definition: nodes.h:584

◆ record_plan_type_dependency()

void record_plan_type_dependency ( PlannerInfo root,
Oid  typid 
)

Definition at line 3003 of file setrefs.c.

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

Referenced by eval_const_expressions_mutator().

3004 {
3005  /*
3006  * As in record_plan_function_dependency, ignore the possibility that
3007  * someone would change a built-in domain.
3008  */
3009  if (typid >= (Oid) FirstUnpinnedObjectId)
3010  {
3011  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
3012 
3013  /*
3014  * It would work to use any syscache on pg_type, but the easiest is
3015  * TYPEOID since we already have the type's OID at hand. Note that
3016  * plancache.c knows we use TYPEOID.
3017  */
3018  inval_item->cacheId = TYPEOID;
3019  inval_item->hashValue = GetSysCacheHashValue1(TYPEOID,
3020  ObjectIdGetDatum(typid));
3021 
3022  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
3023  }
3024 }
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:202
unsigned int Oid
Definition: postgres_ext.h:31
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define FirstUnpinnedObjectId
Definition: transam.h:196
PlannerGlobal * glob
Definition: pathnodes.h:164
List * lappend(List *list, void *datum)
Definition: list.c:336
List * invalItems
Definition: pathnodes.h:112
uint32 hashValue
Definition: plannodes.h:1291
#define makeNode(_type_)
Definition: nodes.h:584

◆ search_indexed_tlist_for_non_var()

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

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

2531 {
2532  TargetEntry *tle;
2533 
2534  /*
2535  * If it's a simple Const, replacing it with a Var is silly, even if there
2536  * happens to be an identical Const below; a Var is more expensive to
2537  * execute than a Const. What's more, replacing it could confuse some
2538  * places in the executor that expect to see simple Consts for, eg,
2539  * dropped columns.
2540  */
2541  if (IsA(node, Const))
2542  return NULL;
2543 
2544  tle = tlist_member(node, itlist->tlist);
2545  if (tle)
2546  {
2547  /* Found a matching subplan output expression */
2548  Var *newvar;
2549 
2550  newvar = makeVarFromTargetEntry(newvarno, tle);
2551  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2552  newvar->varattnosyn = 0;
2553  return newvar;
2554  }
2555  return NULL; /* no match */
2556 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Definition: primnodes.h:186
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Definition: makefuncs.c:103
Index varnosyn
Definition: primnodes.h:199
AttrNumber varattnosyn
Definition: primnodes.h:200
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:68
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,
int  newvarno 
)
static

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

2573 {
2574  ListCell *lc;
2575 
2576  foreach(lc, itlist->tlist)
2577  {
2578  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2579 
2580  /* The equal() check should be redundant, but let's be paranoid */
2581  if (tle->ressortgroupref == sortgroupref &&
2582  equal(node, tle->expr))
2583  {
2584  /* Found a matching subplan output expression */
2585  Var *newvar;
2586 
2587  newvar = makeVarFromTargetEntry(newvarno, tle);
2588  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2589  newvar->varattnosyn = 0;
2590  return newvar;
2591  }
2592  }
2593  return NULL; /* no match */
2594 }
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
Definition: primnodes.h:186
Var * makeVarFromTargetEntry(int varno, TargetEntry *tle)
Definition: makefuncs.c:103
Index varnosyn
Definition: primnodes.h:199
AttrNumber varattnosyn
Definition: primnodes.h:200
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
Index ressortgroupref
Definition: primnodes.h:1458
List * tlist
Definition: setrefs.c:41

◆ search_indexed_tlist_for_var()

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

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

2491 {
2492  int varno = var->varno;
2493  AttrNumber varattno = var->varattno;
2494  tlist_vinfo *vinfo;
2495  int i;
2496 
2497  vinfo = itlist->vars;
2498  i = itlist->num_vars;
2499  while (i-- > 0)
2500  {
2501  if (vinfo->varno == varno && vinfo->varattno == varattno)
2502  {
2503  /* Found a match */
2504  Var *newvar = copyVar(var);
2505 
2506  newvar->varno = newvarno;
2507  newvar->varattno = vinfo->resno;
2508  if (newvar->varnosyn > 0)
2509  newvar->varnosyn += rtoffset;
2510  return newvar;
2511  }
2512  vinfo++;
2513  }
2514  return NULL; /* no match */
2515 }
int varno
Definition: primnodes.h:189
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
AttrNumber resno
Definition: setrefs.c:36
AttrNumber varattno
Definition: primnodes.h:191
Definition: primnodes.h:186
int varno
Definition: setrefs.c:34
AttrNumber varattno
Definition: setrefs.c:35
int num_vars
Definition: setrefs.c:42
static Var * copyVar(Var *var)
Definition: setrefs.c:1650
Index varnosyn
Definition: primnodes.h:199
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 1471 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().

1474 {
1475  ListCell *l;
1476 
1477  /*
1478  * Append, like Sort et al, doesn't actually evaluate its targetlist or
1479  * check quals. If it's got exactly one child plan, then it's not doing
1480  * anything useful at all, and we can strip it out.
1481  */
1482  Assert(aplan->plan.qual == NIL);
1483 
1484  /* First, we gotta recurse on the children */
1485  foreach(l, aplan->appendplans)
1486  {
1487  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1488  }
1489 
1490  /* Now, if there's just one, forget the Append and return that child */
1491  if (list_length(aplan->appendplans) == 1)
1492  return clean_up_removed_plan_level((Plan *) aplan,
1493  (Plan *) linitial(aplan->appendplans));
1494 
1495  /*
1496  * Otherwise, clean up the Append as needed. It's okay to do this after
1497  * recursing to the children, because set_dummy_tlist_references doesn't
1498  * look at those.
1499  */
1500  set_dummy_tlist_references((Plan *) aplan, rtoffset);
1501 
1502  aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
1503 
1504  if (aplan->part_prune_info)
1505  {
1506  foreach(l, aplan->part_prune_info->prune_infos)
1507  {
1508  List *prune_infos = lfirst(l);
1509  ListCell *l2;
1510 
1511  foreach(l2, prune_infos)
1512  {
1513  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1514 
1515  pinfo->rtindex += rtoffset;
1516  }
1517  }
1518  }
1519 
1520  /* We don't need to recurse to lefttree or righttree ... */
1521  Assert(aplan->plan.lefttree == NULL);
1522  Assert(aplan->plan.righttree == NULL);
1523 
1524  return (Plan *) aplan;
1525 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1628
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:527
List * appendplans
Definition: plannodes.h:253
struct Plan * righttree
Definition: plannodes.h:144
#define linitial(l)
Definition: pg_list.h:174
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1295
#define Assert(condition)
Definition: c.h:804
#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:143
Definition: pg_list.h:50
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2321
Plan plan
Definition: plannodes.h:251

◆ set_customscan_references()

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

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

1401 {
1402  ListCell *lc;
1403 
1404  /* Adjust scanrelid if it's valid */
1405  if (cscan->scan.scanrelid > 0)
1406  cscan->scan.scanrelid += rtoffset;
1407 
1408  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1409  {
1410  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1412 
1413  cscan->scan.plan.targetlist = (List *)
1414  fix_upper_expr(root,
1415  (Node *) cscan->scan.plan.targetlist,
1416  itlist,
1417  INDEX_VAR,
1418  rtoffset,
1419  NUM_EXEC_TLIST((Plan *) cscan));
1420  cscan->scan.plan.qual = (List *)
1421  fix_upper_expr(root,
1422  (Node *) cscan->scan.plan.qual,
1423  itlist,
1424  INDEX_VAR,
1425  rtoffset,
1426  NUM_EXEC_QUAL((Plan *) cscan));
1427  cscan->custom_exprs = (List *)
1428  fix_upper_expr(root,
1429  (Node *) cscan->custom_exprs,
1430  itlist,
1431  INDEX_VAR,
1432  rtoffset,
1433  NUM_EXEC_QUAL((Plan *) cscan));
1434  pfree(itlist);
1435  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1436  cscan->custom_scan_tlist =
1437  fix_scan_list(root, cscan->custom_scan_tlist,
1438  rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
1439  }
1440  else
1441  {
1442  /* Adjust tlist, qual, custom_exprs in the standard way */
1443  cscan->scan.plan.targetlist =
1444  fix_scan_list(root, cscan->scan.plan.targetlist,
1445  rtoffset, NUM_EXEC_TLIST((Plan *) cscan));
1446  cscan->scan.plan.qual =
1447  fix_scan_list(root, cscan->scan.plan.qual,
1448  rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
1449  cscan->custom_exprs =
1450  fix_scan_list(root, cscan->custom_exprs,
1451  rtoffset, NUM_EXEC_QUAL((Plan *) cscan));
1452  }
1453 
1454  /* Adjust child plan-nodes recursively, if needed */
1455  foreach(lc, cscan->custom_plans)
1456  {
1457  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1458  }
1459 
1460  cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
1461 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:343
Index scanrelid
Definition: plannodes.h:344
Definition: nodes.h:536
List * custom_exprs
Definition: plannodes.h:669
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1628
List * custom_plans
Definition: plannodes.h:668
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:527
void pfree(void *pointer)
Definition: mcxt.c:1169
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
Scan scan
Definition: plannodes.h:665
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define lfirst(lc)
Definition: pg_list.h:169
List * custom_scan_tlist
Definition: plannodes.h:671
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
Bitmapset * custom_relids
Definition: plannodes.h:672
List * targetlist
Definition: plannodes.h:141
#define INDEX_VAR
Definition: primnodes.h:177
Definition: pg_list.h:50

◆ set_dummy_tlist_references()

static void set_dummy_tlist_references ( Plan plan,
int  rtoffset 
)
static

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

2322 {
2323  List *output_targetlist;
2324  ListCell *l;
2325 
2326  output_targetlist = NIL;
2327  foreach(l, plan->targetlist)
2328  {
2329  TargetEntry *tle = (TargetEntry *) lfirst(l);
2330  Var *oldvar = (Var *) tle->expr;
2331  Var *newvar;
2332 
2333  /*
2334  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
2335  * as Consts, not Vars referencing Consts. Here, there's no speed
2336  * advantage to be had, but it makes EXPLAIN output look cleaner, and
2337  * again it avoids confusing the executor.
2338  */
2339  if (IsA(oldvar, Const))
2340  {
2341  /* just reuse the existing TLE node */
2342  output_targetlist = lappend(output_targetlist, tle);
2343  continue;
2344  }
2345 
2346  newvar = makeVar(OUTER_VAR,
2347  tle->resno,
2348  exprType((Node *) oldvar),
2349  exprTypmod((Node *) oldvar),
2350  exprCollation((Node *) oldvar),
2351  0);
2352  if (IsA(oldvar, Var) &&
2353  oldvar->varnosyn > 0)
2354  {
2355  newvar->varnosyn = oldvar->varnosyn + rtoffset;
2356  newvar->varattnosyn = oldvar->varattnosyn;
2357  }
2358  else
2359  {
2360  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2361  newvar->varattnosyn = 0;
2362  }
2363 
2364  tle = flatCopyTargetEntry(tle);
2365  tle->expr = (Expr *) newvar;
2366  output_targetlist = lappend(output_targetlist, tle);
2367  }
2368  plan->targetlist = output_targetlist;
2369 
2370  /* We don't touch plan->qual here */
2371 }
#define NIL
Definition: pg_list.h:65
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:267
Var * makeVar(int varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
Definition: nodes.h:536
Definition: primnodes.h:186
AttrNumber resno
Definition: primnodes.h:1456
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
List * lappend(List *list, void *datum)
Definition: list.c:336
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:759
List * targetlist
Definition: plannodes.h:141
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:176

◆ set_foreignscan_references()

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

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

1319 {
1320  /* Adjust scanrelid if it's valid */
1321  if (fscan->scan.scanrelid > 0)
1322  fscan->scan.scanrelid += rtoffset;
1323 
1324  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1325  {
1326  /*
1327  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1328  * foreign scan tuple
1329  */
1331 
1332  fscan->scan.plan.targetlist = (List *)
1333  fix_upper_expr(root,
1334  (Node *) fscan->scan.plan.targetlist,
1335  itlist,
1336  INDEX_VAR,
1337  rtoffset,
1338  NUM_EXEC_TLIST((Plan *) fscan));
1339  fscan->scan.plan.qual = (List *)
1340  fix_upper_expr(root,
1341  (Node *) fscan->scan.plan.qual,
1342  itlist,
1343  INDEX_VAR,
1344  rtoffset,
1345  NUM_EXEC_QUAL((Plan *) fscan));
1346  fscan->fdw_exprs = (List *)
1347  fix_upper_expr(root,
1348  (Node *) fscan->fdw_exprs,
1349  itlist,
1350  INDEX_VAR,
1351  rtoffset,
1352  NUM_EXEC_QUAL((Plan *) fscan));
1353  fscan->fdw_recheck_quals = (List *)
1354  fix_upper_expr(root,
1355  (Node *) fscan->fdw_recheck_quals,
1356  itlist,
1357  INDEX_VAR,
1358  rtoffset,
1359  NUM_EXEC_QUAL((Plan *) fscan));
1360  pfree(itlist);
1361  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1362  fscan->fdw_scan_tlist =
1363  fix_scan_list(root, fscan->fdw_scan_tlist,
1364  rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
1365  }
1366  else
1367  {
1368  /*
1369  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1370  * way
1371  */
1372  fscan->scan.plan.targetlist =
1373  fix_scan_list(root, fscan->scan.plan.targetlist,
1374  rtoffset, NUM_EXEC_TLIST((Plan *) fscan));
1375  fscan->scan.plan.qual =
1376  fix_scan_list(root, fscan->scan.plan.qual,
1377  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1378  fscan->fdw_exprs =
1379  fix_scan_list(root, fscan->fdw_exprs,
1380  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1381  fscan->fdw_recheck_quals =
1382  fix_scan_list(root, fscan->fdw_recheck_quals,
1383  rtoffset, NUM_EXEC_QUAL((Plan *) fscan));
1384  }
1385 
1386  fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
1387 
1388  /* Adjust resultRelation if it's valid */
1389  if (fscan->resultRelation > 0)
1390  fscan->resultRelation += rtoffset;
1391 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:343
Index scanrelid
Definition: plannodes.h:344
List * fdw_exprs
Definition: plannodes.h:640
Definition: nodes.h:536
List * fdw_scan_tlist
Definition: plannodes.h:642
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1628
void pfree(void *pointer)
Definition: mcxt.c:1169
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
List * fdw_recheck_quals
Definition: plannodes.h:643
Index resultRelation
Definition: plannodes.h:638
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
List * targetlist
Definition: plannodes.h:141
#define INDEX_VAR
Definition: primnodes.h:177
Definition: pg_list.h:50
Bitmapset * fs_relids
Definition: plannodes.h:644

◆ set_hash_references()

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

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

1597 {
1598  Hash *hplan = (Hash *) plan;
1599  Plan *outer_plan = plan->lefttree;
1600  indexed_tlist *outer_itlist;
1601 
1602  /*
1603  * Hash's hashkeys are used when feeding tuples into the hashtable,
1604  * therefore have them reference Hash's outer plan (which itself is the
1605  * inner plan of the HashJoin).
1606  */
1607  outer_itlist = build_tlist_index(outer_plan->targetlist);
1608  hplan->hashkeys = (List *)
1609  fix_upper_expr(root,
1610  (Node *) hplan->hashkeys,
1611  outer_itlist,
1612  OUTER_VAR,
1613  rtoffset,
1614  NUM_EXEC_QUAL(plan));
1615 
1616  /* Hash doesn't project */
1617  set_dummy_tlist_references(plan, rtoffset);
1618 
1619  /* Hash nodes don't have their own quals */
1620  Assert(plan->qual == NIL);
1621 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
Definition: nodes.h:536
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
List * hashkeys
Definition: plannodes.h:974
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define Assert(condition)
Definition: c.h:804
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
struct Plan * lefttree
Definition: plannodes.h:143
List * targetlist
Definition: plannodes.h:141
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:176
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2321

◆ set_indexonlyscan_references()

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

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

1143 {
1144  indexed_tlist *index_itlist;
1145 
1146  index_itlist = build_tlist_index(plan->indextlist);
1147 
1148  plan->scan.scanrelid += rtoffset;
1149  plan->scan.plan.targetlist = (List *)
1150  fix_upper_expr(root,
1151  (Node *) plan->scan.plan.targetlist,
1152  index_itlist,
1153  INDEX_VAR,
1154  rtoffset,
1155  NUM_EXEC_TLIST((Plan *) plan));
1156  plan->scan.plan.qual = (List *)
1157  fix_upper_expr(root,
1158  (Node *) plan->scan.plan.qual,
1159  index_itlist,
1160  INDEX_VAR,
1161  rtoffset,
1162  NUM_EXEC_QUAL((Plan *) plan));
1163  /* indexqual is already transformed to reference index columns */
1164  plan->indexqual = fix_scan_list(root, plan->indexqual,
1165  rtoffset, 1);
1166  /* indexorderby is already transformed to reference index columns */
1167  plan->indexorderby = fix_scan_list(root, plan->indexorderby,
1168  rtoffset, 1);
1169  /* indextlist must NOT be transformed to reference index columns */
1170  plan->indextlist = fix_scan_list(root, plan->indextlist,
1171  rtoffset, NUM_EXEC_TLIST((Plan *) plan));
1172 
1173  pfree(index_itlist);
1174 
1175  return (Plan *) plan;
1176 }
List * qual
Definition: plannodes.h:142
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:343
Index scanrelid
Definition: plannodes.h:344
Definition: nodes.h:536
void pfree(void *pointer)
Definition: mcxt.c:1169
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
List * indextlist
Definition: plannodes.h:439
List * indexorderby
Definition: plannodes.h:438
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
List * indexqual
Definition: plannodes.h:437
List * targetlist
Definition: plannodes.h:141
#define INDEX_VAR
Definition: primnodes.h:177
Definition: pg_list.h:50

◆ set_join_references()

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

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

1984 {
1985  Plan *outer_plan = join->plan.lefttree;
1986  Plan *inner_plan = join->plan.righttree;
1987  indexed_tlist *outer_itlist;
1988  indexed_tlist *inner_itlist;
1989 
1990  outer_itlist = build_tlist_index(outer_plan->targetlist);
1991  inner_itlist = build_tlist_index(inner_plan->targetlist);
1992 
1993  /*
1994  * First process the joinquals (including merge or hash clauses). These
1995  * are logically below the join so they can always use all values
1996  * available from the input tlists. It's okay to also handle
1997  * NestLoopParams now, because those couldn't refer to nullable
1998  * subexpressions.
1999  */
2000  join->joinqual = fix_join_expr(root,
2001  join->joinqual,
2002  outer_itlist,
2003  inner_itlist,
2004  (Index) 0,
2005  rtoffset,
2006  NUM_EXEC_QUAL((Plan *) join));
2007 
2008  /* Now do join-type-specific stuff */
2009  if (IsA(join, NestLoop))
2010  {
2011  NestLoop *nl = (NestLoop *) join;
2012  ListCell *lc;
2013 
2014  foreach(lc, nl->nestParams)
2015  {
2016  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
2017 
2018  nlp->paramval = (Var *) fix_upper_expr(root,
2019  (Node *) nlp->paramval,
2020  outer_itlist,
2021  OUTER_VAR,
2022  rtoffset,
2023  NUM_EXEC_TLIST(outer_plan));
2024  /* Check we replaced any PlaceHolderVar with simple Var */
2025  if (!(IsA(nlp->paramval, Var) &&
2026  nlp->paramval->varno == OUTER_VAR))
2027  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
2028  }
2029  }
2030  else if (IsA(join, MergeJoin))
2031  {
2032  MergeJoin *mj = (MergeJoin *) join;
2033 
2034  mj->mergeclauses = fix_join_expr(root,
2035  mj->mergeclauses,
2036  outer_itlist,
2037  inner_itlist,
2038  (Index) 0,
2039  rtoffset,
2040  NUM_EXEC_QUAL((Plan *) join));
2041  }
2042  else if (IsA(join, HashJoin))
2043  {
2044  HashJoin *hj = (HashJoin *) join;
2045 
2046  hj->hashclauses = fix_join_expr(root,
2047  hj->hashclauses,
2048  outer_itlist,
2049  inner_itlist,
2050  (Index) 0,
2051  rtoffset,
2052  NUM_EXEC_QUAL((Plan *) join));
2053 
2054  /*
2055  * HashJoin's hashkeys are used to look for matching tuples from its
2056  * outer plan (not the Hash node!) in the hashtable.
2057  */
2058  hj->hashkeys = (List *) fix_upper_expr(root,
2059  (Node *) hj->hashkeys,
2060  outer_itlist,
2061  OUTER_VAR,
2062  rtoffset,
2063  NUM_EXEC_QUAL((Plan *) join));
2064  }
2065 
2066  /*
2067  * Now we need to fix up the targetlist and qpqual, which are logically
2068  * above the join. This means they should not re-use any input expression
2069  * that was computed in the nullable side of an outer join. Vars and
2070  * PlaceHolderVars are fine, so we can implement this restriction just by
2071  * clearing has_non_vars in the indexed_tlist structs.
2072  *
2073  * XXX This is a grotty workaround for the fact that we don't clearly
2074  * distinguish between a Var appearing below an outer join and the "same"
2075  * Var appearing above it. If we did, we'd not need to hack the matching
2076  * rules this way.
2077  */
2078  switch (join->jointype)
2079  {
2080  case JOIN_LEFT:
2081  case JOIN_SEMI:
2082  case JOIN_ANTI:
2083  inner_itlist->has_non_vars = false;
2084  break;
2085  case JOIN_RIGHT:
2086  outer_itlist->has_non_vars = false;
2087  break;
2088  case JOIN_FULL:
2089  outer_itlist->has_non_vars = false;
2090  inner_itlist->has_non_vars = false;
2091  break;
2092  default:
2093  break;
2094  }
2095 
2096  join->plan.targetlist = fix_join_expr(root,
2097  join->plan.targetlist,
2098  outer_itlist,
2099  inner_itlist,
2100  (Index) 0,
2101  rtoffset,
2102  NUM_EXEC_TLIST((Plan *) join));
2103  join->plan.qual = fix_join_expr(root,
2104  join->plan.qual,
2105  outer_itlist,
2106  inner_itlist,
2107  (Index) 0,
2108  rtoffset,
2109  NUM_EXEC_QUAL((Plan *) join));
2110 
2111  pfree(outer_itlist);
2112  pfree(inner_itlist);
2113 }
int varno
Definition: primnodes.h:189
List * qual
Definition: plannodes.h:142
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
List * nestParams
Definition: plannodes.h:726
List * hashkeys
Definition: plannodes.h:774
List * hashclauses
Definition: plannodes.h:766
Definition: nodes.h:536
Definition: primnodes.h:186
List * mergeclauses
Definition: plannodes.h:751
JoinType jointype
Definition: plannodes.h:707
struct Plan * righttree
Definition: plannodes.h:144
void pfree(void *pointer)
Definition: mcxt.c:1169
Var * paramval
Definition: plannodes.h:733
#define ERROR
Definition: elog.h:46
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
bool has_non_vars
Definition: setrefs.c:44
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
unsigned int Index
Definition: c.h:549
#define lfirst(lc)
Definition: pg_list.h:169
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
struct Plan * lefttree
Definition: plannodes.h:143
List * targetlist
Definition: plannodes.h:141
#define elog(elevel,...)
Definition: elog.h:232
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:176
List * joinqual
Definition: plannodes.h:709
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:2634
Plan plan
Definition: plannodes.h:706

◆ set_mergeappend_references()

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

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

1538 {
1539  ListCell *l;
1540 
1541  /*
1542  * MergeAppend, like Sort et al, doesn't actually evaluate its targetlist
1543  * or check quals. If it's got exactly one child plan, then it's not
1544  * doing anything useful at all, and we can strip it out.
1545  */
1546  Assert(mplan->plan.qual == NIL);
1547 
1548  /* First, we gotta recurse on the children */
1549  foreach(l, mplan->mergeplans)
1550  {
1551  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1552  }
1553 
1554  /* Now, if there's just one, forget the MergeAppend and return that child */
1555  if (list_length(mplan->mergeplans) == 1)
1556  return clean_up_removed_plan_level((Plan *) mplan,
1557  (Plan *) linitial(mplan->mergeplans));
1558 
1559  /*
1560  * Otherwise, clean up the MergeAppend as needed. It's okay to do this
1561  * after recursing to the children, because set_dummy_tlist_references
1562  * doesn't look at those.
1563  */
1564  set_dummy_tlist_references((Plan *) mplan, rtoffset);
1565 
1566  mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
1567 
1568  if (mplan->part_prune_info)
1569  {
1570  foreach(l, mplan->part_prune_info->prune_infos)
1571  {
1572  List *prune_infos = lfirst(l);
1573  ListCell *l2;
1574 
1575  foreach(l2, prune_infos)
1576  {
1577  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1578 
1579  pinfo->rtindex += rtoffset;
1580  }
1581  }
1582  }
1583 
1584  /* We don't need to recurse to lefttree or righttree ... */
1585  Assert(mplan->plan.lefttree == NULL);
1586  Assert(mplan->plan.righttree == NULL);
1587 
1588  return (Plan *) mplan;
1589 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1628
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:527
struct Plan * righttree
Definition: plannodes.h:144
#define linitial(l)
Definition: pg_list.h:174
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1295
#define Assert(condition)
Definition: c.h:804
#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:143
List * mergeplans
Definition: plannodes.h:275
Definition: pg_list.h:50
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2321

◆ set_param_references()

static void set_param_references ( PlannerInfo root,
Plan plan 
)
static

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

2198 {
2199  Assert(IsA(plan, Gather) || IsA(plan, GatherMerge));
2200 
2201  if (plan->lefttree->extParam)
2202  {
2203  PlannerInfo *proot;
2204  Bitmapset *initSetParam = NULL;
2205  ListCell *l;
2206 
2207  for (proot = root; proot != NULL; proot = proot->parent_root)
2208  {
2209  foreach(l, proot->init_plans)
2210  {
2211  SubPlan *initsubplan = (SubPlan *) lfirst(l);
2212  ListCell *l2;
2213 
2214  foreach(l2, initsubplan->setParam)
2215  {
2216  initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
2217  }
2218  }
2219  }
2220 
2221  /*
2222  * Remember the list of all external initplan params that are used by
2223  * the children of Gather or Gather merge node.
2224  */
2225  if (IsA(plan, Gather))
2226  ((Gather *) plan)->initParam =
2227  bms_intersect(plan->lefttree->extParam, initSetParam);
2228  else
2229  ((GatherMerge *) plan)->initParam =
2230  bms_intersect(plan->lefttree->extParam, initSetParam);
2231  }
2232 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
PlannerInfo * parent_root
Definition: pathnodes.h:168
#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:242
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
List * setParam
Definition: primnodes.h:770
Bitmapset * extParam
Definition: plannodes.h:159
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
struct Plan * lefttree
Definition: plannodes.h:143

◆ 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, foreach_current_index, PlannerInfo::glob, PlannerInfo::hasAlternativeSubPlans, PlannerInfo::isAltSubplan, PlannerInfo::isUsedSubplan, lappend(), lfirst, lfirst_node, list_length(), NIL, palloc(), palloc0(), AppendRelInfo::parent_relid, PlanRowMark::prti, PlannerInfo::rowMarks, PlanRowMark::rti, set_plan_refs(), PlannerGlobal::subplans, and AppendRelInfo::translated_vars.

Referenced by set_subqueryscan_references(), and standard_planner().

251 {
252  Plan *result;
253  PlannerGlobal *glob = root->glob;
254  int rtoffset = list_length(glob->finalrtable);
255  ListCell *lc;
256 
257  /*
258  * Add all the query's RTEs to the flattened rangetable. The live ones
259  * will have their rangetable indexes increased by rtoffset. (Additional
260  * RTEs, not referenced by the Plan tree, might get added after those.)
261  */
262  add_rtes_to_flat_rtable(root, false);
263 
264  /*
265  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
266  */
267  foreach(lc, root->rowMarks)
268  {
270  PlanRowMark *newrc;
271 
272  /* flat copy is enough since all fields are scalars */
273  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
274  memcpy(newrc, rc, sizeof(PlanRowMark));
275 
276  /* adjust indexes ... but *not* the rowmarkId */
277  newrc->rti += rtoffset;
278  newrc->prti += rtoffset;
279 
280  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
281  }
282 
283  /*
284  * Adjust RT indexes of AppendRelInfos and add to final appendrels list.
285  * We assume the AppendRelInfos were built during planning and don't need
286  * to be copied.
287  */
288  foreach(lc, root->append_rel_list)
289  {
290  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
291 
292  /* adjust RT indexes */
293  appinfo->parent_relid += rtoffset;
294  appinfo->child_relid += rtoffset;
295 
296  /*
297  * Rather than adjust the translated_vars entries, just drop 'em.
298  * Neither the executor nor EXPLAIN currently need that data.
299  */
300  appinfo->translated_vars = NIL;
301 
302  glob->appendRelations = lappend(glob->appendRelations, appinfo);
303  }
304 
305  /* If needed, create workspace for processing AlternativeSubPlans */
306  if (root->hasAlternativeSubPlans)
307  {
308  root->isAltSubplan = (bool *)
309  palloc0(list_length(glob->subplans) * sizeof(bool));
310  root->isUsedSubplan = (bool *)
311  palloc0(list_length(glob->subplans) * sizeof(bool));
312  }
313 
314  /* Now fix the Plan tree */
315  result = set_plan_refs(root, plan, rtoffset);
316 
317  /*
318  * If we have AlternativeSubPlans, it is likely that we now have some
319  * unreferenced subplans in glob->subplans. To avoid expending cycles on
320  * those subplans later, get rid of them by setting those list entries to
321  * NULL. (Note: we can't do this immediately upon processing an
322  * AlternativeSubPlan, because there may be multiple copies of the
323  * AlternativeSubPlan, and they can get resolved differently.)
324  */
325  if (root->hasAlternativeSubPlans)
326  {
327  foreach(lc, glob->subplans)
328  {
329  int ndx = foreach_current_index(lc);
330 
331  /*
332  * If it was used by some AlternativeSubPlan in this query level,
333  * but wasn't selected as best by any AlternativeSubPlan, then we
334  * don't need it. Do not touch subplans that aren't parts of
335  * AlternativeSubPlans.
336  */
337  if (root->isAltSubplan[ndx] && !root->isUsedSubplan[ndx])
338  lfirst(lc) = NULL;
339  }
340  }
341 
342  return result;
343 }
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:288
bool * isUsedSubplan
Definition: pathnodes.h:373
List * appendRelations
Definition: pathnodes.h:108
Index prti
Definition: plannodes.h:1121
List * translated_vars
Definition: pathnodes.h:2334
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:527
bool hasAlternativeSubPlans
Definition: pathnodes.h:351
#define lfirst_node(type, lc)
Definition: pg_list.h:172
List * subplans
Definition: pathnodes.h:96
PlannerGlobal * glob
Definition: pathnodes.h:164
List * lappend(List *list, void *datum)
Definition: list.c:336
void * palloc0(Size size)
Definition: mcxt.c:1093
List * append_rel_list
Definition: pathnodes.h:284
#define lfirst(lc)
Definition: pg_list.h:169
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:351
static int list_length(const List *l)
Definition: pg_list.h:149
bool * isAltSubplan
Definition: pathnodes.h:372
List * finalrtable
Definition: pathnodes.h:102
void * palloc(Size size)
Definition: mcxt.c:1062
Index child_relid
Definition: pathnodes.h:2307
Index parent_relid
Definition: pathnodes.h:2306
List * finalrowmarks
Definition: pathnodes.h:104
#define foreach_current_index(cell)
Definition: pg_list.h:382
unsigned char bool
Definition: c.h:391

◆ set_plan_refs()

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

Definition at line 527 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, TargetEntry::expr, fix_join_expr(), fix_scan_expr(), fix_scan_list, forboth, FunctionScan::functions, PlannerInfo::glob, IndexScan::indexorderby, IndexScan::indexorderbyorig, IndexScan::indexqual, BitmapIndexScan::indexqual, IndexScan::indexqualorig, BitmapIndexScan::indexqualorig, IsA, lappend(), lappend_int(), PlannerGlobal::lastPlanNodeId, Plan::lefttree, lfirst, lfirst_int, Limit::limitCount, Limit::limitOffset, linitial, linitial_int, list_concat(), list_length(), makeNullConst(), NIL, nodeTag, ModifyTable::nominalRelation, NUM_EXEC_QUAL, NUM_EXEC_TLIST, ModifyTable::onConflictSet, ModifyTable::onConflictWhere, outerPlan, Memoize::param_exprs, pfree(), Result::plan, ModifyTable::plan, BitmapAnd::plan, BitmapOr::plan, Scan::plan, LockRows::plan, Limit::plan, Plan::plan_node_id, PlanRowMark::prti, Plan::qual, Result::resconstantqual, PlannerGlobal::resultRelations, ModifyTable::resultRelations, ModifyTable::returningLists, Plan::righttree, ModifyTable::rootRelation, ROWID_VAR, ModifyTable::rowMarks, LockRows::rowMarks, PlanRowMark::rti, SeqScan::scan, SampleScan::scan, IndexScan::scan, BitmapIndexScan::scan, BitmapHeapScan::scan, TidScan::scan, TidRangeScan::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_Memoize, 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_TidRangeScan, T_TidScan, T_Unique, T_ValuesScan, T_WindowAgg, T_WorkTableScan, TableFuncScan::tablefunc, SampleScan::tablesample, Plan::targetlist, TidScan::tidquals, TidRangeScan::tidrangequals, ValuesScan::values_lists, Var::varcollid, Var::varno, Var::vartype, Var::vartypmod, and ModifyTable::withCheckOptionLists.

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

528 {
529  ListCell *l;
530 
531  if (plan == NULL)
532  return NULL;
533 
534  /* Assign this node a unique ID. */
535  plan->plan_node_id = root->glob->lastPlanNodeId++;
536 
537  /*
538  * Plan-type-specific fixes
539  */
540  switch (nodeTag(plan))
541  {
542  case T_SeqScan:
543  {
544  SeqScan *splan = (SeqScan *) plan;
545 
546  splan->scan.scanrelid += rtoffset;
547  splan->scan.plan.targetlist =
548  fix_scan_list(root, splan->scan.plan.targetlist,
549  rtoffset, NUM_EXEC_TLIST(plan));
550  splan->scan.plan.qual =
551  fix_scan_list(root, splan->scan.plan.qual,
552  rtoffset, NUM_EXEC_QUAL(plan));
553  }
554  break;
555  case T_SampleScan:
556  {
557  SampleScan *splan = (SampleScan *) plan;
558 
559  splan->scan.scanrelid += rtoffset;
560  splan->scan.plan.targetlist =
561  fix_scan_list(root, splan->scan.plan.targetlist,
562  rtoffset, NUM_EXEC_TLIST(plan));
563  splan->scan.plan.qual =
564  fix_scan_list(root, splan->scan.plan.qual,
565  rtoffset, NUM_EXEC_QUAL(plan));
566  splan->tablesample = (TableSampleClause *)
567  fix_scan_expr(root, (Node *) splan->tablesample,
568  rtoffset, 1);
569  }
570  break;
571  case T_IndexScan:
572  {
573  IndexScan *splan = (IndexScan *) plan;
574 
575  splan->scan.scanrelid += rtoffset;
576  splan->scan.plan.targetlist =
577  fix_scan_list(root, splan->scan.plan.targetlist,
578  rtoffset, NUM_EXEC_TLIST(plan));
579  splan->scan.plan.qual =
580  fix_scan_list(root, splan->scan.plan.qual,
581  rtoffset, NUM_EXEC_QUAL(plan));
582  splan->indexqual =
583  fix_scan_list(root, splan->indexqual,
584  rtoffset, 1);
585  splan->indexqualorig =
586  fix_scan_list(root, splan->indexqualorig,
587  rtoffset, NUM_EXEC_QUAL(plan));
588  splan->indexorderby =
589  fix_scan_list(root, splan->indexorderby,
590  rtoffset, 1);
591  splan->indexorderbyorig =
592  fix_scan_list(root, splan->indexorderbyorig,
593  rtoffset, NUM_EXEC_QUAL(plan));
594  }
595  break;
596  case T_IndexOnlyScan:
597  {
598  IndexOnlyScan *splan = (IndexOnlyScan *) plan;
599 
600  return set_indexonlyscan_references(root, splan, rtoffset);
601  }
602  break;
603  case T_BitmapIndexScan:
604  {
605  BitmapIndexScan *splan = (BitmapIndexScan *) plan;
606 
607  splan->scan.scanrelid += rtoffset;
608  /* no need to fix targetlist and qual */
609  Assert(splan->scan.plan.targetlist == NIL);
610  Assert(splan->scan.plan.qual == NIL);
611  splan->indexqual =
612  fix_scan_list(root, splan->indexqual, rtoffset, 1);
613  splan->indexqualorig =
614  fix_scan_list(root, splan->indexqualorig,
615  rtoffset, NUM_EXEC_QUAL(plan));
616  }
617  break;
618  case T_BitmapHeapScan:
619  {
620  BitmapHeapScan *splan = (BitmapHeapScan *) plan;
621 
622  splan->scan.scanrelid += rtoffset;
623  splan->scan.plan.targetlist =
624  fix_scan_list(root, splan->scan.plan.targetlist,
625  rtoffset, NUM_EXEC_TLIST(plan));
626  splan->scan.plan.qual =
627  fix_scan_list(root, splan->scan.plan.qual,
628  rtoffset, NUM_EXEC_QUAL(plan));
629  splan->bitmapqualorig =
630  fix_scan_list(root, splan->bitmapqualorig,
631  rtoffset, NUM_EXEC_QUAL(plan));
632  }
633  break;
634  case T_TidScan:
635  {
636  TidScan *splan = (TidScan *) plan;
637 
638  splan->scan.scanrelid += rtoffset;
639  splan->scan.plan.targetlist =
640  fix_scan_list(root, splan->scan.plan.targetlist,
641  rtoffset, NUM_EXEC_TLIST(plan));
642  splan->scan.plan.qual =
643  fix_scan_list(root, splan->scan.plan.qual,
644  rtoffset, NUM_EXEC_QUAL(plan));
645  splan->tidquals =
646  fix_scan_list(root, splan->tidquals,
647  rtoffset, 1);
648  }
649  break;
650  case T_TidRangeScan:
651  {
652  TidRangeScan *splan = (TidRangeScan *) plan;
653 
654  splan->scan.scanrelid += rtoffset;
655  splan->scan.plan.targetlist =
656  fix_scan_list(root, splan->scan.plan.targetlist,
657  rtoffset, NUM_EXEC_TLIST(plan));
658  splan->scan.plan.qual =
659  fix_scan_list(root, splan->scan.plan.qual,
660  rtoffset, NUM_EXEC_QUAL(plan));
661  splan->tidrangequals =
662  fix_scan_list(root, splan->tidrangequals,
663  rtoffset, 1);
664  }
665  break;
666  case T_SubqueryScan:
667  /* Needs special treatment, see comments below */
668  return set_subqueryscan_references(root,
669  (SubqueryScan *) plan,
670  rtoffset);
671  case T_FunctionScan:
672  {
673  FunctionScan *splan = (FunctionScan *) plan;
674 
675  splan->scan.scanrelid += rtoffset;
676  splan->scan.plan.targetlist =
677  fix_scan_list(root, splan->scan.plan.targetlist,
678  rtoffset, NUM_EXEC_TLIST(plan));
679  splan->scan.plan.qual =
680  fix_scan_list(root, splan->scan.plan.qual,
681  rtoffset, NUM_EXEC_QUAL(plan));
682  splan->functions =
683  fix_scan_list(root, splan->functions, rtoffset, 1);
684  }
685  break;
686  case T_TableFuncScan:
687  {
688  TableFuncScan *splan = (TableFuncScan *) plan;
689 
690  splan->scan.scanrelid += rtoffset;
691  splan->scan.plan.targetlist =
692  fix_scan_list(root, splan->scan.plan.targetlist,
693  rtoffset, NUM_EXEC_TLIST(plan));
694  splan->scan.plan.qual =
695  fix_scan_list(root, splan->scan.plan.qual,
696  rtoffset, NUM_EXEC_QUAL(plan));
697  splan->tablefunc = (TableFunc *)
698  fix_scan_expr(root, (Node *) splan->tablefunc,
699  rtoffset, 1);
700  }
701  break;
702  case T_ValuesScan:
703  {
704  ValuesScan *splan = (ValuesScan *) plan;
705 
706  splan->scan.scanrelid += rtoffset;
707  splan->scan.plan.targetlist =
708  fix_scan_list(root, splan->scan.plan.targetlist,
709  rtoffset, NUM_EXEC_TLIST(plan));
710  splan->scan.plan.qual =
711  fix_scan_list(root, splan->scan.plan.qual,
712  rtoffset, NUM_EXEC_QUAL(plan));
713  splan->values_lists =
714  fix_scan_list(root, splan->values_lists,
715  rtoffset, 1);
716  }
717  break;
718  case T_CteScan:
719  {
720  CteScan *splan = (CteScan *) plan;
721 
722  splan->scan.scanrelid += rtoffset;
723  splan->scan.plan.targetlist =
724  fix_scan_list(root, splan->scan.plan.targetlist,
725  rtoffset, NUM_EXEC_TLIST(plan));
726  splan->scan.plan.qual =
727  fix_scan_list(root, splan->scan.plan.qual,
728  rtoffset, NUM_EXEC_QUAL(plan));
729  }
730  break;
732  {
733  NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
734 
735  splan->scan.scanrelid += rtoffset;
736  splan->scan.plan.targetlist =
737  fix_scan_list(root, splan->scan.plan.targetlist,
738  rtoffset, NUM_EXEC_TLIST(plan));
739  splan->scan.plan.qual =
740  fix_scan_list(root, splan->scan.plan.qual,
741  rtoffset, NUM_EXEC_QUAL(plan));
742  }
743  break;
744  case T_WorkTableScan:
745  {
746  WorkTableScan *splan = (WorkTableScan *) plan;
747 
748  splan->scan.scanrelid += rtoffset;
749  splan->scan.plan.targetlist =
750  fix_scan_list(root, splan->scan.plan.targetlist,
751  rtoffset, NUM_EXEC_TLIST(plan));
752  splan->scan.plan.qual =
753  fix_scan_list(root, splan->scan.plan.qual,
754  rtoffset, NUM_EXEC_QUAL(plan));
755  }
756  break;
757  case T_ForeignScan:
758  set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
759  break;
760  case T_CustomScan:
761  set_customscan_references(root, (CustomScan *) plan, rtoffset);
762  break;
763 
764  case T_NestLoop:
765  case T_MergeJoin:
766  case T_HashJoin:
767  set_join_references(root, (Join *) plan, rtoffset);
768  break;
769 
770  case T_Gather:
771  case T_GatherMerge:
772  {
773  set_upper_references(root, plan, rtoffset);
774  set_param_references(root, plan);
775  }
776  break;
777 
778  case T_Hash:
779  set_hash_references(root, plan, rtoffset);
780  break;
781 
782  case T_Memoize:
783  {
784  Memoize *mplan = (Memoize *) plan;
785 
786  /*
787  * Memoize does not evaluate its targetlist. It just uses the
788  * same targetlist from its outer subnode.
789  */
790  set_dummy_tlist_references(plan, rtoffset);
791 
792  mplan->param_exprs = fix_scan_list(root, mplan->param_exprs,
793  rtoffset,
794  NUM_EXEC_TLIST(plan));
795  break;
796  }
797 
798  case T_Material:
799  case T_Sort:
800  case T_IncrementalSort:
801  case T_Unique:
802  case T_SetOp:
803 
804  /*
805  * These plan types don't actually bother to evaluate their
806  * targetlists, because they just return their unmodified input
807  * tuples. Even though the targetlist won't be used by the
808  * executor, we fix it up for possible use by EXPLAIN (not to
809  * mention ease of debugging --- wrong varnos are very confusing).
810  */
811  set_dummy_tlist_references(plan, rtoffset);
812 
813  /*
814  * Since these plan types don't check quals either, we should not
815  * find any qual expression attached to them.
816  */
817  Assert(plan->qual == NIL);
818  break;
819  case T_LockRows:
820  {
821  LockRows *splan = (LockRows *) plan;
822 
823  /*
824  * Like the plan types above, LockRows doesn't evaluate its
825  * tlist or quals. But we have to fix up the RT indexes in
826  * its rowmarks.
827  */
828  set_dummy_tlist_references(plan, rtoffset);
829  Assert(splan->plan.qual == NIL);
830 
831  foreach(l, splan->rowMarks)
832  {
833  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
834 
835  rc->rti += rtoffset;
836  rc->prti += rtoffset;
837  }
838  }
839  break;
840  case T_Limit:
841  {
842  Limit *splan = (Limit *) plan;
843 
844  /*
845  * Like the plan types above, Limit doesn't evaluate its tlist
846  * or quals. It does have live expressions for limit/offset,
847  * however; and those cannot contain subplan variable refs, so
848  * fix_scan_expr works for them.
849  */
850  set_dummy_tlist_references(plan, rtoffset);
851  Assert(splan->plan.qual == NIL);
852 
853  splan->limitOffset =
854  fix_scan_expr(root, splan->limitOffset, rtoffset, 1);
855  splan->limitCount =
856  fix_scan_expr(root, splan->limitCount, rtoffset, 1);
857  }
858  break;
859  case T_Agg:
860  {
861  Agg *agg = (Agg *) plan;
862 
863  /*
864  * If this node is combining partial-aggregation results, we
865  * must convert its Aggrefs to contain references to the
866  * partial-aggregate subexpressions that will be available
867  * from the child plan node.
868  */
869  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
870  {
871  plan->targetlist = (List *)
873  NULL);
874  plan->qual = (List *)
876  NULL);
877  }
878 
879  set_upper_references(root, plan, rtoffset);
880  }
881  break;
882  case T_Group:
883  set_upper_references(root, plan, rtoffset);
884  break;
885  case T_WindowAgg:
886  {
887  WindowAgg *wplan = (WindowAgg *) plan;
888 
889  set_upper_references(root, plan, rtoffset);
890 
891  /*
892  * Like Limit node limit/offset expressions, WindowAgg has
893  * frame offset expressions, which cannot contain subplan
894  * variable refs, so fix_scan_expr works for them.
895  */
896  wplan->startOffset =
897  fix_scan_expr(root, wplan->startOffset, rtoffset, 1);
898  wplan->endOffset =
899  fix_scan_expr(root, wplan->endOffset, rtoffset, 1);
900  }
901  break;
902  case T_Result:
903  {
904  Result *splan = (Result *) plan;
905 
906  /*
907  * Result may or may not have a subplan; if not, it's more
908  * like a scan node than an upper node.
909  */
910  if (splan->plan.lefttree != NULL)
911  set_upper_references(root, plan, rtoffset);
912  else
913  {
914  /*
915  * The tlist of a childless Result could contain
916  * unresolved ROWID_VAR Vars, in case it's representing a
917  * target relation which is completely empty because of
918  * constraint exclusion. Replace any such Vars by null
919  * constants, as though they'd been resolved for a leaf
920  * scan node that doesn't support them. We could have
921  * fix_scan_expr do this, but since the case is only
922  * expected to occur here, it seems safer to special-case
923  * it here and keep the assertions that ROWID_VARs
924  * shouldn't be seen by fix_scan_expr.
925  */
926  foreach(l, splan->plan.targetlist)
927  {
928  TargetEntry *tle = (TargetEntry *) lfirst(l);
929  Var *var = (Var *) tle->expr;
930 
931  if (var && IsA(var, Var) && var->varno == ROWID_VAR)
932  tle->expr = (Expr *) makeNullConst(var->vartype,
933  var->vartypmod,
934  var->varcollid);
935  }
936 
937  splan->plan.targetlist =
938  fix_scan_list(root, splan->plan.targetlist,
939  rtoffset, NUM_EXEC_TLIST(plan));
940  splan->plan.qual =
941  fix_scan_list(root, splan->plan.qual,
942  rtoffset, NUM_EXEC_QUAL(plan));
943  }
944  /* resconstantqual can't contain any subplan variable refs */
945  splan->resconstantqual =
946  fix_scan_expr(root, splan->resconstantqual, rtoffset, 1);
947  }
948  break;
949  case T_ProjectSet:
950  set_upper_references(root, plan, rtoffset);
951  break;
952  case T_ModifyTable:
953  {
954  ModifyTable *splan = (ModifyTable *) plan;
955 
956  Assert(splan->plan.targetlist == NIL);
957  Assert(splan->plan.qual == NIL);
958 
959  splan->withCheckOptionLists =
960  fix_scan_list(root, splan->withCheckOptionLists,
961  rtoffset, 1);
962 
963  if (splan->returningLists)
964  {
965  List *newRL = NIL;
966  Plan *subplan = outerPlan(splan);
967  ListCell *lcrl,
968  *lcrr;
969 
970  /*
971  * Pass each per-resultrel returningList through
972  * set_returning_clause_references().
973  */
975  forboth(lcrl, splan->returningLists,
976  lcrr, splan->resultRelations)
977  {
978  List *rlist = (List *) lfirst(lcrl);
979  Index resultrel = lfirst_int(lcrr);
980 
981  rlist = set_returning_clause_references(root,
982  rlist,
983  subplan,
984  resultrel,
985  rtoffset);
986  newRL = lappend(newRL, rlist);
987  }
988  splan->returningLists = newRL;
989 
990  /*
991  * Set up the visible plan targetlist as being the same as
992  * the first RETURNING list. This is for the use of
993  * EXPLAIN; the executor won't pay any attention to the
994  * targetlist. We postpone this step until here so that
995  * we don't have to do set_returning_clause_references()
996  * twice on identical targetlists.
997  */
998  splan->plan.targetlist = copyObject(linitial(newRL));
999  }
1000 
1001  /*
1002  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
1003  * join', where the inner side is the EXCLUDED tuple.
1004  * Therefore use fix_join_expr to setup the relevant variables
1005  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
1006  * those are already used by RETURNING and it seems better to
1007  * be non-conflicting.
1008  */
1009  if (splan->onConflictSet)
1010  {
1011  indexed_tlist *itlist;
1012 
1013  itlist = build_tlist_index(splan->exclRelTlist);
1014 
1015  splan->onConflictSet =
1016  fix_join_expr(root, splan->onConflictSet,
1017  NULL, itlist,
1018  linitial_int(splan->resultRelations),
1019  rtoffset, NUM_EXEC_QUAL(plan));
1020 
1021  splan->onConflictWhere = (Node *)
1022  fix_join_expr(root, (List *) splan->onConflictWhere,
1023  NULL, itlist,
1024  linitial_int(splan->resultRelations),
1025  rtoffset, NUM_EXEC_QUAL(plan));
1026 
1027  pfree(itlist);
1028 
1029  splan->exclRelTlist =
1030  fix_scan_list(root, splan->exclRelTlist, rtoffset, 1);
1031  }
1032 
1033  splan->nominalRelation += rtoffset;
1034  if (splan->rootRelation)
1035  splan->rootRelation += rtoffset;
1036  splan->exclRelRTI += rtoffset;
1037 
1038  foreach(l, splan->resultRelations)
1039  {
1040  lfirst_int(l) += rtoffset;
1041  }
1042  foreach(l, splan->rowMarks)
1043  {
1044  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
1045 
1046  rc->rti += rtoffset;
1047  rc->prti += rtoffset;
1048  }
1049 
1050  /*
1051  * Append this ModifyTable node's final result relation RT
1052  * index(es) to the global list for the plan.
1053  */
1054  root->glob->resultRelations =
1056  splan->resultRelations);
1057  if (splan->rootRelation)
1058  {
1059  root->glob->resultRelations =
1061  splan->rootRelation);
1062  }
1063  }
1064  break;
1065  case T_Append:
1066  /* Needs special treatment, see comments below */
1067  return set_append_references(root,
1068  (Append *) plan,
1069  rtoffset);
1070  case T_MergeAppend:
1071  /* Needs special treatment, see comments below */
1072  return set_mergeappend_references(root,
1073  (MergeAppend *) plan,
1074  rtoffset);
1075  case T_RecursiveUnion:
1076  /* This doesn't evaluate targetlist or check quals either */
1077  set_dummy_tlist_references(plan, rtoffset);
1078  Assert(plan->qual == NIL);
1079  break;
1080  case T_BitmapAnd:
1081  {
1082  BitmapAnd *splan = (BitmapAnd *) plan;
1083 
1084  /* BitmapAnd works like Append, but has no tlist */
1085  Assert(splan->plan.targetlist == NIL);
1086  Assert(splan->plan.qual == NIL);
1087  foreach(l, splan->bitmapplans)
1088  {
1089  lfirst(l) = set_plan_refs(root,
1090  (Plan *) lfirst(l),
1091  rtoffset);
1092  }
1093  }
1094  break;
1095  case T_BitmapOr:
1096  {
1097  BitmapOr *splan = (BitmapOr *) plan;
1098 
1099  /* BitmapOr works like Append, but has no tlist */
1100  Assert(splan->plan.targetlist == NIL);
1101  Assert(splan->plan.qual == NIL);
1102  foreach(l, splan->bitmapplans)
1103  {
1104  lfirst(l) = set_plan_refs(root,
1105  (Plan *) lfirst(l),
1106  rtoffset);
1107  }
1108  }
1109  break;
1110  default:
1111  elog(ERROR, "unrecognized node type: %d",
1112  (int) nodeTag(plan));
1113  break;
1114  }
1115 
1116  /*
1117  * Now recurse into child plans, if any
1118  *
1119  * NOTE: it is essential that we recurse into child plans AFTER we set
1120  * subplan references in this plan's tlist and quals. If we did the
1121  * reference-adjustments bottom-up, then we would fail to match this
1122  * plan's var nodes against the already-modified nodes of the children.
1123  */
1124  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
1125  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1126 
1127  return plan;
1128 }
List * tidrangequals
Definition: plannodes.h:508
List * bitmapplans
Definition: plannodes.h:318
int varno
Definition: primnodes.h:189
#define NIL
Definition: pg_list.h:65
Plan plan
Definition: plannodes.h:187
List * qual
Definition: plannodes.h:142
Definition: nodes.h:81
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:343
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Plan plan
Definition: plannodes.h:1026
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
Index nominalRelation
Definition: plannodes.h:222
Definition: nodes.h:83
Index scanrelid
Definition: plannodes.h:344
#define ROWID_VAR
Definition: primnodes.h:178
Plan plan
Definition: plannodes.h:1012
List * withCheckOptionLists
Definition: plannodes.h:227
List * functions
Definition: plannodes.h:540
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset)
Definition: setrefs.c:1983
int lastPlanNodeId
Definition: pathnodes.h:120
List * indexqual
Definition: plannodes.h:465
List * tidquals
Definition: plannodes.h:495
TableFunc * tablefunc
Definition: plannodes.h:561
int plan_node_id
Definition: plannodes.h:140
List * resultRelations
Definition: pathnodes.h:106
List * indexqualorig
Definition: plannodes.h:409
struct TableSampleClause * tablesample
Definition: plannodes.h:364
Definition: nodes.h:536
List * list_concat(List *list1, const List *list2)
Definition: list.c:530
Definition: nodes.h:49
Index prti
Definition: plannodes.h:1121
List * values_lists
Definition: plannodes.h:551
static void set_param_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:2197
Definition: nodes.h:78
Definition: primnodes.h:186
Scan scan
Definition: plannodes.h:550
Node * limitOffset
Definition: plannodes.h:1027
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:799
static Plan * set_append_references(PlannerInfo *root, Append *aplan, int rtoffset)
Definition: setrefs.c:1471
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:527
List * onConflictSet
Definition: plannodes.h:235
Index rootRelation
Definition: plannodes.h:223
Const * makeNullConst(Oid consttype, int32 consttypmod, Oid constcollid)
Definition: makefuncs.c:337
List * resultRelations
Definition: plannodes.h:225
static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, int rtoffset)
Definition: setrefs.c:1316
#define linitial_int(l)
Definition: pg_list.h:175
Node * startOffset
Definition: plannodes.h:894
Node * resconstantqual
Definition: plannodes.h:188
List * param_exprs
Definition: plannodes.h:798
List * rowMarks
Definition: plannodes.h:231
struct Plan * righttree
Definition: plannodes.h:144
void pfree(void *pointer)
Definition: mcxt.c:1169
#define linitial(l)
Definition: pg_list.h:174
Definition: nodes.h:46
#define ERROR
Definition: elog.h:46
List * indexorderbyorig
Definition: plannodes.h:411
#define lfirst_int(lc)
Definition: pg_list.h:170
Oid vartype
Definition: primnodes.h:193
Scan scan
Definition: plannodes.h:362
Scan scan
Definition: plannodes.h:570
Node * limitCount
Definition: plannodes.h:1028
Scan scan
Definition: plannodes.h:406
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
Definition: nodes.h:80
PlannerGlobal * glob
Definition: pathnodes.h:164
Node * endOffset
Definition: plannodes.h:895
static SPIPlanPtr splan
Definition: regress.c:263
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1398
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:1186
List * indexqual
Definition: plannodes.h:408
List * bitmapqualorig
Definition: plannodes.h:481
List * lappend_int(List *list, int datum)
Definition: list.c:354
#define outerPlan(node)
Definition: plannodes.h:171
List * lappend(List *list, void *datum)
Definition: list.c:336
Plan plan
Definition: plannodes.h:331
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:1140
List * bitmapplans
Definition: plannodes.h:333
static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:2134
unsigned int Index
Definition: c.h:549
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
Definition: nodes.h:86
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:2252
List * indexorderby
Definition: plannodes.h:410
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
AggSplit aggsplit
Definition: plannodes.h:864
Expr * expr
Definition: primnodes.h:1455
List * rowMarks
Definition: plannodes.h:1013
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
Scan scan
Definition: plannodes.h:494
static int list_length(const List *l)
Definition: pg_list.h:149
struct Plan * lefttree
Definition: plannodes.h:143
List * indexqualorig
Definition: plannodes.h:466
#define nodeTag(nodeptr)
Definition: nodes.h:541
List * targetlist
Definition: plannodes.h:141
Definition: nodes.h:87
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2913
Definition: nodes.h:84
#define elog(elevel,...)
Definition: elog.h:232
Oid varcollid
Definition: primnodes.h:195
List * returningLists
Definition: plannodes.h:228
Plan plan
Definition: plannodes.h:317
Definition: plannodes.h:860
#define copyObject(obj)
Definition: nodes.h:652
Index exclRelRTI
Definition: plannodes.h:238
static Plan * set_mergeappend_references(PlannerInfo *root, MergeAppend *mplan, int rtoffset)
Definition: setrefs.c:1535
Definition: pg_list.h:50
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset, double num_exec)
Definition: setrefs.c:1854
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2321
List * exclRelTlist
Definition: plannodes.h:239
static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1596
Scan scan
Definition: plannodes.h:353
Node * onConflictWhere
Definition: plannodes.h:237
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:2634
Definition: nodes.h:89
int32 vartypmod
Definition: primnodes.h:194

◆ set_returning_clause_references()

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

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

2918 {
2919  indexed_tlist *itlist;
2920 
2921  /*
2922  * We can perform the desired Var fixup by abusing the fix_join_expr
2923  * machinery that formerly handled inner indexscan fixup. We search the
2924  * top plan's targetlist for Vars of non-result relations, and use
2925  * fix_join_expr to convert RETURNING Vars into references to those tlist
2926  * entries, while leaving result-rel Vars as-is.
2927  *
2928  * PlaceHolderVars will also be sought in the targetlist, but no
2929  * more-complex expressions will be. Note that it is not possible for a
2930  * PlaceHolderVar to refer to the result relation, since the result is
2931  * never below an outer join. If that case could happen, we'd have to be
2932  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2933  * expression instead.
2934  */
2935  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2936 
2937  rlist = fix_join_expr(root,
2938  rlist,
2939  itlist,
2940  NULL,
2941  resultRelation,
2942  rtoffset,
2943  NUM_EXEC_TLIST(topplan));
2944 
2945  pfree(itlist);
2946 
2947  return rlist;
2948 }
void pfree(void *pointer)
Definition: mcxt.c:1169
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static indexed_tlist * build_tlist_index_other_vars(List *tlist, int ignore_rel)
Definition: setrefs.c:2438
List * targetlist
Definition: plannodes.h:141
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:2634

◆ set_subqueryscan_references()

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

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

1189 {
1190  RelOptInfo *rel;
1191  Plan *result;
1192 
1193  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1194  rel = find_base_rel(root, plan->scan.scanrelid);
1195 
1196  /* Recursively process the subplan */
1197  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1198 
1199  if (trivial_subqueryscan(plan))
1200  {
1201  /*
1202  * We can omit the SubqueryScan node and just pull up the subplan.
1203  */
1204  result = clean_up_removed_plan_level((Plan *) plan, plan->subplan);
1205  }
1206  else
1207  {
1208  /*
1209  * Keep the SubqueryScan node. We have to do the processing that
1210  * set_plan_references would otherwise have done on it. Notice we do
1211  * not do set_upper_references() here, because a SubqueryScan will
1212  * always have been created with correct references to its subplan's
1213  * outputs to begin with.
1214  */
1215  plan->scan.scanrelid += rtoffset;
1216  plan->scan.plan.targetlist =
1217  fix_scan_list(root, plan->scan.plan.targetlist,
1218  rtoffset, NUM_EXEC_TLIST((Plan *) plan));
1219  plan->scan.plan.qual =
1220  fix_scan_list(root, plan->scan.plan.qual,
1221  rtoffset, NUM_EXEC_QUAL((Plan *) plan));
1222 
1223  result = (Plan *) plan;
1224  }
1225 
1226  return result;
1227 }
List * qual
Definition: plannodes.h:142
#define fix_scan_list(root, lst, rtoffset, num_exec)
Definition: setrefs.c:104
Plan plan
Definition: plannodes.h:343
Index scanrelid
Definition: plannodes.h:344
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1237
PlannerInfo * subroot
Definition: pathnodes.h:725
#define NUM_EXEC_TLIST(parentplan)
Definition: setrefs.c:90
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1295
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
List * targetlist
Definition: plannodes.h:141
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:250
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:375
Plan * subplan
Definition: plannodes.h:530

◆ set_upper_references()

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

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

2135 {
2136  Plan *subplan = plan->lefttree;
2137  indexed_tlist *subplan_itlist;
2138  List *output_targetlist;
2139  ListCell *l;
2140 
2141  subplan_itlist = build_tlist_index(subplan->targetlist);
2142 
2143  output_targetlist = NIL;
2144  foreach(l, plan->targetlist)
2145  {
2146  TargetEntry *tle = (TargetEntry *) lfirst(l);
2147  Node *newexpr;
2148 
2149  /* If it's a sort/group item, first try to match by sortref */
2150  if (tle->ressortgroupref != 0)
2151  {
2152  newexpr = (Node *)
2154  tle->ressortgroupref,
2155  subplan_itlist,
2156  OUTER_VAR);
2157  if (!newexpr)
2158  newexpr = fix_upper_expr(root,
2159  (Node *) tle->expr,
2160  subplan_itlist,
2161  OUTER_VAR,
2162  rtoffset,
2163  NUM_EXEC_TLIST(plan));
2164  }
2165  else
2166  newexpr = fix_upper_expr(root,
2167  (Node *) tle->expr,
2168  subplan_itlist,
2169  OUTER_VAR,
2170  rtoffset,
2171  NUM_EXEC_TLIST(plan));
2172  tle = flatCopyTargetEntry(tle);
2173  tle->expr = (Expr *) newexpr;
2174  output_targetlist = lappend(output_targetlist, tle);
2175  }
2176  plan->targetlist = output_targetlist;
2177 
2178  plan->qual = (List *)
2179  fix_upper_expr(root,
2180  (Node *) plan->qual,
2181  subplan_itlist,
2182  OUTER_VAR,
2183  rtoffset,
2184  NUM_EXEC_QUAL(plan));
2185 
2186  pfree(subplan_itlist);
2187 }
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
Definition: nodes.h:536
static Var * search_indexed_tlist_for_sortgroupref(Expr *node, Index sortgroupref, indexed_tlist *itlist, int newvarno)
Definition: setrefs.c:2569
void pfree(void *pointer)
Definition: mcxt.c:1169
#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:336
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, int newvarno, int rtoffset, double num_exec)
Definition: setrefs.c:2787
#define NUM_EXEC_QUAL(parentplan)
Definition: setrefs.c:91
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2388
struct Plan * lefttree
Definition: plannodes.h:143
List * targetlist
Definition: plannodes.h:141
Index ressortgroupref
Definition: primnodes.h:1458
Definition: pg_list.h:50
#define OUTER_VAR
Definition: primnodes.h:176

◆ trivial_subqueryscan()

static bool trivial_subqueryscan ( SubqueryScan plan)
static

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

1238 {
1239  int attrno;
1240  ListCell *lp,
1241  *lc;
1242 
1243  if (plan->scan.plan.qual != NIL)
1244  return false;
1245 
1246  if (list_length(plan->scan.plan.targetlist) !=
1247  list_length(plan->subplan->targetlist))
1248  return false; /* tlists not same length */
1249 
1250  attrno = 1;
1251  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1252  {
1253  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1254  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1255 
1256  if (ptle->resjunk != ctle->resjunk)
1257  return false; /* tlist doesn't match junk status */
1258 
1259  /*
1260  * We accept either a Var referencing the corresponding element of the
1261  * subplan tlist, or a Const equaling the subplan element. See
1262  * generate_setop_tlist() for motivation.
1263  */
1264  if (ptle->expr && IsA(ptle->expr, Var))
1265  {
1266  Var *var = (Var *) ptle->expr;
1267 
1268  Assert(var->varno == plan->scan.scanrelid);
1269  Assert(var->varlevelsup == 0);
1270  if (var->varattno != attrno)
1271  return false; /* out of order */
1272  }
1273  else if (ptle->expr && IsA(ptle->expr, Const))
1274  {
1275  if (!equal(ptle->expr, ctle->expr))
1276  return false;
1277  }
1278  else
1279  return false;
1280 
1281  attrno++;
1282  }
1283 
1284  return true;
1285 }
int varno
Definition: primnodes.h:189
#define NIL
Definition: pg_list.h:65
List * qual
Definition: plannodes.h:142
Plan plan
Definition: plannodes.h:343
#define IsA(nodeptr, _type_)
Definition: nodes.h:587
Index varlevelsup
Definition: primnodes.h:196
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:446
Index scanrelid
Definition: plannodes.h:344
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3149
AttrNumber varattno
Definition: primnodes.h:191
Definition: primnodes.h:186
bool resjunk
Definition: primnodes.h:1462
#define Assert(condition)
Definition: c.h:804
#define lfirst(lc)
Definition: pg_list.h:169
Expr * expr
Definition: primnodes.h:1455
static int list_length(const List *l)
Definition: pg_list.h:149
List * targetlist
Definition: plannodes.h:141
Plan * subplan
Definition: plannodes.h:530