PostgreSQL Source Code  git master
setrefs.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * setrefs.c
4  * Post-processing of a completed plan tree: fix references to subplan
5  * vars, compute regproc values for operators, etc
6  *
7  * Portions Copyright (c) 1996-2020, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  * src/backend/optimizer/plan/setrefs.c
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17 
18 #include "access/transam.h"
19 #include "catalog/pg_type.h"
20 #include "nodes/makefuncs.h"
21 #include "nodes/nodeFuncs.h"
22 #include "optimizer/optimizer.h"
23 #include "optimizer/pathnode.h"
24 #include "optimizer/planmain.h"
25 #include "optimizer/planner.h"
26 #include "optimizer/tlist.h"
27 #include "tcop/utility.h"
28 #include "utils/lsyscache.h"
29 #include "utils/syscache.h"
30 
31 
32 typedef struct
33 {
34  Index varno; /* RT index of Var */
35  AttrNumber varattno; /* attr number of Var */
36  AttrNumber resno; /* TLE position of Var */
37 } tlist_vinfo;
38 
39 typedef struct
40 {
41  List *tlist; /* underlying target list */
42  int num_vars; /* number of plain Var tlist entries */
43  bool has_ph_vars; /* are there PlaceHolderVar entries? */
44  bool has_non_vars; /* are there other entries? */
45  tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]; /* has num_vars entries */
47 
48 typedef struct
49 {
51  int rtoffset;
53 
54 typedef struct
55 {
60  int rtoffset;
62 
63 typedef struct
64 {
68  int rtoffset;
70 
71 /*
72  * Check if a Const node is a regclass value. We accept plain OID too,
73  * since a regclass Const will get folded to that type if it's an argument
74  * to oideq or similar operators. (This might result in some extraneous
75  * values in a plan's list of relation dependencies, but the worst result
76  * would be occasional useless replans.)
77  */
78 #define ISREGCLASSCONST(con) \
79  (((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
80  !(con)->constisnull)
81 
82 #define fix_scan_list(root, lst, rtoffset) \
83  ((List *) fix_scan_expr(root, (Node *) (lst), rtoffset))
84 
85 static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing);
86 static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte);
87 static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob);
88 static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte);
89 static Plan *set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset);
91  IndexOnlyScan *plan,
92  int rtoffset);
94  SubqueryScan *plan,
95  int rtoffset);
96 static bool trivial_subqueryscan(SubqueryScan *plan);
97 static Plan *clean_up_removed_plan_level(Plan *parent, Plan *child);
98 static void set_foreignscan_references(PlannerInfo *root,
99  ForeignScan *fscan,
100  int rtoffset);
101 static void set_customscan_references(PlannerInfo *root,
102  CustomScan *cscan,
103  int rtoffset);
105  Append *aplan,
106  int rtoffset);
108  MergeAppend *mplan,
109  int rtoffset);
110 static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset);
111 static Relids offset_relid_set(Relids relids, int rtoffset);
112 static Node *fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset);
113 static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
114 static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
115 static void set_join_references(PlannerInfo *root, Join *join, int rtoffset);
116 static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset);
117 static void set_param_references(PlannerInfo *root, Plan *plan);
118 static Node *convert_combining_aggrefs(Node *node, void *context);
119 static void set_dummy_tlist_references(Plan *plan, int rtoffset);
120 static indexed_tlist *build_tlist_index(List *tlist);
122  indexed_tlist *itlist,
123  Index newvarno,
124  int rtoffset);
126  indexed_tlist *itlist,
127  Index newvarno);
129  Index sortgroupref,
130  indexed_tlist *itlist,
131  Index newvarno);
132 static List *fix_join_expr(PlannerInfo *root,
133  List *clauses,
134  indexed_tlist *outer_itlist,
135  indexed_tlist *inner_itlist,
136  Index acceptable_rel, int rtoffset);
137 static Node *fix_join_expr_mutator(Node *node,
138  fix_join_expr_context *context);
139 static Node *fix_upper_expr(PlannerInfo *root,
140  Node *node,
141  indexed_tlist *subplan_itlist,
142  Index newvarno,
143  int rtoffset);
144 static Node *fix_upper_expr_mutator(Node *node,
145  fix_upper_expr_context *context);
147  List *rlist,
148  Plan *topplan,
149  Index resultRelation,
150  int rtoffset);
151 
152 
153 /*****************************************************************************
154  *
155  * SUBPLAN REFERENCES
156  *
157  *****************************************************************************/
158 
159 /*
160  * set_plan_references
161  *
162  * This is the final processing pass of the planner/optimizer. The plan
163  * tree is complete; we just have to adjust some representational details
164  * for the convenience of the executor:
165  *
166  * 1. We flatten the various subquery rangetables into a single list, and
167  * zero out RangeTblEntry fields that are not useful to the executor.
168  *
169  * 2. We adjust Vars in scan nodes to be consistent with the flat rangetable.
170  *
171  * 3. We adjust Vars in upper plan nodes to refer to the outputs of their
172  * subplans.
173  *
174  * 4. Aggrefs in Agg plan nodes need to be adjusted in some cases involving
175  * partial aggregation or minmax aggregate optimization.
176  *
177  * 5. PARAM_MULTIEXPR Params are replaced by regular PARAM_EXEC Params,
178  * now that we have finished planning all MULTIEXPR subplans.
179  *
180  * 6. We compute regproc OIDs for operators (ie, we look up the function
181  * that implements each op).
182  *
183  * 7. We create lists of specific objects that the plan depends on.
184  * This will be used by plancache.c to drive invalidation of cached plans.
185  * Relation dependencies are represented by OIDs, and everything else by
186  * PlanInvalItems (this distinction is motivated by the shared-inval APIs).
187  * Currently, relations, user-defined functions, and domains are the only
188  * types of objects that are explicitly tracked this way.
189  *
190  * 8. We assign every plan node in the tree a unique ID.
191  *
192  * We also perform one final optimization step, which is to delete
193  * SubqueryScan, Append, and MergeAppend plan nodes that aren't doing
194  * anything useful. The reason for doing this last is that
195  * it can't readily be done before set_plan_references, because it would
196  * break set_upper_references: the Vars in the child plan's top tlist
197  * wouldn't match up with the Vars in the outer plan tree. A SubqueryScan
198  * serves a necessary function as a buffer between outer query and subquery
199  * variable numbering ... but after we've flattened the rangetable this is
200  * no longer a problem, since then there's only one rtindex namespace.
201  * Likewise, Append and MergeAppend buffer between the parent and child vars
202  * of an appendrel, but we don't need to worry about that once we've done
203  * set_plan_references.
204  *
205  * set_plan_references recursively traverses the whole plan tree.
206  *
207  * The return value is normally the same Plan node passed in, but can be
208  * different when the passed-in Plan is a node we decide isn't needed.
209  *
210  * The flattened rangetable entries are appended to root->glob->finalrtable.
211  * Also, rowmarks entries are appended to root->glob->finalrowmarks, and the
212  * RT indexes of ModifyTable result relations to root->glob->resultRelations,
213  * and flattened AppendRelInfos are appended to root->glob->appendRelations.
214  * Plan dependencies are appended to root->glob->relationOids (for relations)
215  * and root->glob->invalItems (for everything else).
216  *
217  * Notice that we modify Plan nodes in-place, but use expression_tree_mutator
218  * to process targetlist and qual expressions. We can assume that the Plan
219  * nodes were just built by the planner and are not multiply referenced, but
220  * it's not so safe to assume that for expression tree nodes.
221  */
222 Plan *
224 {
225  PlannerGlobal *glob = root->glob;
226  int rtoffset = list_length(glob->finalrtable);
227  ListCell *lc;
228 
229  /*
230  * Add all the query's RTEs to the flattened rangetable. The live ones
231  * will have their rangetable indexes increased by rtoffset. (Additional
232  * RTEs, not referenced by the Plan tree, might get added after those.)
233  */
234  add_rtes_to_flat_rtable(root, false);
235 
236  /*
237  * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
238  */
239  foreach(lc, root->rowMarks)
240  {
242  PlanRowMark *newrc;
243 
244  /* flat copy is enough since all fields are scalars */
245  newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
246  memcpy(newrc, rc, sizeof(PlanRowMark));
247 
248  /* adjust indexes ... but *not* the rowmarkId */
249  newrc->rti += rtoffset;
250  newrc->prti += rtoffset;
251 
252  glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
253  }
254 
255  /*
256  * Adjust RT indexes of AppendRelInfos and add to final appendrels list.
257  * We assume the AppendRelInfos were built during planning and don't need
258  * to be copied.
259  */
260  foreach(lc, root->append_rel_list)
261  {
262  AppendRelInfo *appinfo = lfirst_node(AppendRelInfo, lc);
263 
264  /* adjust RT indexes */
265  appinfo->parent_relid += rtoffset;
266  appinfo->child_relid += rtoffset;
267 
268  /*
269  * Rather than adjust the translated_vars entries, just drop 'em.
270  * Neither the executor nor EXPLAIN currently need that data.
271  */
272  appinfo->translated_vars = NIL;
273 
274  glob->appendRelations = lappend(glob->appendRelations, appinfo);
275  }
276 
277  /* Now fix the Plan tree */
278  return set_plan_refs(root, plan, rtoffset);
279 }
280 
281 /*
282  * Extract RangeTblEntries from the plan's rangetable, and add to flat rtable
283  *
284  * This can recurse into subquery plans; "recursing" is true if so.
285  */
286 static void
287 add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
288 {
289  PlannerGlobal *glob = root->glob;
290  Index rti;
291  ListCell *lc;
292 
293  /*
294  * Add the query's own RTEs to the flattened rangetable.
295  *
296  * At top level, we must add all RTEs so that their indexes in the
297  * flattened rangetable match up with their original indexes. When
298  * recursing, we only care about extracting relation RTEs.
299  */
300  foreach(lc, root->parse->rtable)
301  {
302  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
303 
304  if (!recursing || rte->rtekind == RTE_RELATION)
305  add_rte_to_flat_rtable(glob, rte);
306  }
307 
308  /*
309  * If there are any dead subqueries, they are not referenced in the Plan
310  * tree, so we must add RTEs contained in them to the flattened rtable
311  * separately. (If we failed to do this, the executor would not perform
312  * expected permission checks for tables mentioned in such subqueries.)
313  *
314  * Note: this pass over the rangetable can't be combined with the previous
315  * one, because that would mess up the numbering of the live RTEs in the
316  * flattened rangetable.
317  */
318  rti = 1;
319  foreach(lc, root->parse->rtable)
320  {
321  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
322 
323  /*
324  * We should ignore inheritance-parent RTEs: their contents have been
325  * pulled up into our rangetable already. Also ignore any subquery
326  * RTEs without matching RelOptInfos, as they likewise have been
327  * pulled up.
328  */
329  if (rte->rtekind == RTE_SUBQUERY && !rte->inh &&
330  rti < root->simple_rel_array_size)
331  {
332  RelOptInfo *rel = root->simple_rel_array[rti];
333 
334  if (rel != NULL)
335  {
336  Assert(rel->relid == rti); /* sanity check on array */
337 
338  /*
339  * The subquery might never have been planned at all, if it
340  * was excluded on the basis of self-contradictory constraints
341  * in our query level. In this case apply
342  * flatten_unplanned_rtes.
343  *
344  * If it was planned but the result rel is dummy, we assume
345  * that it has been omitted from our plan tree (see
346  * set_subquery_pathlist), and recurse to pull up its RTEs.
347  *
348  * Otherwise, it should be represented by a SubqueryScan node
349  * somewhere in our plan tree, and we'll pull up its RTEs when
350  * we process that plan node.
351  *
352  * However, if we're recursing, then we should pull up RTEs
353  * whether the subquery is dummy or not, because we've found
354  * that some upper query level is treating this one as dummy,
355  * and so we won't scan this level's plan tree at all.
356  */
357  if (rel->subroot == NULL)
358  flatten_unplanned_rtes(glob, rte);
359  else if (recursing ||
361  UPPERREL_FINAL, NULL)))
362  add_rtes_to_flat_rtable(rel->subroot, true);
363  }
364  }
365  rti++;
366  }
367 }
368 
369 /*
370  * Extract RangeTblEntries from a subquery that was never planned at all
371  */
372 static void
374 {
375  /* Use query_tree_walker to find all RTEs in the parse tree */
376  (void) query_tree_walker(rte->subquery,
378  (void *) glob,
380 }
381 
382 static bool
384 {
385  if (node == NULL)
386  return false;
387  if (IsA(node, RangeTblEntry))
388  {
389  RangeTblEntry *rte = (RangeTblEntry *) node;
390 
391  /* As above, we need only save relation RTEs */
392  if (rte->rtekind == RTE_RELATION)
393  add_rte_to_flat_rtable(glob, rte);
394  return false;
395  }
396  if (IsA(node, Query))
397  {
398  /* Recurse into subselects */
399  return query_tree_walker((Query *) node,
401  (void *) glob,
403  }
405  (void *) glob);
406 }
407 
408 /*
409  * Add (a copy of) the given RTE to the final rangetable
410  *
411  * In the flat rangetable, we zero out substructure pointers that are not
412  * needed by the executor; this reduces the storage space and copying cost
413  * for cached plans. We keep only the ctename, alias and eref Alias fields,
414  * which are needed by EXPLAIN, and the selectedCols, insertedCols and
415  * updatedCols bitmaps, which are needed for executor-startup permissions
416  * checking and for trigger event checking.
417  */
418 static void
420 {
421  RangeTblEntry *newrte;
422 
423  /* flat copy to duplicate all the scalar fields */
424  newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
425  memcpy(newrte, rte, sizeof(RangeTblEntry));
426 
427  /* zap unneeded sub-structure */
428  newrte->tablesample = NULL;
429  newrte->subquery = NULL;
430  newrte->joinaliasvars = NIL;
431  newrte->joinleftcols = NIL;
432  newrte->joinrightcols = NIL;
433  newrte->functions = NIL;
434  newrte->tablefunc = NULL;
435  newrte->values_lists = NIL;
436  newrte->coltypes = NIL;
437  newrte->coltypmods = NIL;
438  newrte->colcollations = NIL;
439  newrte->securityQuals = NIL;
440 
441  glob->finalrtable = lappend(glob->finalrtable, newrte);
442 
443  /*
444  * Check for RT index overflow; it's very unlikely, but if it did happen,
445  * the executor would get confused by varnos that match the special varno
446  * values.
447  */
449  ereport(ERROR,
450  (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
451  errmsg("too many range table entries")));
452 
453  /*
454  * If it's a plain relation RTE, add the table to relationOids.
455  *
456  * We do this even though the RTE might be unreferenced in the plan tree;
457  * this would correspond to cases such as views that were expanded, child
458  * tables that were eliminated by constraint exclusion, etc. Schema
459  * invalidation on such a rel must still force rebuilding of the plan.
460  *
461  * Note we don't bother to avoid making duplicate list entries. We could,
462  * but it would probably cost more cycles than it would save.
463  */
464  if (newrte->rtekind == RTE_RELATION)
465  glob->relationOids = lappend_oid(glob->relationOids, newrte->relid);
466 }
467 
468 /*
469  * set_plan_refs: recurse through the Plan nodes of a single subquery level
470  */
471 static Plan *
472 set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
473 {
474  ListCell *l;
475 
476  if (plan == NULL)
477  return NULL;
478 
479  /* Assign this node a unique ID. */
480  plan->plan_node_id = root->glob->lastPlanNodeId++;
481 
482  /*
483  * Plan-type-specific fixes
484  */
485  switch (nodeTag(plan))
486  {
487  case T_SeqScan:
488  {
489  SeqScan *splan = (SeqScan *) plan;
490 
491  splan->scanrelid += rtoffset;
492  splan->plan.targetlist =
493  fix_scan_list(root, splan->plan.targetlist, rtoffset);
494  splan->plan.qual =
495  fix_scan_list(root, splan->plan.qual, rtoffset);
496  }
497  break;
498  case T_SampleScan:
499  {
500  SampleScan *splan = (SampleScan *) plan;
501 
502  splan->scan.scanrelid += rtoffset;
503  splan->scan.plan.targetlist =
504  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
505  splan->scan.plan.qual =
506  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
507  splan->tablesample = (TableSampleClause *)
508  fix_scan_expr(root, (Node *) splan->tablesample, rtoffset);
509  }
510  break;
511  case T_IndexScan:
512  {
513  IndexScan *splan = (IndexScan *) plan;
514 
515  splan->scan.scanrelid += rtoffset;
516  splan->scan.plan.targetlist =
517  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
518  splan->scan.plan.qual =
519  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
520  splan->indexqual =
521  fix_scan_list(root, splan->indexqual, rtoffset);
522  splan->indexqualorig =
523  fix_scan_list(root, splan->indexqualorig, rtoffset);
524  splan->indexorderby =
525  fix_scan_list(root, splan->indexorderby, rtoffset);
526  splan->indexorderbyorig =
527  fix_scan_list(root, splan->indexorderbyorig, rtoffset);
528  }
529  break;
530  case T_IndexOnlyScan:
531  {
532  IndexOnlyScan *splan = (IndexOnlyScan *) plan;
533 
534  return set_indexonlyscan_references(root, splan, rtoffset);
535  }
536  break;
537  case T_BitmapIndexScan:
538  {
540 
541  splan->scan.scanrelid += rtoffset;
542  /* no need to fix targetlist and qual */
543  Assert(splan->scan.plan.targetlist == NIL);
544  Assert(splan->scan.plan.qual == NIL);
545  splan->indexqual =
546  fix_scan_list(root, splan->indexqual, rtoffset);
547  splan->indexqualorig =
548  fix_scan_list(root, splan->indexqualorig, rtoffset);
549  }
550  break;
551  case T_BitmapHeapScan:
552  {
553  BitmapHeapScan *splan = (BitmapHeapScan *) plan;
554 
555  splan->scan.scanrelid += rtoffset;
556  splan->scan.plan.targetlist =
557  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
558  splan->scan.plan.qual =
559  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
560  splan->bitmapqualorig =
561  fix_scan_list(root, splan->bitmapqualorig, rtoffset);
562  }
563  break;
564  case T_TidScan:
565  {
566  TidScan *splan = (TidScan *) plan;
567 
568  splan->scan.scanrelid += rtoffset;
569  splan->scan.plan.targetlist =
570  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
571  splan->scan.plan.qual =
572  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
573  splan->tidquals =
574  fix_scan_list(root, splan->tidquals, rtoffset);
575  }
576  break;
577  case T_SubqueryScan:
578  /* Needs special treatment, see comments below */
579  return set_subqueryscan_references(root,
580  (SubqueryScan *) plan,
581  rtoffset);
582  case T_FunctionScan:
583  {
584  FunctionScan *splan = (FunctionScan *) plan;
585 
586  splan->scan.scanrelid += rtoffset;
587  splan->scan.plan.targetlist =
588  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
589  splan->scan.plan.qual =
590  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
591  splan->functions =
592  fix_scan_list(root, splan->functions, rtoffset);
593  }
594  break;
595  case T_TableFuncScan:
596  {
597  TableFuncScan *splan = (TableFuncScan *) plan;
598 
599  splan->scan.scanrelid += rtoffset;
600  splan->scan.plan.targetlist =
601  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
602  splan->scan.plan.qual =
603  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
604  splan->tablefunc = (TableFunc *)
605  fix_scan_expr(root, (Node *) splan->tablefunc, rtoffset);
606  }
607  break;
608  case T_ValuesScan:
609  {
610  ValuesScan *splan = (ValuesScan *) plan;
611 
612  splan->scan.scanrelid += rtoffset;
613  splan->scan.plan.targetlist =
614  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
615  splan->scan.plan.qual =
616  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
617  splan->values_lists =
618  fix_scan_list(root, splan->values_lists, rtoffset);
619  }
620  break;
621  case T_CteScan:
622  {
623  CteScan *splan = (CteScan *) plan;
624 
625  splan->scan.scanrelid += rtoffset;
626  splan->scan.plan.targetlist =
627  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
628  splan->scan.plan.qual =
629  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
630  }
631  break;
633  {
635 
636  splan->scan.scanrelid += rtoffset;
637  splan->scan.plan.targetlist =
638  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
639  splan->scan.plan.qual =
640  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
641  }
642  break;
643  case T_WorkTableScan:
644  {
645  WorkTableScan *splan = (WorkTableScan *) plan;
646 
647  splan->scan.scanrelid += rtoffset;
648  splan->scan.plan.targetlist =
649  fix_scan_list(root, splan->scan.plan.targetlist, rtoffset);
650  splan->scan.plan.qual =
651  fix_scan_list(root, splan->scan.plan.qual, rtoffset);
652  }
653  break;
654  case T_ForeignScan:
655  set_foreignscan_references(root, (ForeignScan *) plan, rtoffset);
656  break;
657  case T_CustomScan:
658  set_customscan_references(root, (CustomScan *) plan, rtoffset);
659  break;
660 
661  case T_NestLoop:
662  case T_MergeJoin:
663  case T_HashJoin:
664  set_join_references(root, (Join *) plan, rtoffset);
665  break;
666 
667  case T_Gather:
668  case T_GatherMerge:
669  {
670  set_upper_references(root, plan, rtoffset);
671  set_param_references(root, plan);
672  }
673  break;
674 
675  case T_Hash:
676  set_hash_references(root, plan, rtoffset);
677  break;
678 
679  case T_Material:
680  case T_Sort:
681  case T_Unique:
682  case T_SetOp:
683 
684  /*
685  * These plan types don't actually bother to evaluate their
686  * targetlists, because they just return their unmodified input
687  * tuples. Even though the targetlist won't be used by the
688  * executor, we fix it up for possible use by EXPLAIN (not to
689  * mention ease of debugging --- wrong varnos are very confusing).
690  */
691  set_dummy_tlist_references(plan, rtoffset);
692 
693  /*
694  * Since these plan types don't check quals either, we should not
695  * find any qual expression attached to them.
696  */
697  Assert(plan->qual == NIL);
698  break;
699  case T_LockRows:
700  {
701  LockRows *splan = (LockRows *) plan;
702 
703  /*
704  * Like the plan types above, LockRows doesn't evaluate its
705  * tlist or quals. But we have to fix up the RT indexes in
706  * its rowmarks.
707  */
708  set_dummy_tlist_references(plan, rtoffset);
709  Assert(splan->plan.qual == NIL);
710 
711  foreach(l, splan->rowMarks)
712  {
713  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
714 
715  rc->rti += rtoffset;
716  rc->prti += rtoffset;
717  }
718  }
719  break;
720  case T_Limit:
721  {
722  Limit *splan = (Limit *) plan;
723 
724  /*
725  * Like the plan types above, Limit doesn't evaluate its tlist
726  * or quals. It does have live expressions for limit/offset,
727  * however; and those cannot contain subplan variable refs, so
728  * fix_scan_expr works for them.
729  */
730  set_dummy_tlist_references(plan, rtoffset);
731  Assert(splan->plan.qual == NIL);
732 
733  splan->limitOffset =
734  fix_scan_expr(root, splan->limitOffset, rtoffset);
735  splan->limitCount =
736  fix_scan_expr(root, splan->limitCount, rtoffset);
737  }
738  break;
739  case T_Agg:
740  {
741  Agg *agg = (Agg *) plan;
742 
743  /*
744  * If this node is combining partial-aggregation results, we
745  * must convert its Aggrefs to contain references to the
746  * partial-aggregate subexpressions that will be available
747  * from the child plan node.
748  */
749  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
750  {
751  plan->targetlist = (List *)
752  convert_combining_aggrefs((Node *) plan->targetlist,
753  NULL);
754  plan->qual = (List *)
755  convert_combining_aggrefs((Node *) plan->qual,
756  NULL);
757  }
758 
759  set_upper_references(root, plan, rtoffset);
760  }
761  break;
762  case T_Group:
763  set_upper_references(root, plan, rtoffset);
764  break;
765  case T_WindowAgg:
766  {
767  WindowAgg *wplan = (WindowAgg *) plan;
768 
769  set_upper_references(root, plan, rtoffset);
770 
771  /*
772  * Like Limit node limit/offset expressions, WindowAgg has
773  * frame offset expressions, which cannot contain subplan
774  * variable refs, so fix_scan_expr works for them.
775  */
776  wplan->startOffset =
777  fix_scan_expr(root, wplan->startOffset, rtoffset);
778  wplan->endOffset =
779  fix_scan_expr(root, wplan->endOffset, rtoffset);
780  }
781  break;
782  case T_Result:
783  {
784  Result *splan = (Result *) plan;
785 
786  /*
787  * Result may or may not have a subplan; if not, it's more
788  * like a scan node than an upper node.
789  */
790  if (splan->plan.lefttree != NULL)
791  set_upper_references(root, plan, rtoffset);
792  else
793  {
794  splan->plan.targetlist =
795  fix_scan_list(root, splan->plan.targetlist, rtoffset);
796  splan->plan.qual =
797  fix_scan_list(root, splan->plan.qual, rtoffset);
798  }
799  /* resconstantqual can't contain any subplan variable refs */
800  splan->resconstantqual =
801  fix_scan_expr(root, splan->resconstantqual, rtoffset);
802  }
803  break;
804  case T_ProjectSet:
805  set_upper_references(root, plan, rtoffset);
806  break;
807  case T_ModifyTable:
808  {
809  ModifyTable *splan = (ModifyTable *) plan;
810 
811  Assert(splan->plan.targetlist == NIL);
812  Assert(splan->plan.qual == NIL);
813 
814  splan->withCheckOptionLists =
815  fix_scan_list(root, splan->withCheckOptionLists, rtoffset);
816 
817  if (splan->returningLists)
818  {
819  List *newRL = NIL;
820  ListCell *lcrl,
821  *lcrr,
822  *lcp;
823 
824  /*
825  * Pass each per-subplan returningList through
826  * set_returning_clause_references().
827  */
829  Assert(list_length(splan->returningLists) == list_length(splan->plans));
830  forthree(lcrl, splan->returningLists,
831  lcrr, splan->resultRelations,
832  lcp, splan->plans)
833  {
834  List *rlist = (List *) lfirst(lcrl);
835  Index resultrel = lfirst_int(lcrr);
836  Plan *subplan = (Plan *) lfirst(lcp);
837 
838  rlist = set_returning_clause_references(root,
839  rlist,
840  subplan,
841  resultrel,
842  rtoffset);
843  newRL = lappend(newRL, rlist);
844  }
845  splan->returningLists = newRL;
846 
847  /*
848  * Set up the visible plan targetlist as being the same as
849  * the first RETURNING list. This is for the use of
850  * EXPLAIN; the executor won't pay any attention to the
851  * targetlist. We postpone this step until here so that
852  * we don't have to do set_returning_clause_references()
853  * twice on identical targetlists.
854  */
855  splan->plan.targetlist = copyObject(linitial(newRL));
856  }
857 
858  /*
859  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
860  * join', where the inner side is the EXCLUDED tuple.
861  * Therefore use fix_join_expr to setup the relevant variables
862  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
863  * those are already used by RETURNING and it seems better to
864  * be non-conflicting.
865  */
866  if (splan->onConflictSet)
867  {
868  indexed_tlist *itlist;
869 
870  itlist = build_tlist_index(splan->exclRelTlist);
871 
872  splan->onConflictSet =
873  fix_join_expr(root, splan->onConflictSet,
874  NULL, itlist,
876  rtoffset);
877 
878  splan->onConflictWhere = (Node *)
879  fix_join_expr(root, (List *) splan->onConflictWhere,
880  NULL, itlist,
882  rtoffset);
883 
884  pfree(itlist);
885 
886  splan->exclRelTlist =
887  fix_scan_list(root, splan->exclRelTlist, rtoffset);
888  }
889 
890  splan->nominalRelation += rtoffset;
891  if (splan->rootRelation)
892  splan->rootRelation += rtoffset;
893  splan->exclRelRTI += rtoffset;
894 
895  foreach(l, splan->resultRelations)
896  {
897  lfirst_int(l) += rtoffset;
898  }
899  foreach(l, splan->rowMarks)
900  {
901  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
902 
903  rc->rti += rtoffset;
904  rc->prti += rtoffset;
905  }
906  foreach(l, splan->plans)
907  {
908  lfirst(l) = set_plan_refs(root,
909  (Plan *) lfirst(l),
910  rtoffset);
911  }
912 
913  /*
914  * Append this ModifyTable node's final result relation RT
915  * index(es) to the global list for the plan, and set its
916  * resultRelIndex to reflect their starting position in the
917  * global list.
918  */
920  root->glob->resultRelations =
922  splan->resultRelations);
923 
924  /*
925  * If the main target relation is a partitioned table, also
926  * add the partition root's RT index to rootResultRelations,
927  * and remember its index in that list in rootResultRelIndex.
928  */
929  if (splan->rootRelation)
930  {
931  splan->rootResultRelIndex =
933  root->glob->rootResultRelations =
935  splan->rootRelation);
936  }
937  }
938  break;
939  case T_Append:
940  /* Needs special treatment, see comments below */
941  return set_append_references(root,
942  (Append *) plan,
943  rtoffset);
944  case T_MergeAppend:
945  /* Needs special treatment, see comments below */
946  return set_mergeappend_references(root,
947  (MergeAppend *) plan,
948  rtoffset);
949  case T_RecursiveUnion:
950  /* This doesn't evaluate targetlist or check quals either */
951  set_dummy_tlist_references(plan, rtoffset);
952  Assert(plan->qual == NIL);
953  break;
954  case T_BitmapAnd:
955  {
956  BitmapAnd *splan = (BitmapAnd *) plan;
957 
958  /* BitmapAnd works like Append, but has no tlist */
959  Assert(splan->plan.targetlist == NIL);
960  Assert(splan->plan.qual == NIL);
961  foreach(l, splan->bitmapplans)
962  {
963  lfirst(l) = set_plan_refs(root,
964  (Plan *) lfirst(l),
965  rtoffset);
966  }
967  }
968  break;
969  case T_BitmapOr:
970  {
971  BitmapOr *splan = (BitmapOr *) plan;
972 
973  /* BitmapOr works like Append, but has no tlist */
974  Assert(splan->plan.targetlist == NIL);
975  Assert(splan->plan.qual == NIL);
976  foreach(l, splan->bitmapplans)
977  {
978  lfirst(l) = set_plan_refs(root,
979  (Plan *) lfirst(l),
980  rtoffset);
981  }
982  }
983  break;
984  default:
985  elog(ERROR, "unrecognized node type: %d",
986  (int) nodeTag(plan));
987  break;
988  }
989 
990  /*
991  * Now recurse into child plans, if any
992  *
993  * NOTE: it is essential that we recurse into child plans AFTER we set
994  * subplan references in this plan's tlist and quals. If we did the
995  * reference-adjustments bottom-up, then we would fail to match this
996  * plan's var nodes against the already-modified nodes of the children.
997  */
998  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
999  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1000 
1001  return plan;
1002 }
1003 
1004 /*
1005  * set_indexonlyscan_references
1006  * Do set_plan_references processing on an IndexOnlyScan
1007  *
1008  * This is unlike the handling of a plain IndexScan because we have to
1009  * convert Vars referencing the heap into Vars referencing the index.
1010  * We can use the fix_upper_expr machinery for that, by working from a
1011  * targetlist describing the index columns.
1012  */
1013 static Plan *
1015  IndexOnlyScan *plan,
1016  int rtoffset)
1017 {
1018  indexed_tlist *index_itlist;
1019 
1020  index_itlist = build_tlist_index(plan->indextlist);
1021 
1022  plan->scan.scanrelid += rtoffset;
1023  plan->scan.plan.targetlist = (List *)
1024  fix_upper_expr(root,
1025  (Node *) plan->scan.plan.targetlist,
1026  index_itlist,
1027  INDEX_VAR,
1028  rtoffset);
1029  plan->scan.plan.qual = (List *)
1030  fix_upper_expr(root,
1031  (Node *) plan->scan.plan.qual,
1032  index_itlist,
1033  INDEX_VAR,
1034  rtoffset);
1035  /* indexqual is already transformed to reference index columns */
1036  plan->indexqual = fix_scan_list(root, plan->indexqual, rtoffset);
1037  /* indexorderby is already transformed to reference index columns */
1038  plan->indexorderby = fix_scan_list(root, plan->indexorderby, rtoffset);
1039  /* indextlist must NOT be transformed to reference index columns */
1040  plan->indextlist = fix_scan_list(root, plan->indextlist, rtoffset);
1041 
1042  pfree(index_itlist);
1043 
1044  return (Plan *) plan;
1045 }
1046 
1047 /*
1048  * set_subqueryscan_references
1049  * Do set_plan_references processing on a SubqueryScan
1050  *
1051  * We try to strip out the SubqueryScan entirely; if we can't, we have
1052  * to do the normal processing on it.
1053  */
1054 static Plan *
1056  SubqueryScan *plan,
1057  int rtoffset)
1058 {
1059  RelOptInfo *rel;
1060  Plan *result;
1061 
1062  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1063  rel = find_base_rel(root, plan->scan.scanrelid);
1064 
1065  /* Recursively process the subplan */
1066  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1067 
1068  if (trivial_subqueryscan(plan))
1069  {
1070  /*
1071  * We can omit the SubqueryScan node and just pull up the subplan.
1072  */
1073  result = clean_up_removed_plan_level((Plan *) plan, plan->subplan);
1074  }
1075  else
1076  {
1077  /*
1078  * Keep the SubqueryScan node. We have to do the processing that
1079  * set_plan_references would otherwise have done on it. Notice we do
1080  * not do set_upper_references() here, because a SubqueryScan will
1081  * always have been created with correct references to its subplan's
1082  * outputs to begin with.
1083  */
1084  plan->scan.scanrelid += rtoffset;
1085  plan->scan.plan.targetlist =
1086  fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
1087  plan->scan.plan.qual =
1088  fix_scan_list(root, plan->scan.plan.qual, rtoffset);
1089 
1090  result = (Plan *) plan;
1091  }
1092 
1093  return result;
1094 }
1095 
1096 /*
1097  * trivial_subqueryscan
1098  * Detect whether a SubqueryScan can be deleted from the plan tree.
1099  *
1100  * We can delete it if it has no qual to check and the targetlist just
1101  * regurgitates the output of the child plan.
1102  */
1103 static bool
1105 {
1106  int attrno;
1107  ListCell *lp,
1108  *lc;
1109 
1110  if (plan->scan.plan.qual != NIL)
1111  return false;
1112 
1113  if (list_length(plan->scan.plan.targetlist) !=
1114  list_length(plan->subplan->targetlist))
1115  return false; /* tlists not same length */
1116 
1117  attrno = 1;
1118  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1119  {
1120  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1121  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1122 
1123  if (ptle->resjunk != ctle->resjunk)
1124  return false; /* tlist doesn't match junk status */
1125 
1126  /*
1127  * We accept either a Var referencing the corresponding element of the
1128  * subplan tlist, or a Const equaling the subplan element. See
1129  * generate_setop_tlist() for motivation.
1130  */
1131  if (ptle->expr && IsA(ptle->expr, Var))
1132  {
1133  Var *var = (Var *) ptle->expr;
1134 
1135  Assert(var->varno == plan->scan.scanrelid);
1136  Assert(var->varlevelsup == 0);
1137  if (var->varattno != attrno)
1138  return false; /* out of order */
1139  }
1140  else if (ptle->expr && IsA(ptle->expr, Const))
1141  {
1142  if (!equal(ptle->expr, ctle->expr))
1143  return false;
1144  }
1145  else
1146  return false;
1147 
1148  attrno++;
1149  }
1150 
1151  return true;
1152 }
1153 
1154 /*
1155  * clean_up_removed_plan_level
1156  * Do necessary cleanup when we strip out a SubqueryScan, Append, etc
1157  *
1158  * We are dropping the "parent" plan in favor of returning just its "child".
1159  * A few small tweaks are needed.
1160  */
1161 static Plan *
1163 {
1164  /* We have to be sure we don't lose any initplans */
1165  child->initPlan = list_concat(parent->initPlan,
1166  child->initPlan);
1167 
1168  /*
1169  * We also have to transfer the parent's column labeling info into the
1170  * child, else columns sent to client will be improperly labeled if this
1171  * is the topmost plan level. resjunk and so on may be important too.
1172  */
1173  apply_tlist_labeling(child->targetlist, parent->targetlist);
1174 
1175  return child;
1176 }
1177 
1178 /*
1179  * set_foreignscan_references
1180  * Do set_plan_references processing on a ForeignScan
1181  */
1182 static void
1184  ForeignScan *fscan,
1185  int rtoffset)
1186 {
1187  /* Adjust scanrelid if it's valid */
1188  if (fscan->scan.scanrelid > 0)
1189  fscan->scan.scanrelid += rtoffset;
1190 
1191  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1192  {
1193  /*
1194  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1195  * foreign scan tuple
1196  */
1198 
1199  fscan->scan.plan.targetlist = (List *)
1200  fix_upper_expr(root,
1201  (Node *) fscan->scan.plan.targetlist,
1202  itlist,
1203  INDEX_VAR,
1204  rtoffset);
1205  fscan->scan.plan.qual = (List *)
1206  fix_upper_expr(root,
1207  (Node *) fscan->scan.plan.qual,
1208  itlist,
1209  INDEX_VAR,
1210  rtoffset);
1211  fscan->fdw_exprs = (List *)
1212  fix_upper_expr(root,
1213  (Node *) fscan->fdw_exprs,
1214  itlist,
1215  INDEX_VAR,
1216  rtoffset);
1217  fscan->fdw_recheck_quals = (List *)
1218  fix_upper_expr(root,
1219  (Node *) fscan->fdw_recheck_quals,
1220  itlist,
1221  INDEX_VAR,
1222  rtoffset);
1223  pfree(itlist);
1224  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1225  fscan->fdw_scan_tlist =
1226  fix_scan_list(root, fscan->fdw_scan_tlist, rtoffset);
1227  }
1228  else
1229  {
1230  /*
1231  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1232  * way
1233  */
1234  fscan->scan.plan.targetlist =
1235  fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset);
1236  fscan->scan.plan.qual =
1237  fix_scan_list(root, fscan->scan.plan.qual, rtoffset);
1238  fscan->fdw_exprs =
1239  fix_scan_list(root, fscan->fdw_exprs, rtoffset);
1240  fscan->fdw_recheck_quals =
1241  fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
1242  }
1243 
1244  fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
1245 }
1246 
1247 /*
1248  * set_customscan_references
1249  * Do set_plan_references processing on a CustomScan
1250  */
1251 static void
1253  CustomScan *cscan,
1254  int rtoffset)
1255 {
1256  ListCell *lc;
1257 
1258  /* Adjust scanrelid if it's valid */
1259  if (cscan->scan.scanrelid > 0)
1260  cscan->scan.scanrelid += rtoffset;
1261 
1262  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1263  {
1264  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1266 
1267  cscan->scan.plan.targetlist = (List *)
1268  fix_upper_expr(root,
1269  (Node *) cscan->scan.plan.targetlist,
1270  itlist,
1271  INDEX_VAR,
1272  rtoffset);
1273  cscan->scan.plan.qual = (List *)
1274  fix_upper_expr(root,
1275  (Node *) cscan->scan.plan.qual,
1276  itlist,
1277  INDEX_VAR,
1278  rtoffset);
1279  cscan->custom_exprs = (List *)
1280  fix_upper_expr(root,
1281  (Node *) cscan->custom_exprs,
1282  itlist,
1283  INDEX_VAR,
1284  rtoffset);
1285  pfree(itlist);
1286  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1287  cscan->custom_scan_tlist =
1288  fix_scan_list(root, cscan->custom_scan_tlist, rtoffset);
1289  }
1290  else
1291  {
1292  /* Adjust tlist, qual, custom_exprs in the standard way */
1293  cscan->scan.plan.targetlist =
1294  fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
1295  cscan->scan.plan.qual =
1296  fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
1297  cscan->custom_exprs =
1298  fix_scan_list(root, cscan->custom_exprs, rtoffset);
1299  }
1300 
1301  /* Adjust child plan-nodes recursively, if needed */
1302  foreach(lc, cscan->custom_plans)
1303  {
1304  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1305  }
1306 
1307  cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
1308 }
1309 
1310 /*
1311  * set_append_references
1312  * Do set_plan_references processing on an Append
1313  *
1314  * We try to strip out the Append entirely; if we can't, we have
1315  * to do the normal processing on it.
1316  */
1317 static Plan *
1319  Append *aplan,
1320  int rtoffset)
1321 {
1322  ListCell *l;
1323 
1324  /*
1325  * Append, like Sort et al, doesn't actually evaluate its targetlist or
1326  * check quals. If it's got exactly one child plan, then it's not doing
1327  * anything useful at all, and we can strip it out.
1328  */
1329  Assert(aplan->plan.qual == NIL);
1330 
1331  /* First, we gotta recurse on the children */
1332  foreach(l, aplan->appendplans)
1333  {
1334  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1335  }
1336 
1337  /* Now, if there's just one, forget the Append and return that child */
1338  if (list_length(aplan->appendplans) == 1)
1339  return clean_up_removed_plan_level((Plan *) aplan,
1340  (Plan *) linitial(aplan->appendplans));
1341 
1342  /*
1343  * Otherwise, clean up the Append as needed. It's okay to do this after
1344  * recursing to the children, because set_dummy_tlist_references doesn't
1345  * look at those.
1346  */
1347  set_dummy_tlist_references((Plan *) aplan, rtoffset);
1348 
1349  aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
1350 
1351  if (aplan->part_prune_info)
1352  {
1353  foreach(l, aplan->part_prune_info->prune_infos)
1354  {
1355  List *prune_infos = lfirst(l);
1356  ListCell *l2;
1357 
1358  foreach(l2, prune_infos)
1359  {
1360  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1361 
1362  pinfo->rtindex += rtoffset;
1363  }
1364  }
1365  }
1366 
1367  /* We don't need to recurse to lefttree or righttree ... */
1368  Assert(aplan->plan.lefttree == NULL);
1369  Assert(aplan->plan.righttree == NULL);
1370 
1371  return (Plan *) aplan;
1372 }
1373 
1374 /*
1375  * set_mergeappend_references
1376  * Do set_plan_references processing on a MergeAppend
1377  *
1378  * We try to strip out the MergeAppend entirely; if we can't, we have
1379  * to do the normal processing on it.
1380  */
1381 static Plan *
1383  MergeAppend *mplan,
1384  int rtoffset)
1385 {
1386  ListCell *l;
1387 
1388  /*
1389  * MergeAppend, like Sort et al, doesn't actually evaluate its targetlist
1390  * or check quals. If it's got exactly one child plan, then it's not
1391  * doing anything useful at all, and we can strip it out.
1392  */
1393  Assert(mplan->plan.qual == NIL);
1394 
1395  /* First, we gotta recurse on the children */
1396  foreach(l, mplan->mergeplans)
1397  {
1398  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1399  }
1400 
1401  /* Now, if there's just one, forget the MergeAppend and return that child */
1402  if (list_length(mplan->mergeplans) == 1)
1403  return clean_up_removed_plan_level((Plan *) mplan,
1404  (Plan *) linitial(mplan->mergeplans));
1405 
1406  /*
1407  * Otherwise, clean up the MergeAppend as needed. It's okay to do this
1408  * after recursing to the children, because set_dummy_tlist_references
1409  * doesn't look at those.
1410  */
1411  set_dummy_tlist_references((Plan *) mplan, rtoffset);
1412 
1413  mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
1414 
1415  if (mplan->part_prune_info)
1416  {
1417  foreach(l, mplan->part_prune_info->prune_infos)
1418  {
1419  List *prune_infos = lfirst(l);
1420  ListCell *l2;
1421 
1422  foreach(l2, prune_infos)
1423  {
1424  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1425 
1426  pinfo->rtindex += rtoffset;
1427  }
1428  }
1429  }
1430 
1431  /* We don't need to recurse to lefttree or righttree ... */
1432  Assert(mplan->plan.lefttree == NULL);
1433  Assert(mplan->plan.righttree == NULL);
1434 
1435  return (Plan *) mplan;
1436 }
1437 
1438 /*
1439  * set_hash_references
1440  * Do set_plan_references processing on a Hash node
1441  */
1442 static void
1443 set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
1444 {
1445  Hash *hplan = (Hash *) plan;
1446  Plan *outer_plan = plan->lefttree;
1447  indexed_tlist *outer_itlist;
1448 
1449  /*
1450  * Hash's hashkeys are used when feeding tuples into the hashtable,
1451  * therefore have them reference Hash's outer plan (which itself is the
1452  * inner plan of the HashJoin).
1453  */
1454  outer_itlist = build_tlist_index(outer_plan->targetlist);
1455  hplan->hashkeys = (List *)
1456  fix_upper_expr(root,
1457  (Node *) hplan->hashkeys,
1458  outer_itlist,
1459  OUTER_VAR,
1460  rtoffset);
1461 
1462  /* Hash doesn't project */
1463  set_dummy_tlist_references(plan, rtoffset);
1464 
1465  /* Hash nodes don't have their own quals */
1466  Assert(plan->qual == NIL);
1467 }
1468 
1469 /*
1470  * offset_relid_set
1471  * Apply rtoffset to the members of a Relids set.
1472  */
1473 static Relids
1474 offset_relid_set(Relids relids, int rtoffset)
1475 {
1476  Relids result = NULL;
1477  int rtindex;
1478 
1479  /* If there's no offset to apply, we needn't recompute the value */
1480  if (rtoffset == 0)
1481  return relids;
1482  rtindex = -1;
1483  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
1484  result = bms_add_member(result, rtindex + rtoffset);
1485  return result;
1486 }
1487 
1488 /*
1489  * copyVar
1490  * Copy a Var node.
1491  *
1492  * fix_scan_expr and friends do this enough times that it's worth having
1493  * a bespoke routine instead of using the generic copyObject() function.
1494  */
1495 static inline Var *
1497 {
1498  Var *newvar = (Var *) palloc(sizeof(Var));
1499 
1500  *newvar = *var;
1501  return newvar;
1502 }
1503 
1504 /*
1505  * fix_expr_common
1506  * Do generic set_plan_references processing on an expression node
1507  *
1508  * This is code that is common to all variants of expression-fixing.
1509  * We must look up operator opcode info for OpExpr and related nodes,
1510  * add OIDs from regclass Const nodes into root->glob->relationOids, and
1511  * add PlanInvalItems for user-defined functions into root->glob->invalItems.
1512  * We also fill in column index lists for GROUPING() expressions.
1513  *
1514  * We assume it's okay to update opcode info in-place. So this could possibly
1515  * scribble on the planner's input data structures, but it's OK.
1516  */
1517 static void
1519 {
1520  /* We assume callers won't call us on a NULL pointer */
1521  if (IsA(node, Aggref))
1522  {
1524  ((Aggref *) node)->aggfnoid);
1525  }
1526  else if (IsA(node, WindowFunc))
1527  {
1529  ((WindowFunc *) node)->winfnoid);
1530  }
1531  else if (IsA(node, FuncExpr))
1532  {
1534  ((FuncExpr *) node)->funcid);
1535  }
1536  else if (IsA(node, OpExpr))
1537  {
1538  set_opfuncid((OpExpr *) node);
1540  ((OpExpr *) node)->opfuncid);
1541  }
1542  else if (IsA(node, DistinctExpr))
1543  {
1544  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1546  ((DistinctExpr *) node)->opfuncid);
1547  }
1548  else if (IsA(node, NullIfExpr))
1549  {
1550  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1552  ((NullIfExpr *) node)->opfuncid);
1553  }
1554  else if (IsA(node, ScalarArrayOpExpr))
1555  {
1558  ((ScalarArrayOpExpr *) node)->opfuncid);
1559  }
1560  else if (IsA(node, Const))
1561  {
1562  Const *con = (Const *) node;
1563 
1564  /* Check for regclass reference */
1565  if (ISREGCLASSCONST(con))
1566  root->glob->relationOids =
1567  lappend_oid(root->glob->relationOids,
1569  }
1570  else if (IsA(node, GroupingFunc))
1571  {
1572  GroupingFunc *g = (GroupingFunc *) node;
1573  AttrNumber *grouping_map = root->grouping_map;
1574 
1575  /* If there are no grouping sets, we don't need this. */
1576 
1577  Assert(grouping_map || g->cols == NIL);
1578 
1579  if (grouping_map)
1580  {
1581  ListCell *lc;
1582  List *cols = NIL;
1583 
1584  foreach(lc, g->refs)
1585  {
1586  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1587  }
1588 
1589  Assert(!g->cols || equal(cols, g->cols));
1590 
1591  if (!g->cols)
1592  g->cols = cols;
1593  }
1594  }
1595 }
1596 
1597 /*
1598  * fix_param_node
1599  * Do set_plan_references processing on a Param
1600  *
1601  * If it's a PARAM_MULTIEXPR, replace it with the appropriate Param from
1602  * root->multiexpr_params; otherwise no change is needed.
1603  * Just for paranoia's sake, we make a copy of the node in either case.
1604  */
1605 static Node *
1607 {
1608  if (p->paramkind == PARAM_MULTIEXPR)
1609  {
1610  int subqueryid = p->paramid >> 16;
1611  int colno = p->paramid & 0xFFFF;
1612  List *params;
1613 
1614  if (subqueryid <= 0 ||
1615  subqueryid > list_length(root->multiexpr_params))
1616  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1617  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1618  if (colno <= 0 || colno > list_length(params))
1619  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1620  return copyObject(list_nth(params, colno - 1));
1621  }
1622  return (Node *) copyObject(p);
1623 }
1624 
1625 /*
1626  * fix_scan_expr
1627  * Do set_plan_references processing on a scan-level expression
1628  *
1629  * This consists of incrementing all Vars' varnos by rtoffset,
1630  * replacing PARAM_MULTIEXPR Params, expanding PlaceHolderVars,
1631  * replacing Aggref nodes that should be replaced by initplan output Params,
1632  * looking up operator opcode info for OpExpr and related nodes,
1633  * and adding OIDs from regclass Const nodes into root->glob->relationOids.
1634  */
1635 static Node *
1636 fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
1637 {
1638  fix_scan_expr_context context;
1639 
1640  context.root = root;
1641  context.rtoffset = rtoffset;
1642 
1643  if (rtoffset != 0 ||
1644  root->multiexpr_params != NIL ||
1645  root->glob->lastPHId != 0 ||
1646  root->minmax_aggs != NIL)
1647  {
1648  return fix_scan_expr_mutator(node, &context);
1649  }
1650  else
1651  {
1652  /*
1653  * If rtoffset == 0, we don't need to change any Vars, and if there
1654  * are no MULTIEXPR subqueries then we don't need to replace
1655  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1656  * we won't need to remove them, and if there are no minmax Aggrefs we
1657  * won't need to replace them. Then it's OK to just scribble on the
1658  * input node tree instead of copying (since the only change, filling
1659  * in any unset opfuncid fields, is harmless). This saves just enough
1660  * cycles to be noticeable on trivial queries.
1661  */
1662  (void) fix_scan_expr_walker(node, &context);
1663  return node;
1664  }
1665 }
1666 
1667 static Node *
1669 {
1670  if (node == NULL)
1671  return NULL;
1672  if (IsA(node, Var))
1673  {
1674  Var *var = copyVar((Var *) node);
1675 
1676  Assert(var->varlevelsup == 0);
1677 
1678  /*
1679  * We should not see any Vars marked INNER_VAR or OUTER_VAR. But an
1680  * indexqual expression could contain INDEX_VAR Vars.
1681  */
1682  Assert(var->varno != INNER_VAR);
1683  Assert(var->varno != OUTER_VAR);
1684  if (!IS_SPECIAL_VARNO(var->varno))
1685  var->varno += context->rtoffset;
1686  if (var->varnosyn > 0)
1687  var->varnosyn += context->rtoffset;
1688  return (Node *) var;
1689  }
1690  if (IsA(node, Param))
1691  return fix_param_node(context->root, (Param *) node);
1692  if (IsA(node, Aggref))
1693  {
1694  Aggref *aggref = (Aggref *) node;
1695 
1696  /* See if the Aggref should be replaced by a Param */
1697  if (context->root->minmax_aggs != NIL &&
1698  list_length(aggref->args) == 1)
1699  {
1700  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1701  ListCell *lc;
1702 
1703  foreach(lc, context->root->minmax_aggs)
1704  {
1705  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1706 
1707  if (mminfo->aggfnoid == aggref->aggfnoid &&
1708  equal(mminfo->target, curTarget->expr))
1709  return (Node *) copyObject(mminfo->param);
1710  }
1711  }
1712  /* If no match, just fall through to process it normally */
1713  }
1714  if (IsA(node, CurrentOfExpr))
1715  {
1716  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1717 
1718  Assert(cexpr->cvarno != INNER_VAR);
1719  Assert(cexpr->cvarno != OUTER_VAR);
1720  if (!IS_SPECIAL_VARNO(cexpr->cvarno))
1721  cexpr->cvarno += context->rtoffset;
1722  return (Node *) cexpr;
1723  }
1724  if (IsA(node, PlaceHolderVar))
1725  {
1726  /* At scan level, we should always just evaluate the contained expr */
1727  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1728 
1729  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1730  }
1731  fix_expr_common(context->root, node);
1733  (void *) context);
1734 }
1735 
1736 static bool
1738 {
1739  if (node == NULL)
1740  return false;
1741  Assert(!IsA(node, PlaceHolderVar));
1742  fix_expr_common(context->root, node);
1744  (void *) context);
1745 }
1746 
1747 /*
1748  * set_join_references
1749  * Modify the target list and quals of a join node to reference its
1750  * subplans, by setting the varnos to OUTER_VAR or INNER_VAR and setting
1751  * attno values to the result domain number of either the corresponding
1752  * outer or inner join tuple item. Also perform opcode lookup for these
1753  * expressions, and add regclass OIDs to root->glob->relationOids.
1754  */
1755 static void
1756 set_join_references(PlannerInfo *root, Join *join, int rtoffset)
1757 {
1758  Plan *outer_plan = join->plan.lefttree;
1759  Plan *inner_plan = join->plan.righttree;
1760  indexed_tlist *outer_itlist;
1761  indexed_tlist *inner_itlist;
1762 
1763  outer_itlist = build_tlist_index(outer_plan->targetlist);
1764  inner_itlist = build_tlist_index(inner_plan->targetlist);
1765 
1766  /*
1767  * First process the joinquals (including merge or hash clauses). These
1768  * are logically below the join so they can always use all values
1769  * available from the input tlists. It's okay to also handle
1770  * NestLoopParams now, because those couldn't refer to nullable
1771  * subexpressions.
1772  */
1773  join->joinqual = fix_join_expr(root,
1774  join->joinqual,
1775  outer_itlist,
1776  inner_itlist,
1777  (Index) 0,
1778  rtoffset);
1779 
1780  /* Now do join-type-specific stuff */
1781  if (IsA(join, NestLoop))
1782  {
1783  NestLoop *nl = (NestLoop *) join;
1784  ListCell *lc;
1785 
1786  foreach(lc, nl->nestParams)
1787  {
1788  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1789 
1790  nlp->paramval = (Var *) fix_upper_expr(root,
1791  (Node *) nlp->paramval,
1792  outer_itlist,
1793  OUTER_VAR,
1794  rtoffset);
1795  /* Check we replaced any PlaceHolderVar with simple Var */
1796  if (!(IsA(nlp->paramval, Var) &&
1797  nlp->paramval->varno == OUTER_VAR))
1798  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
1799  }
1800  }
1801  else if (IsA(join, MergeJoin))
1802  {
1803  MergeJoin *mj = (MergeJoin *) join;
1804 
1805  mj->mergeclauses = fix_join_expr(root,
1806  mj->mergeclauses,
1807  outer_itlist,
1808  inner_itlist,
1809  (Index) 0,
1810  rtoffset);
1811  }
1812  else if (IsA(join, HashJoin))
1813  {
1814  HashJoin *hj = (HashJoin *) join;
1815 
1816  hj->hashclauses = fix_join_expr(root,
1817  hj->hashclauses,
1818  outer_itlist,
1819  inner_itlist,
1820  (Index) 0,
1821  rtoffset);
1822 
1823  /*
1824  * HashJoin's hashkeys are used to look for matching tuples from its
1825  * outer plan (not the Hash node!) in the hashtable.
1826  */
1827  hj->hashkeys = (List *) fix_upper_expr(root,
1828  (Node *) hj->hashkeys,
1829  outer_itlist,
1830  OUTER_VAR,
1831  rtoffset);
1832  }
1833 
1834  /*
1835  * Now we need to fix up the targetlist and qpqual, which are logically
1836  * above the join. This means they should not re-use any input expression
1837  * that was computed in the nullable side of an outer join. Vars and
1838  * PlaceHolderVars are fine, so we can implement this restriction just by
1839  * clearing has_non_vars in the indexed_tlist structs.
1840  *
1841  * XXX This is a grotty workaround for the fact that we don't clearly
1842  * distinguish between a Var appearing below an outer join and the "same"
1843  * Var appearing above it. If we did, we'd not need to hack the matching
1844  * rules this way.
1845  */
1846  switch (join->jointype)
1847  {
1848  case JOIN_LEFT:
1849  case JOIN_SEMI:
1850  case JOIN_ANTI:
1851  inner_itlist->has_non_vars = false;
1852  break;
1853  case JOIN_RIGHT:
1854  outer_itlist->has_non_vars = false;
1855  break;
1856  case JOIN_FULL:
1857  outer_itlist->has_non_vars = false;
1858  inner_itlist->has_non_vars = false;
1859  break;
1860  default:
1861  break;
1862  }
1863 
1864  join->plan.targetlist = fix_join_expr(root,
1865  join->plan.targetlist,
1866  outer_itlist,
1867  inner_itlist,
1868  (Index) 0,
1869  rtoffset);
1870  join->plan.qual = fix_join_expr(root,
1871  join->plan.qual,
1872  outer_itlist,
1873  inner_itlist,
1874  (Index) 0,
1875  rtoffset);
1876 
1877  pfree(outer_itlist);
1878  pfree(inner_itlist);
1879 }
1880 
1881 /*
1882  * set_upper_references
1883  * Update the targetlist and quals of an upper-level plan node
1884  * to refer to the tuples returned by its lefttree subplan.
1885  * Also perform opcode lookup for these expressions, and
1886  * add regclass OIDs to root->glob->relationOids.
1887  *
1888  * This is used for single-input plan types like Agg, Group, Result.
1889  *
1890  * In most cases, we have to match up individual Vars in the tlist and
1891  * qual expressions with elements of the subplan's tlist (which was
1892  * generated by flattening these selfsame expressions, so it should have all
1893  * the required variables). There is an important exception, however:
1894  * depending on where we are in the plan tree, sort/group columns may have
1895  * been pushed into the subplan tlist unflattened. If these values are also
1896  * needed in the output then we want to reference the subplan tlist element
1897  * rather than recomputing the expression.
1898  */
1899 static void
1900 set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
1901 {
1902  Plan *subplan = plan->lefttree;
1903  indexed_tlist *subplan_itlist;
1904  List *output_targetlist;
1905  ListCell *l;
1906 
1907  subplan_itlist = build_tlist_index(subplan->targetlist);
1908 
1909  output_targetlist = NIL;
1910  foreach(l, plan->targetlist)
1911  {
1912  TargetEntry *tle = (TargetEntry *) lfirst(l);
1913  Node *newexpr;
1914 
1915  /* If it's a sort/group item, first try to match by sortref */
1916  if (tle->ressortgroupref != 0)
1917  {
1918  newexpr = (Node *)
1920  tle->ressortgroupref,
1921  subplan_itlist,
1922  OUTER_VAR);
1923  if (!newexpr)
1924  newexpr = fix_upper_expr(root,
1925  (Node *) tle->expr,
1926  subplan_itlist,
1927  OUTER_VAR,
1928  rtoffset);
1929  }
1930  else
1931  newexpr = fix_upper_expr(root,
1932  (Node *) tle->expr,
1933  subplan_itlist,
1934  OUTER_VAR,
1935  rtoffset);
1936  tle = flatCopyTargetEntry(tle);
1937  tle->expr = (Expr *) newexpr;
1938  output_targetlist = lappend(output_targetlist, tle);
1939  }
1940  plan->targetlist = output_targetlist;
1941 
1942  plan->qual = (List *)
1943  fix_upper_expr(root,
1944  (Node *) plan->qual,
1945  subplan_itlist,
1946  OUTER_VAR,
1947  rtoffset);
1948 
1949  pfree(subplan_itlist);
1950 }
1951 
1952 /*
1953  * set_param_references
1954  * Initialize the initParam list in Gather or Gather merge node such that
1955  * it contains reference of all the params that needs to be evaluated
1956  * before execution of the node. It contains the initplan params that are
1957  * being passed to the plan nodes below it.
1958  */
1959 static void
1961 {
1962  Assert(IsA(plan, Gather) ||IsA(plan, GatherMerge));
1963 
1964  if (plan->lefttree->extParam)
1965  {
1966  PlannerInfo *proot;
1967  Bitmapset *initSetParam = NULL;
1968  ListCell *l;
1969 
1970  for (proot = root; proot != NULL; proot = proot->parent_root)
1971  {
1972  foreach(l, proot->init_plans)
1973  {
1974  SubPlan *initsubplan = (SubPlan *) lfirst(l);
1975  ListCell *l2;
1976 
1977  foreach(l2, initsubplan->setParam)
1978  {
1979  initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
1980  }
1981  }
1982  }
1983 
1984  /*
1985  * Remember the list of all external initplan params that are used by
1986  * the children of Gather or Gather merge node.
1987  */
1988  if (IsA(plan, Gather))
1989  ((Gather *) plan)->initParam =
1990  bms_intersect(plan->lefttree->extParam, initSetParam);
1991  else
1992  ((GatherMerge *) plan)->initParam =
1993  bms_intersect(plan->lefttree->extParam, initSetParam);
1994  }
1995 }
1996 
1997 /*
1998  * Recursively scan an expression tree and convert Aggrefs to the proper
1999  * intermediate form for combining aggregates. This means (1) replacing each
2000  * one's argument list with a single argument that is the original Aggref
2001  * modified to show partial aggregation and (2) changing the upper Aggref to
2002  * show combining aggregation.
2003  *
2004  * After this step, set_upper_references will replace the partial Aggrefs
2005  * with Vars referencing the lower Agg plan node's outputs, so that the final
2006  * form seen by the executor is a combining Aggref with a Var as input.
2007  *
2008  * It's rather messy to postpone this step until setrefs.c; ideally it'd be
2009  * done in createplan.c. The difficulty is that once we modify the Aggref
2010  * expressions, they will no longer be equal() to their original form and
2011  * so cross-plan-node-level matches will fail. So this has to happen after
2012  * the plan node above the Agg has resolved its subplan references.
2013  */
2014 static Node *
2015 convert_combining_aggrefs(Node *node, void *context)
2016 {
2017  if (node == NULL)
2018  return NULL;
2019  if (IsA(node, Aggref))
2020  {
2021  Aggref *orig_agg = (Aggref *) node;
2022  Aggref *child_agg;
2023  Aggref *parent_agg;
2024 
2025  /* Assert we've not chosen to partial-ize any unsupported cases */
2026  Assert(orig_agg->aggorder == NIL);
2027  Assert(orig_agg->aggdistinct == NIL);
2028 
2029  /*
2030  * Since aggregate calls can't be nested, we needn't recurse into the
2031  * arguments. But for safety, flat-copy the Aggref node itself rather
2032  * than modifying it in-place.
2033  */
2034  child_agg = makeNode(Aggref);
2035  memcpy(child_agg, orig_agg, sizeof(Aggref));
2036 
2037  /*
2038  * For the parent Aggref, we want to copy all the fields of the
2039  * original aggregate *except* the args list, which we'll replace
2040  * below, and the aggfilter expression, which should be applied only
2041  * by the child not the parent. Rather than explicitly knowing about
2042  * all the other fields here, we can momentarily modify child_agg to
2043  * provide a suitable source for copyObject.
2044  */
2045  child_agg->args = NIL;
2046  child_agg->aggfilter = NULL;
2047  parent_agg = copyObject(child_agg);
2048  child_agg->args = orig_agg->args;
2049  child_agg->aggfilter = orig_agg->aggfilter;
2050 
2051  /*
2052  * Now, set up child_agg to represent the first phase of partial
2053  * aggregation. For now, assume serialization is required.
2054  */
2056 
2057  /*
2058  * And set up parent_agg to represent the second phase.
2059  */
2060  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
2061  1, NULL, false));
2063 
2064  return (Node *) parent_agg;
2065  }
2067  (void *) context);
2068 }
2069 
2070 /*
2071  * set_dummy_tlist_references
2072  * Replace the targetlist of an upper-level plan node with a simple
2073  * list of OUTER_VAR references to its child.
2074  *
2075  * This is used for plan types like Sort and Append that don't evaluate
2076  * their targetlists. Although the executor doesn't care at all what's in
2077  * the tlist, EXPLAIN needs it to be realistic.
2078  *
2079  * Note: we could almost use set_upper_references() here, but it fails for
2080  * Append for lack of a lefttree subplan. Single-purpose code is faster
2081  * anyway.
2082  */
2083 static void
2084 set_dummy_tlist_references(Plan *plan, int rtoffset)
2085 {
2086  List *output_targetlist;
2087  ListCell *l;
2088 
2089  output_targetlist = NIL;
2090  foreach(l, plan->targetlist)
2091  {
2092  TargetEntry *tle = (TargetEntry *) lfirst(l);
2093  Var *oldvar = (Var *) tle->expr;
2094  Var *newvar;
2095 
2096  /*
2097  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
2098  * as Consts, not Vars referencing Consts. Here, there's no speed
2099  * advantage to be had, but it makes EXPLAIN output look cleaner, and
2100  * again it avoids confusing the executor.
2101  */
2102  if (IsA(oldvar, Const))
2103  {
2104  /* just reuse the existing TLE node */
2105  output_targetlist = lappend(output_targetlist, tle);
2106  continue;
2107  }
2108 
2109  newvar = makeVar(OUTER_VAR,
2110  tle->resno,
2111  exprType((Node *) oldvar),
2112  exprTypmod((Node *) oldvar),
2113  exprCollation((Node *) oldvar),
2114  0);
2115  if (IsA(oldvar, Var) &&
2116  oldvar->varnosyn > 0)
2117  {
2118  newvar->varnosyn = oldvar->varnosyn + rtoffset;
2119  newvar->varattnosyn = oldvar->varattnosyn;
2120  }
2121  else
2122  {
2123  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2124  newvar->varattnosyn = 0;
2125  }
2126 
2127  tle = flatCopyTargetEntry(tle);
2128  tle->expr = (Expr *) newvar;
2129  output_targetlist = lappend(output_targetlist, tle);
2130  }
2131  plan->targetlist = output_targetlist;
2132 
2133  /* We don't touch plan->qual here */
2134 }
2135 
2136 
2137 /*
2138  * build_tlist_index --- build an index data structure for a child tlist
2139  *
2140  * In most cases, subplan tlists will be "flat" tlists with only Vars,
2141  * so we try to optimize that case by extracting information about Vars
2142  * in advance. Matching a parent tlist to a child is still an O(N^2)
2143  * operation, but at least with a much smaller constant factor than plain
2144  * tlist_member() searches.
2145  *
2146  * The result of this function is an indexed_tlist struct to pass to
2147  * search_indexed_tlist_for_var() or search_indexed_tlist_for_non_var().
2148  * When done, the indexed_tlist may be freed with a single pfree().
2149  */
2150 static indexed_tlist *
2152 {
2153  indexed_tlist *itlist;
2154  tlist_vinfo *vinfo;
2155  ListCell *l;
2156 
2157  /* Create data structure with enough slots for all tlist entries */
2158  itlist = (indexed_tlist *)
2160  list_length(tlist) * sizeof(tlist_vinfo));
2161 
2162  itlist->tlist = tlist;
2163  itlist->has_ph_vars = false;
2164  itlist->has_non_vars = false;
2165 
2166  /* Find the Vars and fill in the index array */
2167  vinfo = itlist->vars;
2168  foreach(l, tlist)
2169  {
2170  TargetEntry *tle = (TargetEntry *) lfirst(l);
2171 
2172  if (tle->expr && IsA(tle->expr, Var))
2173  {
2174  Var *var = (Var *) tle->expr;
2175 
2176  vinfo->varno = var->varno;
2177  vinfo->varattno = var->varattno;
2178  vinfo->resno = tle->resno;
2179  vinfo++;
2180  }
2181  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2182  itlist->has_ph_vars = true;
2183  else
2184  itlist->has_non_vars = true;
2185  }
2186 
2187  itlist->num_vars = (vinfo - itlist->vars);
2188 
2189  return itlist;
2190 }
2191 
2192 /*
2193  * build_tlist_index_other_vars --- build a restricted tlist index
2194  *
2195  * This is like build_tlist_index, but we only index tlist entries that
2196  * are Vars belonging to some rel other than the one specified. We will set
2197  * has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
2198  * (so nothing other than Vars and PlaceHolderVars can be matched).
2199  */
2200 static indexed_tlist *
2202 {
2203  indexed_tlist *itlist;
2204  tlist_vinfo *vinfo;
2205  ListCell *l;
2206 
2207  /* Create data structure with enough slots for all tlist entries */
2208  itlist = (indexed_tlist *)
2210  list_length(tlist) * sizeof(tlist_vinfo));
2211 
2212  itlist->tlist = tlist;
2213  itlist->has_ph_vars = false;
2214  itlist->has_non_vars = false;
2215 
2216  /* Find the desired Vars and fill in the index array */
2217  vinfo = itlist->vars;
2218  foreach(l, tlist)
2219  {
2220  TargetEntry *tle = (TargetEntry *) lfirst(l);
2221 
2222  if (tle->expr && IsA(tle->expr, Var))
2223  {
2224  Var *var = (Var *) tle->expr;
2225 
2226  if (var->varno != ignore_rel)
2227  {
2228  vinfo->varno = var->varno;
2229  vinfo->varattno = var->varattno;
2230  vinfo->resno = tle->resno;
2231  vinfo++;
2232  }
2233  }
2234  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2235  itlist->has_ph_vars = true;
2236  }
2237 
2238  itlist->num_vars = (vinfo - itlist->vars);
2239 
2240  return itlist;
2241 }
2242 
2243 /*
2244  * search_indexed_tlist_for_var --- find a Var in an indexed tlist
2245  *
2246  * If a match is found, return a copy of the given Var with suitably
2247  * modified varno/varattno (to wit, newvarno and the resno of the TLE entry).
2248  * Also ensure that varnosyn is incremented by rtoffset.
2249  * If no match, return NULL.
2250  */
2251 static Var *
2253  Index newvarno, int rtoffset)
2254 {
2255  Index varno = var->varno;
2256  AttrNumber varattno = var->varattno;
2257  tlist_vinfo *vinfo;
2258  int i;
2259 
2260  vinfo = itlist->vars;
2261  i = itlist->num_vars;
2262  while (i-- > 0)
2263  {
2264  if (vinfo->varno == varno && vinfo->varattno == varattno)
2265  {
2266  /* Found a match */
2267  Var *newvar = copyVar(var);
2268 
2269  newvar->varno = newvarno;
2270  newvar->varattno = vinfo->resno;
2271  if (newvar->varnosyn > 0)
2272  newvar->varnosyn += rtoffset;
2273  return newvar;
2274  }
2275  vinfo++;
2276  }
2277  return NULL; /* no match */
2278 }
2279 
2280 /*
2281  * search_indexed_tlist_for_non_var --- find a non-Var in an indexed tlist
2282  *
2283  * If a match is found, return a Var constructed to reference the tlist item.
2284  * If no match, return NULL.
2285  *
2286  * NOTE: it is a waste of time to call this unless itlist->has_ph_vars or
2287  * itlist->has_non_vars. Furthermore, set_join_references() relies on being
2288  * able to prevent matching of non-Vars by clearing itlist->has_non_vars,
2289  * so there's a correctness reason not to call it unless that's set.
2290  */
2291 static Var *
2293  indexed_tlist *itlist, Index newvarno)
2294 {
2295  TargetEntry *tle;
2296 
2297  /*
2298  * If it's a simple Const, replacing it with a Var is silly, even if there
2299  * happens to be an identical Const below; a Var is more expensive to
2300  * execute than a Const. What's more, replacing it could confuse some
2301  * places in the executor that expect to see simple Consts for, eg,
2302  * dropped columns.
2303  */
2304  if (IsA(node, Const))
2305  return NULL;
2306 
2307  tle = tlist_member(node, itlist->tlist);
2308  if (tle)
2309  {
2310  /* Found a matching subplan output expression */
2311  Var *newvar;
2312 
2313  newvar = makeVarFromTargetEntry(newvarno, tle);
2314  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2315  newvar->varattnosyn = 0;
2316  return newvar;
2317  }
2318  return NULL; /* no match */
2319 }
2320 
2321 /*
2322  * search_indexed_tlist_for_sortgroupref --- find a sort/group expression
2323  *
2324  * If a match is found, return a Var constructed to reference the tlist item.
2325  * If no match, return NULL.
2326  *
2327  * This is needed to ensure that we select the right subplan TLE in cases
2328  * where there are multiple textually-equal()-but-volatile sort expressions.
2329  * And it's also faster than search_indexed_tlist_for_non_var.
2330  */
2331 static Var *
2333  Index sortgroupref,
2334  indexed_tlist *itlist,
2335  Index newvarno)
2336 {
2337  ListCell *lc;
2338 
2339  foreach(lc, itlist->tlist)
2340  {
2341  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2342 
2343  /* The equal() check should be redundant, but let's be paranoid */
2344  if (tle->ressortgroupref == sortgroupref &&
2345  equal(node, tle->expr))
2346  {
2347  /* Found a matching subplan output expression */
2348  Var *newvar;
2349 
2350  newvar = makeVarFromTargetEntry(newvarno, tle);
2351  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2352  newvar->varattnosyn = 0;
2353  return newvar;
2354  }
2355  }
2356  return NULL; /* no match */
2357 }
2358 
2359 /*
2360  * fix_join_expr
2361  * Create a new set of targetlist entries or join qual clauses by
2362  * changing the varno/varattno values of variables in the clauses
2363  * to reference target list values from the outer and inner join
2364  * relation target lists. Also perform opcode lookup and add
2365  * regclass OIDs to root->glob->relationOids.
2366  *
2367  * This is used in three different scenarios:
2368  * 1) a normal join clause, where all the Vars in the clause *must* be
2369  * replaced by OUTER_VAR or INNER_VAR references. In this case
2370  * acceptable_rel should be zero so that any failure to match a Var will be
2371  * reported as an error.
2372  * 2) RETURNING clauses, which may contain both Vars of the target relation
2373  * and Vars of other relations. In this case we want to replace the
2374  * other-relation Vars by OUTER_VAR references, while leaving target Vars
2375  * alone. Thus inner_itlist = NULL and acceptable_rel = the ID of the
2376  * target relation should be passed.
2377  * 3) ON CONFLICT UPDATE SET/WHERE clauses. Here references to EXCLUDED are
2378  * to be replaced with INNER_VAR references, while leaving target Vars (the
2379  * to-be-updated relation) alone. Correspondingly inner_itlist is to be
2380  * EXCLUDED elements, outer_itlist = NULL and acceptable_rel the target
2381  * relation.
2382  *
2383  * 'clauses' is the targetlist or list of join clauses
2384  * 'outer_itlist' is the indexed target list of the outer join relation,
2385  * or NULL
2386  * 'inner_itlist' is the indexed target list of the inner join relation,
2387  * or NULL
2388  * 'acceptable_rel' is either zero or the rangetable index of a relation
2389  * whose Vars may appear in the clause without provoking an error
2390  * 'rtoffset': how much to increment varnos by
2391  *
2392  * Returns the new expression tree. The original clause structure is
2393  * not modified.
2394  */
2395 static List *
2397  List *clauses,
2398  indexed_tlist *outer_itlist,
2399  indexed_tlist *inner_itlist,
2400  Index acceptable_rel,
2401  int rtoffset)
2402 {
2403  fix_join_expr_context context;
2404 
2405  context.root = root;
2406  context.outer_itlist = outer_itlist;
2407  context.inner_itlist = inner_itlist;
2408  context.acceptable_rel = acceptable_rel;
2409  context.rtoffset = rtoffset;
2410  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2411 }
2412 
2413 static Node *
2415 {
2416  Var *newvar;
2417 
2418  if (node == NULL)
2419  return NULL;
2420  if (IsA(node, Var))
2421  {
2422  Var *var = (Var *) node;
2423 
2424  /* Look for the var in the input tlists, first in the outer */
2425  if (context->outer_itlist)
2426  {
2427  newvar = search_indexed_tlist_for_var(var,
2428  context->outer_itlist,
2429  OUTER_VAR,
2430  context->rtoffset);
2431  if (newvar)
2432  return (Node *) newvar;
2433  }
2434 
2435  /* then in the inner. */
2436  if (context->inner_itlist)
2437  {
2438  newvar = search_indexed_tlist_for_var(var,
2439  context->inner_itlist,
2440  INNER_VAR,
2441  context->rtoffset);
2442  if (newvar)
2443  return (Node *) newvar;
2444  }
2445 
2446  /* If it's for acceptable_rel, adjust and return it */
2447  if (var->varno == context->acceptable_rel)
2448  {
2449  var = copyVar(var);
2450  var->varno += context->rtoffset;
2451  if (var->varnosyn > 0)
2452  var->varnosyn += context->rtoffset;
2453  return (Node *) var;
2454  }
2455 
2456  /* No referent found for Var */
2457  elog(ERROR, "variable not found in subplan target lists");
2458  }
2459  if (IsA(node, PlaceHolderVar))
2460  {
2461  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2462 
2463  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2464  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2465  {
2466  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2467  context->outer_itlist,
2468  OUTER_VAR);
2469  if (newvar)
2470  return (Node *) newvar;
2471  }
2472  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2473  {
2474  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2475  context->inner_itlist,
2476  INNER_VAR);
2477  if (newvar)
2478  return (Node *) newvar;
2479  }
2480 
2481  /* If not supplied by input plans, evaluate the contained expr */
2482  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2483  }
2484  /* Try matching more complex expressions too, if tlists have any */
2485  if (context->outer_itlist && context->outer_itlist->has_non_vars)
2486  {
2487  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2488  context->outer_itlist,
2489  OUTER_VAR);
2490  if (newvar)
2491  return (Node *) newvar;
2492  }
2493  if (context->inner_itlist && context->inner_itlist->has_non_vars)
2494  {
2495  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2496  context->inner_itlist,
2497  INNER_VAR);
2498  if (newvar)
2499  return (Node *) newvar;
2500  }
2501  /* Special cases (apply only AFTER failing to match to lower tlist) */
2502  if (IsA(node, Param))
2503  return fix_param_node(context->root, (Param *) node);
2504  fix_expr_common(context->root, node);
2505  return expression_tree_mutator(node,
2507  (void *) context);
2508 }
2509 
2510 /*
2511  * fix_upper_expr
2512  * Modifies an expression tree so that all Var nodes reference outputs
2513  * of a subplan. Also looks for Aggref nodes that should be replaced
2514  * by initplan output Params. Also performs opcode lookup, and adds
2515  * regclass OIDs to root->glob->relationOids.
2516  *
2517  * This is used to fix up target and qual expressions of non-join upper-level
2518  * plan nodes, as well as index-only scan nodes.
2519  *
2520  * An error is raised if no matching var can be found in the subplan tlist
2521  * --- so this routine should only be applied to nodes whose subplans'
2522  * targetlists were generated by flattening the expressions used in the
2523  * parent node.
2524  *
2525  * If itlist->has_non_vars is true, then we try to match whole subexpressions
2526  * against elements of the subplan tlist, so that we can avoid recomputing
2527  * expressions that were already computed by the subplan. (This is relatively
2528  * expensive, so we don't want to try it in the common case where the
2529  * subplan tlist is just a flattened list of Vars.)
2530  *
2531  * 'node': the tree to be fixed (a target item or qual)
2532  * 'subplan_itlist': indexed target list for subplan (or index)
2533  * 'newvarno': varno to use for Vars referencing tlist elements
2534  * 'rtoffset': how much to increment varnos by
2535  *
2536  * The resulting tree is a copy of the original in which all Var nodes have
2537  * varno = newvarno, varattno = resno of corresponding targetlist element.
2538  * The original tree is not modified.
2539  */
2540 static Node *
2542  Node *node,
2543  indexed_tlist *subplan_itlist,
2544  Index newvarno,
2545  int rtoffset)
2546 {
2547  fix_upper_expr_context context;
2548 
2549  context.root = root;
2550  context.subplan_itlist = subplan_itlist;
2551  context.newvarno = newvarno;
2552  context.rtoffset = rtoffset;
2553  return fix_upper_expr_mutator(node, &context);
2554 }
2555 
2556 static Node *
2558 {
2559  Var *newvar;
2560 
2561  if (node == NULL)
2562  return NULL;
2563  if (IsA(node, Var))
2564  {
2565  Var *var = (Var *) node;
2566 
2567  newvar = search_indexed_tlist_for_var(var,
2568  context->subplan_itlist,
2569  context->newvarno,
2570  context->rtoffset);
2571  if (!newvar)
2572  elog(ERROR, "variable not found in subplan target list");
2573  return (Node *) newvar;
2574  }
2575  if (IsA(node, PlaceHolderVar))
2576  {
2577  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2578 
2579  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2580  if (context->subplan_itlist->has_ph_vars)
2581  {
2582  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2583  context->subplan_itlist,
2584  context->newvarno);
2585  if (newvar)
2586  return (Node *) newvar;
2587  }
2588  /* If not supplied by input plan, evaluate the contained expr */
2589  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2590  }
2591  /* Try matching more complex expressions too, if tlist has any */
2592  if (context->subplan_itlist->has_non_vars)
2593  {
2594  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2595  context->subplan_itlist,
2596  context->newvarno);
2597  if (newvar)
2598  return (Node *) newvar;
2599  }
2600  /* Special cases (apply only AFTER failing to match to lower tlist) */
2601  if (IsA(node, Param))
2602  return fix_param_node(context->root, (Param *) node);
2603  if (IsA(node, Aggref))
2604  {
2605  Aggref *aggref = (Aggref *) node;
2606 
2607  /* See if the Aggref should be replaced by a Param */
2608  if (context->root->minmax_aggs != NIL &&
2609  list_length(aggref->args) == 1)
2610  {
2611  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2612  ListCell *lc;
2613 
2614  foreach(lc, context->root->minmax_aggs)
2615  {
2616  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2617 
2618  if (mminfo->aggfnoid == aggref->aggfnoid &&
2619  equal(mminfo->target, curTarget->expr))
2620  return (Node *) copyObject(mminfo->param);
2621  }
2622  }
2623  /* If no match, just fall through to process it normally */
2624  }
2625  fix_expr_common(context->root, node);
2626  return expression_tree_mutator(node,
2628  (void *) context);
2629 }
2630 
2631 /*
2632  * set_returning_clause_references
2633  * Perform setrefs.c's work on a RETURNING targetlist
2634  *
2635  * If the query involves more than just the result table, we have to
2636  * adjust any Vars that refer to other tables to reference junk tlist
2637  * entries in the top subplan's targetlist. Vars referencing the result
2638  * table should be left alone, however (the executor will evaluate them
2639  * using the actual heap tuple, after firing triggers if any). In the
2640  * adjusted RETURNING list, result-table Vars will have their original
2641  * varno (plus rtoffset), but Vars for other rels will have varno OUTER_VAR.
2642  *
2643  * We also must perform opcode lookup and add regclass OIDs to
2644  * root->glob->relationOids.
2645  *
2646  * 'rlist': the RETURNING targetlist to be fixed
2647  * 'topplan': the top subplan node that will be just below the ModifyTable
2648  * node (note it's not yet passed through set_plan_refs)
2649  * 'resultRelation': RT index of the associated result relation
2650  * 'rtoffset': how much to increment varnos by
2651  *
2652  * Note: the given 'root' is for the parent query level, not the 'topplan'.
2653  * This does not matter currently since we only access the dependency-item
2654  * lists in root->glob, but it would need some hacking if we wanted a root
2655  * that actually matches the subplan.
2656  *
2657  * Note: resultRelation is not yet adjusted by rtoffset.
2658  */
2659 static List *
2661  List *rlist,
2662  Plan *topplan,
2663  Index resultRelation,
2664  int rtoffset)
2665 {
2666  indexed_tlist *itlist;
2667 
2668  /*
2669  * We can perform the desired Var fixup by abusing the fix_join_expr
2670  * machinery that formerly handled inner indexscan fixup. We search the
2671  * top plan's targetlist for Vars of non-result relations, and use
2672  * fix_join_expr to convert RETURNING Vars into references to those tlist
2673  * entries, while leaving result-rel Vars as-is.
2674  *
2675  * PlaceHolderVars will also be sought in the targetlist, but no
2676  * more-complex expressions will be. Note that it is not possible for a
2677  * PlaceHolderVar to refer to the result relation, since the result is
2678  * never below an outer join. If that case could happen, we'd have to be
2679  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2680  * expression instead.
2681  */
2682  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2683 
2684  rlist = fix_join_expr(root,
2685  rlist,
2686  itlist,
2687  NULL,
2688  resultRelation,
2689  rtoffset);
2690 
2691  pfree(itlist);
2692 
2693  return rlist;
2694 }
2695 
2696 
2697 /*****************************************************************************
2698  * QUERY DEPENDENCY MANAGEMENT
2699  *****************************************************************************/
2700 
2701 /*
2702  * record_plan_function_dependency
2703  * Mark the current plan as depending on a particular function.
2704  *
2705  * This is exported so that the function-inlining code can record a
2706  * dependency on a function that it's removed from the plan tree.
2707  */
2708 void
2710 {
2711  /*
2712  * For performance reasons, we don't bother to track built-in functions;
2713  * we just assume they'll never change (or at least not in ways that'd
2714  * invalidate plans using them). For this purpose we can consider a
2715  * built-in function to be one with OID less than FirstBootstrapObjectId.
2716  * Note that the OID generator guarantees never to generate such an OID
2717  * after startup, even at OID wraparound.
2718  */
2719  if (funcid >= (Oid) FirstBootstrapObjectId)
2720  {
2721  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2722 
2723  /*
2724  * It would work to use any syscache on pg_proc, but the easiest is
2725  * PROCOID since we already have the function's OID at hand. Note
2726  * that plancache.c knows we use PROCOID.
2727  */
2728  inval_item->cacheId = PROCOID;
2729  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2730  ObjectIdGetDatum(funcid));
2731 
2732  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2733  }
2734 }
2735 
2736 /*
2737  * record_plan_type_dependency
2738  * Mark the current plan as depending on a particular type.
2739  *
2740  * This is exported so that eval_const_expressions can record a
2741  * dependency on a domain that it's removed a CoerceToDomain node for.
2742  *
2743  * We don't currently need to record dependencies on domains that the
2744  * plan contains CoerceToDomain nodes for, though that might change in
2745  * future. Hence, this isn't actually called in this module, though
2746  * someday fix_expr_common might call it.
2747  */
2748 void
2750 {
2751  /*
2752  * As in record_plan_function_dependency, ignore the possibility that
2753  * someone would change a built-in domain.
2754  */
2755  if (typid >= (Oid) FirstBootstrapObjectId)
2756  {
2757  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2758 
2759  /*
2760  * It would work to use any syscache on pg_type, but the easiest is
2761  * TYPEOID since we already have the type's OID at hand. Note that
2762  * plancache.c knows we use TYPEOID.
2763  */
2764  inval_item->cacheId = TYPEOID;
2765  inval_item->hashValue = GetSysCacheHashValue1(TYPEOID,
2766  ObjectIdGetDatum(typid));
2767 
2768  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2769  }
2770 }
2771 
2772 /*
2773  * extract_query_dependencies
2774  * Given a rewritten, but not yet planned, query or queries
2775  * (i.e. a Query node or list of Query nodes), extract dependencies
2776  * just as set_plan_references would do. Also detect whether any
2777  * rewrite steps were affected by RLS.
2778  *
2779  * This is needed by plancache.c to handle invalidation of cached unplanned
2780  * queries.
2781  *
2782  * Note: this does not go through eval_const_expressions, and hence doesn't
2783  * reflect its additions of inlined functions and elided CoerceToDomain nodes
2784  * to the invalItems list. This is obviously OK for functions, since we'll
2785  * see them in the original query tree anyway. For domains, it's OK because
2786  * we don't care about domains unless they get elided. That is, a plan might
2787  * have domain dependencies that the query tree doesn't.
2788  */
2789 void
2791  List **relationOids,
2792  List **invalItems,
2793  bool *hasRowSecurity)
2794 {
2795  PlannerGlobal glob;
2796  PlannerInfo root;
2797 
2798  /* Make up dummy planner state so we can use this module's machinery */
2799  MemSet(&glob, 0, sizeof(glob));
2800  glob.type = T_PlannerGlobal;
2801  glob.relationOids = NIL;
2802  glob.invalItems = NIL;
2803  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2804  glob.dependsOnRole = false;
2805 
2806  MemSet(&root, 0, sizeof(root));
2807  root.type = T_PlannerInfo;
2808  root.glob = &glob;
2809 
2810  (void) extract_query_dependencies_walker(query, &root);
2811 
2812  *relationOids = glob.relationOids;
2813  *invalItems = glob.invalItems;
2814  *hasRowSecurity = glob.dependsOnRole;
2815 }
2816 
2817 /*
2818  * Tree walker for extract_query_dependencies.
2819  *
2820  * This is exported so that expression_planner_with_deps can call it on
2821  * simple expressions (post-planning, not before planning, in that case).
2822  * In that usage, glob.dependsOnRole isn't meaningful, but the relationOids
2823  * and invalItems lists are added to as needed.
2824  */
2825 bool
2827 {
2828  if (node == NULL)
2829  return false;
2830  Assert(!IsA(node, PlaceHolderVar));
2831  if (IsA(node, Query))
2832  {
2833  Query *query = (Query *) node;
2834  ListCell *lc;
2835 
2836  if (query->commandType == CMD_UTILITY)
2837  {
2838  /*
2839  * Ignore utility statements, except those (such as EXPLAIN) that
2840  * contain a parsed-but-not-planned query.
2841  */
2842  query = UtilityContainsQuery(query->utilityStmt);
2843  if (query == NULL)
2844  return false;
2845  }
2846 
2847  /* Remember if any Query has RLS quals applied by rewriter */
2848  if (query->hasRowSecurity)
2849  context->glob->dependsOnRole = true;
2850 
2851  /* Collect relation OIDs in this Query's rtable */
2852  foreach(lc, query->rtable)
2853  {
2854  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2855 
2856  if (rte->rtekind == RTE_RELATION)
2857  context->glob->relationOids =
2858  lappend_oid(context->glob->relationOids, rte->relid);
2859  else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
2860  OidIsValid(rte->relid))
2861  context->glob->relationOids =
2862  lappend_oid(context->glob->relationOids,
2863  rte->relid);
2864  }
2865 
2866  /* And recurse into the query's subexpressions */
2868  (void *) context, 0);
2869  }
2870  /* Extract function dependencies and check for regclass Consts */
2871  fix_expr_common(context, node);
2873  (void *) context);
2874 }
Datum constvalue
Definition: primnodes.h:214
List * aggdistinct
Definition: primnodes.h:321
List * bitmapplans
Definition: plannodes.h:319
#define NIL
Definition: pg_list.h:65
List * rowMarks
Definition: pathnodes.h:292
Plan plan
Definition: plannodes.h:188
void apply_tlist_labeling(List *dest_tlist, List *src_tlist)
Definition: tlist.c:340
bool query_tree_walker(Query *query, bool(*walker)(), void *context, int flags)
Definition: nodeFuncs.c:2273
List * qual
Definition: plannodes.h:143
Index varno
Definition: setrefs.c:34
#define ISREGCLASSCONST(con)
Definition: setrefs.c:78
Definition: nodes.h:78
Plan plan
Definition: plannodes.h:344
#define IsA(nodeptr, _type_)
Definition: nodes.h:577
Query * parse
Definition: pathnodes.h:179
indexed_tlist * inner_itlist
Definition: setrefs.c:58
List * joinaliasvars
Definition: parsenodes.h:1049
Index varlevelsup
Definition: primnodes.h:191
Node * expression_tree_mutator(Node *node, Node *(*mutator)(), void *context)
Definition: nodeFuncs.c:2516
Plan plan
Definition: plannodes.h:972
#define forboth(cell1, list1, cell2, list2)
Definition: pg_list.h:419
Index nominalRelation
Definition: plannodes.h:223
static Node * fix_param_node(PlannerInfo *root, Param *p)
Definition: setrefs.c:1606
Definition: nodes.h:80
Index scanrelid
Definition: plannodes.h:345
tlist_vinfo vars[FLEXIBLE_ARRAY_MEMBER]
Definition: setrefs.c:45
List * refs
Definition: primnodes.h:361
List * nestParams
Definition: plannodes.h:703
Plan plan
Definition: plannodes.h:958
List * hashkeys
Definition: plannodes.h:751
static void flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:373
bool equal(const void *a, const void *b)
Definition: equalfuncs.c:3027
AttrNumber resno
Definition: setrefs.c:36
PlannerInfo * parent_root
Definition: pathnodes.h:185
List * withCheckOptionLists
Definition: plannodes.h:230
#define QTW_EXAMINE_RTES_BEFORE
Definition: nodeFuncs.h:25
List * functions
Definition: plannodes.h:525
static void set_join_references(PlannerInfo *root, Join *join, int rtoffset)
Definition: setrefs.c:1756
int resultRelIndex
Definition: plannodes.h:227
int32 exprTypmod(const Node *expr)
Definition: nodeFuncs.c:275
#define forthree(cell1, list1, cell2, list2, cell3, list3)
Definition: pg_list.h:464
List * hashclauses
Definition: plannodes.h:743
List * securityQuals
Definition: parsenodes.h:1123
#define DatumGetObjectId(X)
Definition: postgres.h:500
int lastPlanNodeId
Definition: pathnodes.h:137
List * indexqual
Definition: plannodes.h:463
List * fdw_exprs
Definition: plannodes.h:617
List * coltypmods
Definition: parsenodes.h:1100
Param * param
Definition: pathnodes.h:2291
List * tidquals
Definition: plannodes.h:493
int bms_next_member(const Bitmapset *a, int prevbit)
Definition: bitmapset.c:1043
TableFunc * tablefunc
Definition: plannodes.h:546
void mark_partial_aggref(Aggref *agg, AggSplit aggsplit)
Definition: planner.c:5285
int plan_node_id
Definition: plannodes.h:141
List * resultRelations
Definition: pathnodes.h:121
List * indexqualorig
Definition: plannodes.h:407
Var * makeVarFromTargetEntry(Index varno, TargetEntry *tle)
Definition: makefuncs.c:103
struct TableSampleClause * tablesample
Definition: plannodes.h:362
PlannerInfo * root
Definition: setrefs.c:50
ParamKind paramkind
Definition: primnodes.h:262
#define FLEXIBLE_ARRAY_MEMBER
Definition: c.h:276
Definition: nodes.h:526
List * custom_exprs
Definition: plannodes.h:646
List * appendRelations
Definition: pathnodes.h:125
List * list_concat(List *list1, const List *list2)
Definition: list.c:516
Definition: nodes.h:49
int errcode(int sqlerrcode)
Definition: elog.c:610
List * args
Definition: primnodes.h:319
Index prti
Definition: plannodes.h:1063
#define MemSet(start, val, len)
Definition: c.h:971
AttrNumber varattno
Definition: primnodes.h:186
List * values_lists
Definition: plannodes.h:536
static void set_param_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:1960
List * minmax_aggs
Definition: pathnodes.h:329
#define GetSysCacheHashValue1(cacheId, key1)
Definition: syscache.h:201
List * fdw_scan_tlist
Definition: plannodes.h:619
Definition: nodes.h:76
unsigned int Oid
Definition: postgres_ext.h:31
Node * utilityStmt
Definition: parsenodes.h:120
Definition: primnodes.h:181
static Relids offset_relid_set(Relids relids, int rtoffset)
Definition: setrefs.c:1474
AttrNumber * grouping_map
Definition: pathnodes.h:328
Scan scan
Definition: plannodes.h:535
List * custom_plans
Definition: plannodes.h:645
Node * limitOffset
Definition: plannodes.h:973
List * lappend_oid(List *list, Oid datum)
Definition: list.c:358
#define OidIsValid(objectId)
Definition: c.h:644
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:788
List * colcollations
Definition: parsenodes.h:1101
static Plan * set_append_references(PlannerInfo *root, Append *aplan, int rtoffset)
Definition: setrefs.c:1318
List * translated_vars
Definition: pathnodes.h:2219
List * values_lists
Definition: parsenodes.h:1072
List * plans
Definition: plannodes.h:229
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1104
static Plan * set_plan_refs(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:472
static Node * fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
Definition: setrefs.c:2414
static void add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
Definition: setrefs.c:419
List * onConflictSet
Definition: plannodes.h:238
int rootResultRelIndex
Definition: plannodes.h:228
Index rootRelation
Definition: plannodes.h:224
List * resultRelations
Definition: plannodes.h:226
List * mergeclauses
Definition: plannodes.h:728
struct RelOptInfo ** simple_rel_array
Definition: pathnodes.h:203
static void set_foreignscan_references(PlannerInfo *root, ForeignScan *fscan, int rtoffset)
Definition: setrefs.c:1183
static List * fix_join_expr(PlannerInfo *root, List *clauses, indexed_tlist *outer_itlist, indexed_tlist *inner_itlist, Index acceptable_rel, int rtoffset)
Definition: setrefs.c:2396
List * rootResultRelations
Definition: pathnodes.h:123
List * multiexpr_params
Definition: pathnodes.h:263
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2061
List * appendplans
Definition: plannodes.h:255
#define list_make1(x1)
Definition: pg_list.h:227
#define linitial_int(l)
Definition: pg_list.h:196
PlannerInfo * subroot
Definition: pathnodes.h:687
AttrNumber varattno
Definition: setrefs.c:35
Node * startOffset
Definition: plannodes.h:840
JoinType jointype
Definition: plannodes.h:684
bool dependsOnRole
Definition: pathnodes.h:141
Node * resconstantqual
Definition: plannodes.h:189
List * rowMarks
Definition: plannodes.h:234
struct Plan * righttree
Definition: plannodes.h:145
void pfree(void *pointer)
Definition: mcxt.c:1056
#define IS_SPECIAL_VARNO(varno)
Definition: primnodes.h:175
Var * paramval
Definition: plannodes.h:710
bool has_ph_vars
Definition: setrefs.c:43
bool resjunk
Definition: primnodes.h:1414
#define linitial(l)
Definition: pg_list.h:195
Definition: nodes.h:46
List * rtable
Definition: parsenodes.h:137
#define ObjectIdGetDatum(X)
Definition: postgres.h:507
#define ERROR
Definition: elog.h:43
List * indexorderbyorig
Definition: plannodes.h:409
TableFunc * tablefunc
Definition: parsenodes.h:1067
#define lfirst_int(lc)
Definition: pg_list.h:191
static void * list_nth(const List *list, int n)
Definition: pg_list.h:277
Scan scan
Definition: plannodes.h:360
Scan scan
Definition: plannodes.h:555
Node * limitCount
Definition: plannodes.h:974
Scan scan
Definition: plannodes.h:404
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:1390
int num_vars
Definition: setrefs.c:42
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2557
Definition: nodes.h:77
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1177
#define lfirst_node(type, lc)
Definition: pg_list.h:193
static bool flatten_rtes_walker(Node *node, PlannerGlobal *glob)
Definition: setrefs.c:383
static Var * copyVar(Var *var)
Definition: setrefs.c:1496
PlannerGlobal * glob
Definition: pathnodes.h:181
Node * endOffset
Definition: plannodes.h:841
List * aggorder
Definition: primnodes.h:320
AttrNumber resno
Definition: primnodes.h:1408
#define FirstBootstrapObjectId
Definition: transam.h:140
List * fdw_recheck_quals
Definition: plannodes.h:620
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:269
List * joinrightcols
Definition: parsenodes.h:1051
static SPIPlanPtr splan
Definition: regress.c:258
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1252
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:1055
List * indexqual
Definition: plannodes.h:406
static Node * fix_upper_expr(PlannerInfo *root, Node *node, indexed_tlist *subplan_itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2541
List * bitmapqualorig
Definition: plannodes.h:479
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:236
Var * makeVar(Index varno, AttrNumber varattno, Oid vartype, int32 vartypmod, Oid varcollid, Index varlevelsup)
Definition: makefuncs.c:66
PlannerInfo * root
Definition: setrefs.c:56
List * lappend_int(List *list, int datum)
Definition: list.c:340
Index relid
Definition: pathnodes.h:671
List * cols
Definition: primnodes.h:362
Index varnosyn
Definition: primnodes.h:194
List * lappend(List *list, void *datum)
Definition: list.c:322
Plan plan
Definition: plannodes.h:332
Index varno
Definition: primnodes.h:184
Scan scan
Definition: plannodes.h:642
static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1737
List * invalItems
Definition: pathnodes.h:129
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1668
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:1014
List * bitmapplans
Definition: plannodes.h:334
NodeTag type
Definition: pathnodes.h:177
AttrNumber varattnosyn
Definition: primnodes.h:195
List * append_rel_list
Definition: pathnodes.h:290
Index lastPHId
Definition: pathnodes.h:133
static void set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1900
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1162
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:259
List * hashkeys
Definition: plannodes.h:920
bool has_non_vars
Definition: setrefs.c:44
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2709
unsigned int Index
Definition: c.h:475
TargetEntry * tlist_member(Expr *node, List *targetlist)
Definition: tlist.c:73
List * init_plans
Definition: pathnodes.h:259
Definition: nodes.h:83
uint32 hashValue
Definition: plannodes.h:1233
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2292
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:2015
Oid aggfnoid
Definition: primnodes.h:312
#define ereport(elevel,...)
Definition: elog.h:144
List * joinleftcols
Definition: parsenodes.h:1050
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2826
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1518
#define INNER_VAR
Definition: primnodes.h:171
List * indextlist
Definition: plannodes.h:437
CmdType commandType
Definition: parsenodes.h:112
List * indexorderby
Definition: plannodes.h:436
#define makeNode(_type_)
Definition: nodes.h:574
List * indexorderby
Definition: plannodes.h:408
#define Assert(condition)
Definition: c.h:738
#define lfirst(lc)
Definition: pg_list.h:190
Expr * target
Definition: pathnodes.h:2287
static void add_rtes_to_flat_rtable(PlannerInfo *root, bool recursing)
Definition: setrefs.c:287
void extract_query_dependencies(Node *query, List **relationOids, List **invalItems, bool *hasRowSecurity)
Definition: setrefs.c:2790
AggSplit aggsplit
Definition: plannodes.h:810
List * functions
Definition: parsenodes.h:1061
NodeTag type
Definition: pathnodes.h:107
List * custom_scan_tlist
Definition: plannodes.h:648
List * setParam
Definition: primnodes.h:727
static Var * search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno, int rtoffset)
Definition: setrefs.c:2252
Expr * expr
Definition: primnodes.h:1407
List * rowMarks
Definition: plannodes.h:959
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2151
int paramid
Definition: primnodes.h:263
Scan scan
Definition: plannodes.h:492
Oid exprType(const Node *expr)
Definition: nodeFuncs.c:41
bool expression_tree_walker(Node *node, bool(*walker)(), void *context)
Definition: nodeFuncs.c:1839
static int list_length(const List *l)
Definition: pg_list.h:169
List * relationOids
Definition: pathnodes.h:127
Oid exprCollation(const Node *expr)
Definition: nodeFuncs.c:719
List * indexqual
Definition: plannodes.h:435
Expr * aggfilter
Definition: primnodes.h:322
Bitmapset * extParam
Definition: plannodes.h:160
Bitmapset * bms_add_member(Bitmapset *a, int x)
Definition: bitmapset.c:736
struct Plan * lefttree
Definition: plannodes.h:144
Bitmapset * custom_relids
Definition: plannodes.h:649
static indexed_tlist * build_tlist_index_other_vars(List *tlist, Index ignore_rel)
Definition: setrefs.c:2201
List * indexqualorig
Definition: plannodes.h:464
#define nodeTag(nodeptr)
Definition: nodes.h:531
List * targetlist
Definition: plannodes.h:142
RTEKind rtekind
Definition: parsenodes.h:974
Definition: nodes.h:84
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2660
List * mergeplans
Definition: plannodes.h:276
List * finalrtable
Definition: pathnodes.h:117
Query * subquery
Definition: parsenodes.h:1009
void * palloc(Size size)
Definition: mcxt.c:949
int errmsg(const char *fmt,...)
Definition: elog.c:824
void set_opfuncid(OpExpr *opexpr)
Definition: nodeFuncs.c:1618
List * initPlan
Definition: plannodes.h:146
Definition: nodes.h:81
#define elog(elevel,...)
Definition: elog.h:214
int i
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
Definition: setrefs.c:1636
Index ressortgroupref
Definition: primnodes.h:1410
indexed_tlist * outer_itlist
Definition: setrefs.c:57
List * returningLists
Definition: plannodes.h:231
PlannerInfo * root
Definition: setrefs.c:65
Plan plan
Definition: plannodes.h:318
Definition: plannodes.h:806
Index child_relid
Definition: pathnodes.h:2192
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:223
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:363
#define copyObject(obj)
Definition: nodes.h:642
static Var * search_indexed_tlist_for_sortgroupref(Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2332
Index exclRelRTI
Definition: plannodes.h:240
List * coltypes
Definition: parsenodes.h:1099
Index parent_relid
Definition: pathnodes.h:2191
#define INDEX_VAR
Definition: primnodes.h:173
static Plan * set_mergeappend_references(PlannerInfo *root, MergeAppend *mplan, int rtoffset)
Definition: setrefs.c:1382
Definition: regcomp.c:224
List * finalrowmarks
Definition: pathnodes.h:119
Definition: pg_list.h:50
#define fix_scan_list(root, lst, rtoffset)
Definition: setrefs.c:82
struct TableSampleClause * tablesample
Definition: parsenodes.h:1004
int16 AttrNumber
Definition: attnum.h:21
#define OUTER_VAR
Definition: primnodes.h:172
void set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
Definition: nodeFuncs.c:1629
indexed_tlist * subplan_itlist
Definition: setrefs.c:66
List * joinqual
Definition: plannodes.h:686
static void set_dummy_tlist_references(Plan *plan, int rtoffset)
Definition: setrefs.c:2084
List * exclRelTlist
Definition: plannodes.h:241
#define offsetof(type, field)
Definition: c.h:661
static void set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
Definition: setrefs.c:1443
Plan * subplan
Definition: plannodes.h:515
bool hasRowSecurity
Definition: parsenodes.h:133
Plan plan
Definition: plannodes.h:253
Node * onConflictWhere
Definition: plannodes.h:239
void record_plan_type_dependency(PlannerInfo *root, Oid typid)
Definition: setrefs.c:2749
Bitmapset * fs_relids
Definition: plannodes.h:621
Definition: nodes.h:86
Plan plan
Definition: plannodes.h:683
List * tlist
Definition: setrefs.c:41