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_IncrementalSort:
682  case T_Unique:
683  case T_SetOp:
684 
685  /*
686  * These plan types don't actually bother to evaluate their
687  * targetlists, because they just return their unmodified input
688  * tuples. Even though the targetlist won't be used by the
689  * executor, we fix it up for possible use by EXPLAIN (not to
690  * mention ease of debugging --- wrong varnos are very confusing).
691  */
692  set_dummy_tlist_references(plan, rtoffset);
693 
694  /*
695  * Since these plan types don't check quals either, we should not
696  * find any qual expression attached to them.
697  */
698  Assert(plan->qual == NIL);
699  break;
700  case T_LockRows:
701  {
702  LockRows *splan = (LockRows *) plan;
703 
704  /*
705  * Like the plan types above, LockRows doesn't evaluate its
706  * tlist or quals. But we have to fix up the RT indexes in
707  * its rowmarks.
708  */
709  set_dummy_tlist_references(plan, rtoffset);
710  Assert(splan->plan.qual == NIL);
711 
712  foreach(l, splan->rowMarks)
713  {
714  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
715 
716  rc->rti += rtoffset;
717  rc->prti += rtoffset;
718  }
719  }
720  break;
721  case T_Limit:
722  {
723  Limit *splan = (Limit *) plan;
724 
725  /*
726  * Like the plan types above, Limit doesn't evaluate its tlist
727  * or quals. It does have live expressions for limit/offset,
728  * however; and those cannot contain subplan variable refs, so
729  * fix_scan_expr works for them.
730  */
731  set_dummy_tlist_references(plan, rtoffset);
732  Assert(splan->plan.qual == NIL);
733 
734  splan->limitOffset =
735  fix_scan_expr(root, splan->limitOffset, rtoffset);
736  splan->limitCount =
737  fix_scan_expr(root, splan->limitCount, rtoffset);
738  }
739  break;
740  case T_Agg:
741  {
742  Agg *agg = (Agg *) plan;
743 
744  /*
745  * If this node is combining partial-aggregation results, we
746  * must convert its Aggrefs to contain references to the
747  * partial-aggregate subexpressions that will be available
748  * from the child plan node.
749  */
750  if (DO_AGGSPLIT_COMBINE(agg->aggsplit))
751  {
752  plan->targetlist = (List *)
753  convert_combining_aggrefs((Node *) plan->targetlist,
754  NULL);
755  plan->qual = (List *)
756  convert_combining_aggrefs((Node *) plan->qual,
757  NULL);
758  }
759 
760  set_upper_references(root, plan, rtoffset);
761  }
762  break;
763  case T_Group:
764  set_upper_references(root, plan, rtoffset);
765  break;
766  case T_WindowAgg:
767  {
768  WindowAgg *wplan = (WindowAgg *) plan;
769 
770  set_upper_references(root, plan, rtoffset);
771 
772  /*
773  * Like Limit node limit/offset expressions, WindowAgg has
774  * frame offset expressions, which cannot contain subplan
775  * variable refs, so fix_scan_expr works for them.
776  */
777  wplan->startOffset =
778  fix_scan_expr(root, wplan->startOffset, rtoffset);
779  wplan->endOffset =
780  fix_scan_expr(root, wplan->endOffset, rtoffset);
781  }
782  break;
783  case T_Result:
784  {
785  Result *splan = (Result *) plan;
786 
787  /*
788  * Result may or may not have a subplan; if not, it's more
789  * like a scan node than an upper node.
790  */
791  if (splan->plan.lefttree != NULL)
792  set_upper_references(root, plan, rtoffset);
793  else
794  {
795  splan->plan.targetlist =
796  fix_scan_list(root, splan->plan.targetlist, rtoffset);
797  splan->plan.qual =
798  fix_scan_list(root, splan->plan.qual, rtoffset);
799  }
800  /* resconstantqual can't contain any subplan variable refs */
801  splan->resconstantqual =
802  fix_scan_expr(root, splan->resconstantqual, rtoffset);
803  }
804  break;
805  case T_ProjectSet:
806  set_upper_references(root, plan, rtoffset);
807  break;
808  case T_ModifyTable:
809  {
810  ModifyTable *splan = (ModifyTable *) plan;
811 
812  Assert(splan->plan.targetlist == NIL);
813  Assert(splan->plan.qual == NIL);
814 
815  splan->withCheckOptionLists =
816  fix_scan_list(root, splan->withCheckOptionLists, rtoffset);
817 
818  if (splan->returningLists)
819  {
820  List *newRL = NIL;
821  ListCell *lcrl,
822  *lcrr,
823  *lcp;
824 
825  /*
826  * Pass each per-subplan returningList through
827  * set_returning_clause_references().
828  */
830  Assert(list_length(splan->returningLists) == list_length(splan->plans));
831  forthree(lcrl, splan->returningLists,
832  lcrr, splan->resultRelations,
833  lcp, splan->plans)
834  {
835  List *rlist = (List *) lfirst(lcrl);
836  Index resultrel = lfirst_int(lcrr);
837  Plan *subplan = (Plan *) lfirst(lcp);
838 
839  rlist = set_returning_clause_references(root,
840  rlist,
841  subplan,
842  resultrel,
843  rtoffset);
844  newRL = lappend(newRL, rlist);
845  }
846  splan->returningLists = newRL;
847 
848  /*
849  * Set up the visible plan targetlist as being the same as
850  * the first RETURNING list. This is for the use of
851  * EXPLAIN; the executor won't pay any attention to the
852  * targetlist. We postpone this step until here so that
853  * we don't have to do set_returning_clause_references()
854  * twice on identical targetlists.
855  */
856  splan->plan.targetlist = copyObject(linitial(newRL));
857  }
858 
859  /*
860  * We treat ModifyTable with ON CONFLICT as a form of 'pseudo
861  * join', where the inner side is the EXCLUDED tuple.
862  * Therefore use fix_join_expr to setup the relevant variables
863  * to INNER_VAR. We explicitly don't create any OUTER_VARs as
864  * those are already used by RETURNING and it seems better to
865  * be non-conflicting.
866  */
867  if (splan->onConflictSet)
868  {
869  indexed_tlist *itlist;
870 
871  itlist = build_tlist_index(splan->exclRelTlist);
872 
873  splan->onConflictSet =
874  fix_join_expr(root, splan->onConflictSet,
875  NULL, itlist,
877  rtoffset);
878 
879  splan->onConflictWhere = (Node *)
880  fix_join_expr(root, (List *) splan->onConflictWhere,
881  NULL, itlist,
883  rtoffset);
884 
885  pfree(itlist);
886 
887  splan->exclRelTlist =
888  fix_scan_list(root, splan->exclRelTlist, rtoffset);
889  }
890 
891  splan->nominalRelation += rtoffset;
892  if (splan->rootRelation)
893  splan->rootRelation += rtoffset;
894  splan->exclRelRTI += rtoffset;
895 
896  foreach(l, splan->resultRelations)
897  {
898  lfirst_int(l) += rtoffset;
899  }
900  foreach(l, splan->rowMarks)
901  {
902  PlanRowMark *rc = (PlanRowMark *) lfirst(l);
903 
904  rc->rti += rtoffset;
905  rc->prti += rtoffset;
906  }
907  foreach(l, splan->plans)
908  {
909  lfirst(l) = set_plan_refs(root,
910  (Plan *) lfirst(l),
911  rtoffset);
912  }
913 
914  /*
915  * Append this ModifyTable node's final result relation RT
916  * index(es) to the global list for the plan, and set its
917  * resultRelIndex to reflect their starting position in the
918  * global list.
919  */
921  root->glob->resultRelations =
923  splan->resultRelations);
924 
925  /*
926  * If the main target relation is a partitioned table, also
927  * add the partition root's RT index to rootResultRelations,
928  * and remember its index in that list in rootResultRelIndex.
929  */
930  if (splan->rootRelation)
931  {
932  splan->rootResultRelIndex =
934  root->glob->rootResultRelations =
936  splan->rootRelation);
937  }
938  }
939  break;
940  case T_Append:
941  /* Needs special treatment, see comments below */
942  return set_append_references(root,
943  (Append *) plan,
944  rtoffset);
945  case T_MergeAppend:
946  /* Needs special treatment, see comments below */
947  return set_mergeappend_references(root,
948  (MergeAppend *) plan,
949  rtoffset);
950  case T_RecursiveUnion:
951  /* This doesn't evaluate targetlist or check quals either */
952  set_dummy_tlist_references(plan, rtoffset);
953  Assert(plan->qual == NIL);
954  break;
955  case T_BitmapAnd:
956  {
957  BitmapAnd *splan = (BitmapAnd *) plan;
958 
959  /* BitmapAnd works like Append, but has no tlist */
960  Assert(splan->plan.targetlist == NIL);
961  Assert(splan->plan.qual == NIL);
962  foreach(l, splan->bitmapplans)
963  {
964  lfirst(l) = set_plan_refs(root,
965  (Plan *) lfirst(l),
966  rtoffset);
967  }
968  }
969  break;
970  case T_BitmapOr:
971  {
972  BitmapOr *splan = (BitmapOr *) plan;
973 
974  /* BitmapOr works like Append, but has no tlist */
975  Assert(splan->plan.targetlist == NIL);
976  Assert(splan->plan.qual == NIL);
977  foreach(l, splan->bitmapplans)
978  {
979  lfirst(l) = set_plan_refs(root,
980  (Plan *) lfirst(l),
981  rtoffset);
982  }
983  }
984  break;
985  default:
986  elog(ERROR, "unrecognized node type: %d",
987  (int) nodeTag(plan));
988  break;
989  }
990 
991  /*
992  * Now recurse into child plans, if any
993  *
994  * NOTE: it is essential that we recurse into child plans AFTER we set
995  * subplan references in this plan's tlist and quals. If we did the
996  * reference-adjustments bottom-up, then we would fail to match this
997  * plan's var nodes against the already-modified nodes of the children.
998  */
999  plan->lefttree = set_plan_refs(root, plan->lefttree, rtoffset);
1000  plan->righttree = set_plan_refs(root, plan->righttree, rtoffset);
1001 
1002  return plan;
1003 }
1004 
1005 /*
1006  * set_indexonlyscan_references
1007  * Do set_plan_references processing on an IndexOnlyScan
1008  *
1009  * This is unlike the handling of a plain IndexScan because we have to
1010  * convert Vars referencing the heap into Vars referencing the index.
1011  * We can use the fix_upper_expr machinery for that, by working from a
1012  * targetlist describing the index columns.
1013  */
1014 static Plan *
1016  IndexOnlyScan *plan,
1017  int rtoffset)
1018 {
1019  indexed_tlist *index_itlist;
1020 
1021  index_itlist = build_tlist_index(plan->indextlist);
1022 
1023  plan->scan.scanrelid += rtoffset;
1024  plan->scan.plan.targetlist = (List *)
1025  fix_upper_expr(root,
1026  (Node *) plan->scan.plan.targetlist,
1027  index_itlist,
1028  INDEX_VAR,
1029  rtoffset);
1030  plan->scan.plan.qual = (List *)
1031  fix_upper_expr(root,
1032  (Node *) plan->scan.plan.qual,
1033  index_itlist,
1034  INDEX_VAR,
1035  rtoffset);
1036  /* indexqual is already transformed to reference index columns */
1037  plan->indexqual = fix_scan_list(root, plan->indexqual, rtoffset);
1038  /* indexorderby is already transformed to reference index columns */
1039  plan->indexorderby = fix_scan_list(root, plan->indexorderby, rtoffset);
1040  /* indextlist must NOT be transformed to reference index columns */
1041  plan->indextlist = fix_scan_list(root, plan->indextlist, rtoffset);
1042 
1043  pfree(index_itlist);
1044 
1045  return (Plan *) plan;
1046 }
1047 
1048 /*
1049  * set_subqueryscan_references
1050  * Do set_plan_references processing on a SubqueryScan
1051  *
1052  * We try to strip out the SubqueryScan entirely; if we can't, we have
1053  * to do the normal processing on it.
1054  */
1055 static Plan *
1057  SubqueryScan *plan,
1058  int rtoffset)
1059 {
1060  RelOptInfo *rel;
1061  Plan *result;
1062 
1063  /* Need to look up the subquery's RelOptInfo, since we need its subroot */
1064  rel = find_base_rel(root, plan->scan.scanrelid);
1065 
1066  /* Recursively process the subplan */
1067  plan->subplan = set_plan_references(rel->subroot, plan->subplan);
1068 
1069  if (trivial_subqueryscan(plan))
1070  {
1071  /*
1072  * We can omit the SubqueryScan node and just pull up the subplan.
1073  */
1074  result = clean_up_removed_plan_level((Plan *) plan, plan->subplan);
1075  }
1076  else
1077  {
1078  /*
1079  * Keep the SubqueryScan node. We have to do the processing that
1080  * set_plan_references would otherwise have done on it. Notice we do
1081  * not do set_upper_references() here, because a SubqueryScan will
1082  * always have been created with correct references to its subplan's
1083  * outputs to begin with.
1084  */
1085  plan->scan.scanrelid += rtoffset;
1086  plan->scan.plan.targetlist =
1087  fix_scan_list(root, plan->scan.plan.targetlist, rtoffset);
1088  plan->scan.plan.qual =
1089  fix_scan_list(root, plan->scan.plan.qual, rtoffset);
1090 
1091  result = (Plan *) plan;
1092  }
1093 
1094  return result;
1095 }
1096 
1097 /*
1098  * trivial_subqueryscan
1099  * Detect whether a SubqueryScan can be deleted from the plan tree.
1100  *
1101  * We can delete it if it has no qual to check and the targetlist just
1102  * regurgitates the output of the child plan.
1103  */
1104 static bool
1106 {
1107  int attrno;
1108  ListCell *lp,
1109  *lc;
1110 
1111  if (plan->scan.plan.qual != NIL)
1112  return false;
1113 
1114  if (list_length(plan->scan.plan.targetlist) !=
1115  list_length(plan->subplan->targetlist))
1116  return false; /* tlists not same length */
1117 
1118  attrno = 1;
1119  forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
1120  {
1121  TargetEntry *ptle = (TargetEntry *) lfirst(lp);
1122  TargetEntry *ctle = (TargetEntry *) lfirst(lc);
1123 
1124  if (ptle->resjunk != ctle->resjunk)
1125  return false; /* tlist doesn't match junk status */
1126 
1127  /*
1128  * We accept either a Var referencing the corresponding element of the
1129  * subplan tlist, or a Const equaling the subplan element. See
1130  * generate_setop_tlist() for motivation.
1131  */
1132  if (ptle->expr && IsA(ptle->expr, Var))
1133  {
1134  Var *var = (Var *) ptle->expr;
1135 
1136  Assert(var->varno == plan->scan.scanrelid);
1137  Assert(var->varlevelsup == 0);
1138  if (var->varattno != attrno)
1139  return false; /* out of order */
1140  }
1141  else if (ptle->expr && IsA(ptle->expr, Const))
1142  {
1143  if (!equal(ptle->expr, ctle->expr))
1144  return false;
1145  }
1146  else
1147  return false;
1148 
1149  attrno++;
1150  }
1151 
1152  return true;
1153 }
1154 
1155 /*
1156  * clean_up_removed_plan_level
1157  * Do necessary cleanup when we strip out a SubqueryScan, Append, etc
1158  *
1159  * We are dropping the "parent" plan in favor of returning just its "child".
1160  * A few small tweaks are needed.
1161  */
1162 static Plan *
1164 {
1165  /* We have to be sure we don't lose any initplans */
1166  child->initPlan = list_concat(parent->initPlan,
1167  child->initPlan);
1168 
1169  /*
1170  * We also have to transfer the parent's column labeling info into the
1171  * child, else columns sent to client will be improperly labeled if this
1172  * is the topmost plan level. resjunk and so on may be important too.
1173  */
1174  apply_tlist_labeling(child->targetlist, parent->targetlist);
1175 
1176  return child;
1177 }
1178 
1179 /*
1180  * set_foreignscan_references
1181  * Do set_plan_references processing on a ForeignScan
1182  */
1183 static void
1185  ForeignScan *fscan,
1186  int rtoffset)
1187 {
1188  /* Adjust scanrelid if it's valid */
1189  if (fscan->scan.scanrelid > 0)
1190  fscan->scan.scanrelid += rtoffset;
1191 
1192  if (fscan->fdw_scan_tlist != NIL || fscan->scan.scanrelid == 0)
1193  {
1194  /*
1195  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals to reference
1196  * foreign scan tuple
1197  */
1199 
1200  fscan->scan.plan.targetlist = (List *)
1201  fix_upper_expr(root,
1202  (Node *) fscan->scan.plan.targetlist,
1203  itlist,
1204  INDEX_VAR,
1205  rtoffset);
1206  fscan->scan.plan.qual = (List *)
1207  fix_upper_expr(root,
1208  (Node *) fscan->scan.plan.qual,
1209  itlist,
1210  INDEX_VAR,
1211  rtoffset);
1212  fscan->fdw_exprs = (List *)
1213  fix_upper_expr(root,
1214  (Node *) fscan->fdw_exprs,
1215  itlist,
1216  INDEX_VAR,
1217  rtoffset);
1218  fscan->fdw_recheck_quals = (List *)
1219  fix_upper_expr(root,
1220  (Node *) fscan->fdw_recheck_quals,
1221  itlist,
1222  INDEX_VAR,
1223  rtoffset);
1224  pfree(itlist);
1225  /* fdw_scan_tlist itself just needs fix_scan_list() adjustments */
1226  fscan->fdw_scan_tlist =
1227  fix_scan_list(root, fscan->fdw_scan_tlist, rtoffset);
1228  }
1229  else
1230  {
1231  /*
1232  * Adjust tlist, qual, fdw_exprs, fdw_recheck_quals in the standard
1233  * way
1234  */
1235  fscan->scan.plan.targetlist =
1236  fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset);
1237  fscan->scan.plan.qual =
1238  fix_scan_list(root, fscan->scan.plan.qual, rtoffset);
1239  fscan->fdw_exprs =
1240  fix_scan_list(root, fscan->fdw_exprs, rtoffset);
1241  fscan->fdw_recheck_quals =
1242  fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
1243  }
1244 
1245  fscan->fs_relids = offset_relid_set(fscan->fs_relids, rtoffset);
1246 }
1247 
1248 /*
1249  * set_customscan_references
1250  * Do set_plan_references processing on a CustomScan
1251  */
1252 static void
1254  CustomScan *cscan,
1255  int rtoffset)
1256 {
1257  ListCell *lc;
1258 
1259  /* Adjust scanrelid if it's valid */
1260  if (cscan->scan.scanrelid > 0)
1261  cscan->scan.scanrelid += rtoffset;
1262 
1263  if (cscan->custom_scan_tlist != NIL || cscan->scan.scanrelid == 0)
1264  {
1265  /* Adjust tlist, qual, custom_exprs to reference custom scan tuple */
1267 
1268  cscan->scan.plan.targetlist = (List *)
1269  fix_upper_expr(root,
1270  (Node *) cscan->scan.plan.targetlist,
1271  itlist,
1272  INDEX_VAR,
1273  rtoffset);
1274  cscan->scan.plan.qual = (List *)
1275  fix_upper_expr(root,
1276  (Node *) cscan->scan.plan.qual,
1277  itlist,
1278  INDEX_VAR,
1279  rtoffset);
1280  cscan->custom_exprs = (List *)
1281  fix_upper_expr(root,
1282  (Node *) cscan->custom_exprs,
1283  itlist,
1284  INDEX_VAR,
1285  rtoffset);
1286  pfree(itlist);
1287  /* custom_scan_tlist itself just needs fix_scan_list() adjustments */
1288  cscan->custom_scan_tlist =
1289  fix_scan_list(root, cscan->custom_scan_tlist, rtoffset);
1290  }
1291  else
1292  {
1293  /* Adjust tlist, qual, custom_exprs in the standard way */
1294  cscan->scan.plan.targetlist =
1295  fix_scan_list(root, cscan->scan.plan.targetlist, rtoffset);
1296  cscan->scan.plan.qual =
1297  fix_scan_list(root, cscan->scan.plan.qual, rtoffset);
1298  cscan->custom_exprs =
1299  fix_scan_list(root, cscan->custom_exprs, rtoffset);
1300  }
1301 
1302  /* Adjust child plan-nodes recursively, if needed */
1303  foreach(lc, cscan->custom_plans)
1304  {
1305  lfirst(lc) = set_plan_refs(root, (Plan *) lfirst(lc), rtoffset);
1306  }
1307 
1308  cscan->custom_relids = offset_relid_set(cscan->custom_relids, rtoffset);
1309 }
1310 
1311 /*
1312  * set_append_references
1313  * Do set_plan_references processing on an Append
1314  *
1315  * We try to strip out the Append entirely; if we can't, we have
1316  * to do the normal processing on it.
1317  */
1318 static Plan *
1320  Append *aplan,
1321  int rtoffset)
1322 {
1323  ListCell *l;
1324 
1325  /*
1326  * Append, like Sort et al, doesn't actually evaluate its targetlist or
1327  * check quals. If it's got exactly one child plan, then it's not doing
1328  * anything useful at all, and we can strip it out.
1329  */
1330  Assert(aplan->plan.qual == NIL);
1331 
1332  /* First, we gotta recurse on the children */
1333  foreach(l, aplan->appendplans)
1334  {
1335  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1336  }
1337 
1338  /* Now, if there's just one, forget the Append and return that child */
1339  if (list_length(aplan->appendplans) == 1)
1340  return clean_up_removed_plan_level((Plan *) aplan,
1341  (Plan *) linitial(aplan->appendplans));
1342 
1343  /*
1344  * Otherwise, clean up the Append as needed. It's okay to do this after
1345  * recursing to the children, because set_dummy_tlist_references doesn't
1346  * look at those.
1347  */
1348  set_dummy_tlist_references((Plan *) aplan, rtoffset);
1349 
1350  aplan->apprelids = offset_relid_set(aplan->apprelids, rtoffset);
1351 
1352  if (aplan->part_prune_info)
1353  {
1354  foreach(l, aplan->part_prune_info->prune_infos)
1355  {
1356  List *prune_infos = lfirst(l);
1357  ListCell *l2;
1358 
1359  foreach(l2, prune_infos)
1360  {
1361  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1362 
1363  pinfo->rtindex += rtoffset;
1364  }
1365  }
1366  }
1367 
1368  /* We don't need to recurse to lefttree or righttree ... */
1369  Assert(aplan->plan.lefttree == NULL);
1370  Assert(aplan->plan.righttree == NULL);
1371 
1372  return (Plan *) aplan;
1373 }
1374 
1375 /*
1376  * set_mergeappend_references
1377  * Do set_plan_references processing on a MergeAppend
1378  *
1379  * We try to strip out the MergeAppend entirely; if we can't, we have
1380  * to do the normal processing on it.
1381  */
1382 static Plan *
1384  MergeAppend *mplan,
1385  int rtoffset)
1386 {
1387  ListCell *l;
1388 
1389  /*
1390  * MergeAppend, like Sort et al, doesn't actually evaluate its targetlist
1391  * or check quals. If it's got exactly one child plan, then it's not
1392  * doing anything useful at all, and we can strip it out.
1393  */
1394  Assert(mplan->plan.qual == NIL);
1395 
1396  /* First, we gotta recurse on the children */
1397  foreach(l, mplan->mergeplans)
1398  {
1399  lfirst(l) = set_plan_refs(root, (Plan *) lfirst(l), rtoffset);
1400  }
1401 
1402  /* Now, if there's just one, forget the MergeAppend and return that child */
1403  if (list_length(mplan->mergeplans) == 1)
1404  return clean_up_removed_plan_level((Plan *) mplan,
1405  (Plan *) linitial(mplan->mergeplans));
1406 
1407  /*
1408  * Otherwise, clean up the MergeAppend as needed. It's okay to do this
1409  * after recursing to the children, because set_dummy_tlist_references
1410  * doesn't look at those.
1411  */
1412  set_dummy_tlist_references((Plan *) mplan, rtoffset);
1413 
1414  mplan->apprelids = offset_relid_set(mplan->apprelids, rtoffset);
1415 
1416  if (mplan->part_prune_info)
1417  {
1418  foreach(l, mplan->part_prune_info->prune_infos)
1419  {
1420  List *prune_infos = lfirst(l);
1421  ListCell *l2;
1422 
1423  foreach(l2, prune_infos)
1424  {
1425  PartitionedRelPruneInfo *pinfo = lfirst(l2);
1426 
1427  pinfo->rtindex += rtoffset;
1428  }
1429  }
1430  }
1431 
1432  /* We don't need to recurse to lefttree or righttree ... */
1433  Assert(mplan->plan.lefttree == NULL);
1434  Assert(mplan->plan.righttree == NULL);
1435 
1436  return (Plan *) mplan;
1437 }
1438 
1439 /*
1440  * set_hash_references
1441  * Do set_plan_references processing on a Hash node
1442  */
1443 static void
1444 set_hash_references(PlannerInfo *root, Plan *plan, int rtoffset)
1445 {
1446  Hash *hplan = (Hash *) plan;
1447  Plan *outer_plan = plan->lefttree;
1448  indexed_tlist *outer_itlist;
1449 
1450  /*
1451  * Hash's hashkeys are used when feeding tuples into the hashtable,
1452  * therefore have them reference Hash's outer plan (which itself is the
1453  * inner plan of the HashJoin).
1454  */
1455  outer_itlist = build_tlist_index(outer_plan->targetlist);
1456  hplan->hashkeys = (List *)
1457  fix_upper_expr(root,
1458  (Node *) hplan->hashkeys,
1459  outer_itlist,
1460  OUTER_VAR,
1461  rtoffset);
1462 
1463  /* Hash doesn't project */
1464  set_dummy_tlist_references(plan, rtoffset);
1465 
1466  /* Hash nodes don't have their own quals */
1467  Assert(plan->qual == NIL);
1468 }
1469 
1470 /*
1471  * offset_relid_set
1472  * Apply rtoffset to the members of a Relids set.
1473  */
1474 static Relids
1475 offset_relid_set(Relids relids, int rtoffset)
1476 {
1477  Relids result = NULL;
1478  int rtindex;
1479 
1480  /* If there's no offset to apply, we needn't recompute the value */
1481  if (rtoffset == 0)
1482  return relids;
1483  rtindex = -1;
1484  while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
1485  result = bms_add_member(result, rtindex + rtoffset);
1486  return result;
1487 }
1488 
1489 /*
1490  * copyVar
1491  * Copy a Var node.
1492  *
1493  * fix_scan_expr and friends do this enough times that it's worth having
1494  * a bespoke routine instead of using the generic copyObject() function.
1495  */
1496 static inline Var *
1498 {
1499  Var *newvar = (Var *) palloc(sizeof(Var));
1500 
1501  *newvar = *var;
1502  return newvar;
1503 }
1504 
1505 /*
1506  * fix_expr_common
1507  * Do generic set_plan_references processing on an expression node
1508  *
1509  * This is code that is common to all variants of expression-fixing.
1510  * We must look up operator opcode info for OpExpr and related nodes,
1511  * add OIDs from regclass Const nodes into root->glob->relationOids, and
1512  * add PlanInvalItems for user-defined functions into root->glob->invalItems.
1513  * We also fill in column index lists for GROUPING() expressions.
1514  *
1515  * We assume it's okay to update opcode info in-place. So this could possibly
1516  * scribble on the planner's input data structures, but it's OK.
1517  */
1518 static void
1520 {
1521  /* We assume callers won't call us on a NULL pointer */
1522  if (IsA(node, Aggref))
1523  {
1525  ((Aggref *) node)->aggfnoid);
1526  }
1527  else if (IsA(node, WindowFunc))
1528  {
1530  ((WindowFunc *) node)->winfnoid);
1531  }
1532  else if (IsA(node, FuncExpr))
1533  {
1535  ((FuncExpr *) node)->funcid);
1536  }
1537  else if (IsA(node, OpExpr))
1538  {
1539  set_opfuncid((OpExpr *) node);
1541  ((OpExpr *) node)->opfuncid);
1542  }
1543  else if (IsA(node, DistinctExpr))
1544  {
1545  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1547  ((DistinctExpr *) node)->opfuncid);
1548  }
1549  else if (IsA(node, NullIfExpr))
1550  {
1551  set_opfuncid((OpExpr *) node); /* rely on struct equivalence */
1553  ((NullIfExpr *) node)->opfuncid);
1554  }
1555  else if (IsA(node, ScalarArrayOpExpr))
1556  {
1559  ((ScalarArrayOpExpr *) node)->opfuncid);
1560  }
1561  else if (IsA(node, Const))
1562  {
1563  Const *con = (Const *) node;
1564 
1565  /* Check for regclass reference */
1566  if (ISREGCLASSCONST(con))
1567  root->glob->relationOids =
1568  lappend_oid(root->glob->relationOids,
1570  }
1571  else if (IsA(node, GroupingFunc))
1572  {
1573  GroupingFunc *g = (GroupingFunc *) node;
1574  AttrNumber *grouping_map = root->grouping_map;
1575 
1576  /* If there are no grouping sets, we don't need this. */
1577 
1578  Assert(grouping_map || g->cols == NIL);
1579 
1580  if (grouping_map)
1581  {
1582  ListCell *lc;
1583  List *cols = NIL;
1584 
1585  foreach(lc, g->refs)
1586  {
1587  cols = lappend_int(cols, grouping_map[lfirst_int(lc)]);
1588  }
1589 
1590  Assert(!g->cols || equal(cols, g->cols));
1591 
1592  if (!g->cols)
1593  g->cols = cols;
1594  }
1595  }
1596 }
1597 
1598 /*
1599  * fix_param_node
1600  * Do set_plan_references processing on a Param
1601  *
1602  * If it's a PARAM_MULTIEXPR, replace it with the appropriate Param from
1603  * root->multiexpr_params; otherwise no change is needed.
1604  * Just for paranoia's sake, we make a copy of the node in either case.
1605  */
1606 static Node *
1608 {
1609  if (p->paramkind == PARAM_MULTIEXPR)
1610  {
1611  int subqueryid = p->paramid >> 16;
1612  int colno = p->paramid & 0xFFFF;
1613  List *params;
1614 
1615  if (subqueryid <= 0 ||
1616  subqueryid > list_length(root->multiexpr_params))
1617  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1618  params = (List *) list_nth(root->multiexpr_params, subqueryid - 1);
1619  if (colno <= 0 || colno > list_length(params))
1620  elog(ERROR, "unexpected PARAM_MULTIEXPR ID: %d", p->paramid);
1621  return copyObject(list_nth(params, colno - 1));
1622  }
1623  return (Node *) copyObject(p);
1624 }
1625 
1626 /*
1627  * fix_scan_expr
1628  * Do set_plan_references processing on a scan-level expression
1629  *
1630  * This consists of incrementing all Vars' varnos by rtoffset,
1631  * replacing PARAM_MULTIEXPR Params, expanding PlaceHolderVars,
1632  * replacing Aggref nodes that should be replaced by initplan output Params,
1633  * looking up operator opcode info for OpExpr and related nodes,
1634  * and adding OIDs from regclass Const nodes into root->glob->relationOids.
1635  */
1636 static Node *
1637 fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
1638 {
1639  fix_scan_expr_context context;
1640 
1641  context.root = root;
1642  context.rtoffset = rtoffset;
1643 
1644  if (rtoffset != 0 ||
1645  root->multiexpr_params != NIL ||
1646  root->glob->lastPHId != 0 ||
1647  root->minmax_aggs != NIL)
1648  {
1649  return fix_scan_expr_mutator(node, &context);
1650  }
1651  else
1652  {
1653  /*
1654  * If rtoffset == 0, we don't need to change any Vars, and if there
1655  * are no MULTIEXPR subqueries then we don't need to replace
1656  * PARAM_MULTIEXPR Params, and if there are no placeholders anywhere
1657  * we won't need to remove them, and if there are no minmax Aggrefs we
1658  * won't need to replace them. Then it's OK to just scribble on the
1659  * input node tree instead of copying (since the only change, filling
1660  * in any unset opfuncid fields, is harmless). This saves just enough
1661  * cycles to be noticeable on trivial queries.
1662  */
1663  (void) fix_scan_expr_walker(node, &context);
1664  return node;
1665  }
1666 }
1667 
1668 static Node *
1670 {
1671  if (node == NULL)
1672  return NULL;
1673  if (IsA(node, Var))
1674  {
1675  Var *var = copyVar((Var *) node);
1676 
1677  Assert(var->varlevelsup == 0);
1678 
1679  /*
1680  * We should not see any Vars marked INNER_VAR or OUTER_VAR. But an
1681  * indexqual expression could contain INDEX_VAR Vars.
1682  */
1683  Assert(var->varno != INNER_VAR);
1684  Assert(var->varno != OUTER_VAR);
1685  if (!IS_SPECIAL_VARNO(var->varno))
1686  var->varno += context->rtoffset;
1687  if (var->varnosyn > 0)
1688  var->varnosyn += context->rtoffset;
1689  return (Node *) var;
1690  }
1691  if (IsA(node, Param))
1692  return fix_param_node(context->root, (Param *) node);
1693  if (IsA(node, Aggref))
1694  {
1695  Aggref *aggref = (Aggref *) node;
1696 
1697  /* See if the Aggref should be replaced by a Param */
1698  if (context->root->minmax_aggs != NIL &&
1699  list_length(aggref->args) == 1)
1700  {
1701  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
1702  ListCell *lc;
1703 
1704  foreach(lc, context->root->minmax_aggs)
1705  {
1706  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
1707 
1708  if (mminfo->aggfnoid == aggref->aggfnoid &&
1709  equal(mminfo->target, curTarget->expr))
1710  return (Node *) copyObject(mminfo->param);
1711  }
1712  }
1713  /* If no match, just fall through to process it normally */
1714  }
1715  if (IsA(node, CurrentOfExpr))
1716  {
1717  CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
1718 
1719  Assert(cexpr->cvarno != INNER_VAR);
1720  Assert(cexpr->cvarno != OUTER_VAR);
1721  if (!IS_SPECIAL_VARNO(cexpr->cvarno))
1722  cexpr->cvarno += context->rtoffset;
1723  return (Node *) cexpr;
1724  }
1725  if (IsA(node, PlaceHolderVar))
1726  {
1727  /* At scan level, we should always just evaluate the contained expr */
1728  PlaceHolderVar *phv = (PlaceHolderVar *) node;
1729 
1730  return fix_scan_expr_mutator((Node *) phv->phexpr, context);
1731  }
1732  fix_expr_common(context->root, node);
1734  (void *) context);
1735 }
1736 
1737 static bool
1739 {
1740  if (node == NULL)
1741  return false;
1742  Assert(!IsA(node, PlaceHolderVar));
1743  fix_expr_common(context->root, node);
1745  (void *) context);
1746 }
1747 
1748 /*
1749  * set_join_references
1750  * Modify the target list and quals of a join node to reference its
1751  * subplans, by setting the varnos to OUTER_VAR or INNER_VAR and setting
1752  * attno values to the result domain number of either the corresponding
1753  * outer or inner join tuple item. Also perform opcode lookup for these
1754  * expressions, and add regclass OIDs to root->glob->relationOids.
1755  */
1756 static void
1757 set_join_references(PlannerInfo *root, Join *join, int rtoffset)
1758 {
1759  Plan *outer_plan = join->plan.lefttree;
1760  Plan *inner_plan = join->plan.righttree;
1761  indexed_tlist *outer_itlist;
1762  indexed_tlist *inner_itlist;
1763 
1764  outer_itlist = build_tlist_index(outer_plan->targetlist);
1765  inner_itlist = build_tlist_index(inner_plan->targetlist);
1766 
1767  /*
1768  * First process the joinquals (including merge or hash clauses). These
1769  * are logically below the join so they can always use all values
1770  * available from the input tlists. It's okay to also handle
1771  * NestLoopParams now, because those couldn't refer to nullable
1772  * subexpressions.
1773  */
1774  join->joinqual = fix_join_expr(root,
1775  join->joinqual,
1776  outer_itlist,
1777  inner_itlist,
1778  (Index) 0,
1779  rtoffset);
1780 
1781  /* Now do join-type-specific stuff */
1782  if (IsA(join, NestLoop))
1783  {
1784  NestLoop *nl = (NestLoop *) join;
1785  ListCell *lc;
1786 
1787  foreach(lc, nl->nestParams)
1788  {
1789  NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1790 
1791  nlp->paramval = (Var *) fix_upper_expr(root,
1792  (Node *) nlp->paramval,
1793  outer_itlist,
1794  OUTER_VAR,
1795  rtoffset);
1796  /* Check we replaced any PlaceHolderVar with simple Var */
1797  if (!(IsA(nlp->paramval, Var) &&
1798  nlp->paramval->varno == OUTER_VAR))
1799  elog(ERROR, "NestLoopParam was not reduced to a simple Var");
1800  }
1801  }
1802  else if (IsA(join, MergeJoin))
1803  {
1804  MergeJoin *mj = (MergeJoin *) join;
1805 
1806  mj->mergeclauses = fix_join_expr(root,
1807  mj->mergeclauses,
1808  outer_itlist,
1809  inner_itlist,
1810  (Index) 0,
1811  rtoffset);
1812  }
1813  else if (IsA(join, HashJoin))
1814  {
1815  HashJoin *hj = (HashJoin *) join;
1816 
1817  hj->hashclauses = fix_join_expr(root,
1818  hj->hashclauses,
1819  outer_itlist,
1820  inner_itlist,
1821  (Index) 0,
1822  rtoffset);
1823 
1824  /*
1825  * HashJoin's hashkeys are used to look for matching tuples from its
1826  * outer plan (not the Hash node!) in the hashtable.
1827  */
1828  hj->hashkeys = (List *) fix_upper_expr(root,
1829  (Node *) hj->hashkeys,
1830  outer_itlist,
1831  OUTER_VAR,
1832  rtoffset);
1833  }
1834 
1835  /*
1836  * Now we need to fix up the targetlist and qpqual, which are logically
1837  * above the join. This means they should not re-use any input expression
1838  * that was computed in the nullable side of an outer join. Vars and
1839  * PlaceHolderVars are fine, so we can implement this restriction just by
1840  * clearing has_non_vars in the indexed_tlist structs.
1841  *
1842  * XXX This is a grotty workaround for the fact that we don't clearly
1843  * distinguish between a Var appearing below an outer join and the "same"
1844  * Var appearing above it. If we did, we'd not need to hack the matching
1845  * rules this way.
1846  */
1847  switch (join->jointype)
1848  {
1849  case JOIN_LEFT:
1850  case JOIN_SEMI:
1851  case JOIN_ANTI:
1852  inner_itlist->has_non_vars = false;
1853  break;
1854  case JOIN_RIGHT:
1855  outer_itlist->has_non_vars = false;
1856  break;
1857  case JOIN_FULL:
1858  outer_itlist->has_non_vars = false;
1859  inner_itlist->has_non_vars = false;
1860  break;
1861  default:
1862  break;
1863  }
1864 
1865  join->plan.targetlist = fix_join_expr(root,
1866  join->plan.targetlist,
1867  outer_itlist,
1868  inner_itlist,
1869  (Index) 0,
1870  rtoffset);
1871  join->plan.qual = fix_join_expr(root,
1872  join->plan.qual,
1873  outer_itlist,
1874  inner_itlist,
1875  (Index) 0,
1876  rtoffset);
1877 
1878  pfree(outer_itlist);
1879  pfree(inner_itlist);
1880 }
1881 
1882 /*
1883  * set_upper_references
1884  * Update the targetlist and quals of an upper-level plan node
1885  * to refer to the tuples returned by its lefttree subplan.
1886  * Also perform opcode lookup for these expressions, and
1887  * add regclass OIDs to root->glob->relationOids.
1888  *
1889  * This is used for single-input plan types like Agg, Group, Result.
1890  *
1891  * In most cases, we have to match up individual Vars in the tlist and
1892  * qual expressions with elements of the subplan's tlist (which was
1893  * generated by flattening these selfsame expressions, so it should have all
1894  * the required variables). There is an important exception, however:
1895  * depending on where we are in the plan tree, sort/group columns may have
1896  * been pushed into the subplan tlist unflattened. If these values are also
1897  * needed in the output then we want to reference the subplan tlist element
1898  * rather than recomputing the expression.
1899  */
1900 static void
1901 set_upper_references(PlannerInfo *root, Plan *plan, int rtoffset)
1902 {
1903  Plan *subplan = plan->lefttree;
1904  indexed_tlist *subplan_itlist;
1905  List *output_targetlist;
1906  ListCell *l;
1907 
1908  subplan_itlist = build_tlist_index(subplan->targetlist);
1909 
1910  output_targetlist = NIL;
1911  foreach(l, plan->targetlist)
1912  {
1913  TargetEntry *tle = (TargetEntry *) lfirst(l);
1914  Node *newexpr;
1915 
1916  /* If it's a sort/group item, first try to match by sortref */
1917  if (tle->ressortgroupref != 0)
1918  {
1919  newexpr = (Node *)
1921  tle->ressortgroupref,
1922  subplan_itlist,
1923  OUTER_VAR);
1924  if (!newexpr)
1925  newexpr = fix_upper_expr(root,
1926  (Node *) tle->expr,
1927  subplan_itlist,
1928  OUTER_VAR,
1929  rtoffset);
1930  }
1931  else
1932  newexpr = fix_upper_expr(root,
1933  (Node *) tle->expr,
1934  subplan_itlist,
1935  OUTER_VAR,
1936  rtoffset);
1937  tle = flatCopyTargetEntry(tle);
1938  tle->expr = (Expr *) newexpr;
1939  output_targetlist = lappend(output_targetlist, tle);
1940  }
1941  plan->targetlist = output_targetlist;
1942 
1943  plan->qual = (List *)
1944  fix_upper_expr(root,
1945  (Node *) plan->qual,
1946  subplan_itlist,
1947  OUTER_VAR,
1948  rtoffset);
1949 
1950  pfree(subplan_itlist);
1951 }
1952 
1953 /*
1954  * set_param_references
1955  * Initialize the initParam list in Gather or Gather merge node such that
1956  * it contains reference of all the params that needs to be evaluated
1957  * before execution of the node. It contains the initplan params that are
1958  * being passed to the plan nodes below it.
1959  */
1960 static void
1962 {
1963  Assert(IsA(plan, Gather) || IsA(plan, GatherMerge));
1964 
1965  if (plan->lefttree->extParam)
1966  {
1967  PlannerInfo *proot;
1968  Bitmapset *initSetParam = NULL;
1969  ListCell *l;
1970 
1971  for (proot = root; proot != NULL; proot = proot->parent_root)
1972  {
1973  foreach(l, proot->init_plans)
1974  {
1975  SubPlan *initsubplan = (SubPlan *) lfirst(l);
1976  ListCell *l2;
1977 
1978  foreach(l2, initsubplan->setParam)
1979  {
1980  initSetParam = bms_add_member(initSetParam, lfirst_int(l2));
1981  }
1982  }
1983  }
1984 
1985  /*
1986  * Remember the list of all external initplan params that are used by
1987  * the children of Gather or Gather merge node.
1988  */
1989  if (IsA(plan, Gather))
1990  ((Gather *) plan)->initParam =
1991  bms_intersect(plan->lefttree->extParam, initSetParam);
1992  else
1993  ((GatherMerge *) plan)->initParam =
1994  bms_intersect(plan->lefttree->extParam, initSetParam);
1995  }
1996 }
1997 
1998 /*
1999  * Recursively scan an expression tree and convert Aggrefs to the proper
2000  * intermediate form for combining aggregates. This means (1) replacing each
2001  * one's argument list with a single argument that is the original Aggref
2002  * modified to show partial aggregation and (2) changing the upper Aggref to
2003  * show combining aggregation.
2004  *
2005  * After this step, set_upper_references will replace the partial Aggrefs
2006  * with Vars referencing the lower Agg plan node's outputs, so that the final
2007  * form seen by the executor is a combining Aggref with a Var as input.
2008  *
2009  * It's rather messy to postpone this step until setrefs.c; ideally it'd be
2010  * done in createplan.c. The difficulty is that once we modify the Aggref
2011  * expressions, they will no longer be equal() to their original form and
2012  * so cross-plan-node-level matches will fail. So this has to happen after
2013  * the plan node above the Agg has resolved its subplan references.
2014  */
2015 static Node *
2016 convert_combining_aggrefs(Node *node, void *context)
2017 {
2018  if (node == NULL)
2019  return NULL;
2020  if (IsA(node, Aggref))
2021  {
2022  Aggref *orig_agg = (Aggref *) node;
2023  Aggref *child_agg;
2024  Aggref *parent_agg;
2025 
2026  /* Assert we've not chosen to partial-ize any unsupported cases */
2027  Assert(orig_agg->aggorder == NIL);
2028  Assert(orig_agg->aggdistinct == NIL);
2029 
2030  /*
2031  * Since aggregate calls can't be nested, we needn't recurse into the
2032  * arguments. But for safety, flat-copy the Aggref node itself rather
2033  * than modifying it in-place.
2034  */
2035  child_agg = makeNode(Aggref);
2036  memcpy(child_agg, orig_agg, sizeof(Aggref));
2037 
2038  /*
2039  * For the parent Aggref, we want to copy all the fields of the
2040  * original aggregate *except* the args list, which we'll replace
2041  * below, and the aggfilter expression, which should be applied only
2042  * by the child not the parent. Rather than explicitly knowing about
2043  * all the other fields here, we can momentarily modify child_agg to
2044  * provide a suitable source for copyObject.
2045  */
2046  child_agg->args = NIL;
2047  child_agg->aggfilter = NULL;
2048  parent_agg = copyObject(child_agg);
2049  child_agg->args = orig_agg->args;
2050  child_agg->aggfilter = orig_agg->aggfilter;
2051 
2052  /*
2053  * Now, set up child_agg to represent the first phase of partial
2054  * aggregation. For now, assume serialization is required.
2055  */
2057 
2058  /*
2059  * And set up parent_agg to represent the second phase.
2060  */
2061  parent_agg->args = list_make1(makeTargetEntry((Expr *) child_agg,
2062  1, NULL, false));
2064 
2065  return (Node *) parent_agg;
2066  }
2068  (void *) context);
2069 }
2070 
2071 /*
2072  * set_dummy_tlist_references
2073  * Replace the targetlist of an upper-level plan node with a simple
2074  * list of OUTER_VAR references to its child.
2075  *
2076  * This is used for plan types like Sort and Append that don't evaluate
2077  * their targetlists. Although the executor doesn't care at all what's in
2078  * the tlist, EXPLAIN needs it to be realistic.
2079  *
2080  * Note: we could almost use set_upper_references() here, but it fails for
2081  * Append for lack of a lefttree subplan. Single-purpose code is faster
2082  * anyway.
2083  */
2084 static void
2085 set_dummy_tlist_references(Plan *plan, int rtoffset)
2086 {
2087  List *output_targetlist;
2088  ListCell *l;
2089 
2090  output_targetlist = NIL;
2091  foreach(l, plan->targetlist)
2092  {
2093  TargetEntry *tle = (TargetEntry *) lfirst(l);
2094  Var *oldvar = (Var *) tle->expr;
2095  Var *newvar;
2096 
2097  /*
2098  * As in search_indexed_tlist_for_non_var(), we prefer to keep Consts
2099  * as Consts, not Vars referencing Consts. Here, there's no speed
2100  * advantage to be had, but it makes EXPLAIN output look cleaner, and
2101  * again it avoids confusing the executor.
2102  */
2103  if (IsA(oldvar, Const))
2104  {
2105  /* just reuse the existing TLE node */
2106  output_targetlist = lappend(output_targetlist, tle);
2107  continue;
2108  }
2109 
2110  newvar = makeVar(OUTER_VAR,
2111  tle->resno,
2112  exprType((Node *) oldvar),
2113  exprTypmod((Node *) oldvar),
2114  exprCollation((Node *) oldvar),
2115  0);
2116  if (IsA(oldvar, Var) &&
2117  oldvar->varnosyn > 0)
2118  {
2119  newvar->varnosyn = oldvar->varnosyn + rtoffset;
2120  newvar->varattnosyn = oldvar->varattnosyn;
2121  }
2122  else
2123  {
2124  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2125  newvar->varattnosyn = 0;
2126  }
2127 
2128  tle = flatCopyTargetEntry(tle);
2129  tle->expr = (Expr *) newvar;
2130  output_targetlist = lappend(output_targetlist, tle);
2131  }
2132  plan->targetlist = output_targetlist;
2133 
2134  /* We don't touch plan->qual here */
2135 }
2136 
2137 
2138 /*
2139  * build_tlist_index --- build an index data structure for a child tlist
2140  *
2141  * In most cases, subplan tlists will be "flat" tlists with only Vars,
2142  * so we try to optimize that case by extracting information about Vars
2143  * in advance. Matching a parent tlist to a child is still an O(N^2)
2144  * operation, but at least with a much smaller constant factor than plain
2145  * tlist_member() searches.
2146  *
2147  * The result of this function is an indexed_tlist struct to pass to
2148  * search_indexed_tlist_for_var() or search_indexed_tlist_for_non_var().
2149  * When done, the indexed_tlist may be freed with a single pfree().
2150  */
2151 static indexed_tlist *
2153 {
2154  indexed_tlist *itlist;
2155  tlist_vinfo *vinfo;
2156  ListCell *l;
2157 
2158  /* Create data structure with enough slots for all tlist entries */
2159  itlist = (indexed_tlist *)
2161  list_length(tlist) * sizeof(tlist_vinfo));
2162 
2163  itlist->tlist = tlist;
2164  itlist->has_ph_vars = false;
2165  itlist->has_non_vars = false;
2166 
2167  /* Find the Vars and fill in the index array */
2168  vinfo = itlist->vars;
2169  foreach(l, tlist)
2170  {
2171  TargetEntry *tle = (TargetEntry *) lfirst(l);
2172 
2173  if (tle->expr && IsA(tle->expr, Var))
2174  {
2175  Var *var = (Var *) tle->expr;
2176 
2177  vinfo->varno = var->varno;
2178  vinfo->varattno = var->varattno;
2179  vinfo->resno = tle->resno;
2180  vinfo++;
2181  }
2182  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2183  itlist->has_ph_vars = true;
2184  else
2185  itlist->has_non_vars = true;
2186  }
2187 
2188  itlist->num_vars = (vinfo - itlist->vars);
2189 
2190  return itlist;
2191 }
2192 
2193 /*
2194  * build_tlist_index_other_vars --- build a restricted tlist index
2195  *
2196  * This is like build_tlist_index, but we only index tlist entries that
2197  * are Vars belonging to some rel other than the one specified. We will set
2198  * has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
2199  * (so nothing other than Vars and PlaceHolderVars can be matched).
2200  */
2201 static indexed_tlist *
2203 {
2204  indexed_tlist *itlist;
2205  tlist_vinfo *vinfo;
2206  ListCell *l;
2207 
2208  /* Create data structure with enough slots for all tlist entries */
2209  itlist = (indexed_tlist *)
2211  list_length(tlist) * sizeof(tlist_vinfo));
2212 
2213  itlist->tlist = tlist;
2214  itlist->has_ph_vars = false;
2215  itlist->has_non_vars = false;
2216 
2217  /* Find the desired Vars and fill in the index array */
2218  vinfo = itlist->vars;
2219  foreach(l, tlist)
2220  {
2221  TargetEntry *tle = (TargetEntry *) lfirst(l);
2222 
2223  if (tle->expr && IsA(tle->expr, Var))
2224  {
2225  Var *var = (Var *) tle->expr;
2226 
2227  if (var->varno != ignore_rel)
2228  {
2229  vinfo->varno = var->varno;
2230  vinfo->varattno = var->varattno;
2231  vinfo->resno = tle->resno;
2232  vinfo++;
2233  }
2234  }
2235  else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
2236  itlist->has_ph_vars = true;
2237  }
2238 
2239  itlist->num_vars = (vinfo - itlist->vars);
2240 
2241  return itlist;
2242 }
2243 
2244 /*
2245  * search_indexed_tlist_for_var --- find a Var in an indexed tlist
2246  *
2247  * If a match is found, return a copy of the given Var with suitably
2248  * modified varno/varattno (to wit, newvarno and the resno of the TLE entry).
2249  * Also ensure that varnosyn is incremented by rtoffset.
2250  * If no match, return NULL.
2251  */
2252 static Var *
2254  Index newvarno, int rtoffset)
2255 {
2256  Index varno = var->varno;
2257  AttrNumber varattno = var->varattno;
2258  tlist_vinfo *vinfo;
2259  int i;
2260 
2261  vinfo = itlist->vars;
2262  i = itlist->num_vars;
2263  while (i-- > 0)
2264  {
2265  if (vinfo->varno == varno && vinfo->varattno == varattno)
2266  {
2267  /* Found a match */
2268  Var *newvar = copyVar(var);
2269 
2270  newvar->varno = newvarno;
2271  newvar->varattno = vinfo->resno;
2272  if (newvar->varnosyn > 0)
2273  newvar->varnosyn += rtoffset;
2274  return newvar;
2275  }
2276  vinfo++;
2277  }
2278  return NULL; /* no match */
2279 }
2280 
2281 /*
2282  * search_indexed_tlist_for_non_var --- find a non-Var in an indexed tlist
2283  *
2284  * If a match is found, return a Var constructed to reference the tlist item.
2285  * If no match, return NULL.
2286  *
2287  * NOTE: it is a waste of time to call this unless itlist->has_ph_vars or
2288  * itlist->has_non_vars. Furthermore, set_join_references() relies on being
2289  * able to prevent matching of non-Vars by clearing itlist->has_non_vars,
2290  * so there's a correctness reason not to call it unless that's set.
2291  */
2292 static Var *
2294  indexed_tlist *itlist, Index newvarno)
2295 {
2296  TargetEntry *tle;
2297 
2298  /*
2299  * If it's a simple Const, replacing it with a Var is silly, even if there
2300  * happens to be an identical Const below; a Var is more expensive to
2301  * execute than a Const. What's more, replacing it could confuse some
2302  * places in the executor that expect to see simple Consts for, eg,
2303  * dropped columns.
2304  */
2305  if (IsA(node, Const))
2306  return NULL;
2307 
2308  tle = tlist_member(node, itlist->tlist);
2309  if (tle)
2310  {
2311  /* Found a matching subplan output expression */
2312  Var *newvar;
2313 
2314  newvar = makeVarFromTargetEntry(newvarno, tle);
2315  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2316  newvar->varattnosyn = 0;
2317  return newvar;
2318  }
2319  return NULL; /* no match */
2320 }
2321 
2322 /*
2323  * search_indexed_tlist_for_sortgroupref --- find a sort/group expression
2324  *
2325  * If a match is found, return a Var constructed to reference the tlist item.
2326  * If no match, return NULL.
2327  *
2328  * This is needed to ensure that we select the right subplan TLE in cases
2329  * where there are multiple textually-equal()-but-volatile sort expressions.
2330  * And it's also faster than search_indexed_tlist_for_non_var.
2331  */
2332 static Var *
2334  Index sortgroupref,
2335  indexed_tlist *itlist,
2336  Index newvarno)
2337 {
2338  ListCell *lc;
2339 
2340  foreach(lc, itlist->tlist)
2341  {
2342  TargetEntry *tle = (TargetEntry *) lfirst(lc);
2343 
2344  /* The equal() check should be redundant, but let's be paranoid */
2345  if (tle->ressortgroupref == sortgroupref &&
2346  equal(node, tle->expr))
2347  {
2348  /* Found a matching subplan output expression */
2349  Var *newvar;
2350 
2351  newvar = makeVarFromTargetEntry(newvarno, tle);
2352  newvar->varnosyn = 0; /* wasn't ever a plain Var */
2353  newvar->varattnosyn = 0;
2354  return newvar;
2355  }
2356  }
2357  return NULL; /* no match */
2358 }
2359 
2360 /*
2361  * fix_join_expr
2362  * Create a new set of targetlist entries or join qual clauses by
2363  * changing the varno/varattno values of variables in the clauses
2364  * to reference target list values from the outer and inner join
2365  * relation target lists. Also perform opcode lookup and add
2366  * regclass OIDs to root->glob->relationOids.
2367  *
2368  * This is used in three different scenarios:
2369  * 1) a normal join clause, where all the Vars in the clause *must* be
2370  * replaced by OUTER_VAR or INNER_VAR references. In this case
2371  * acceptable_rel should be zero so that any failure to match a Var will be
2372  * reported as an error.
2373  * 2) RETURNING clauses, which may contain both Vars of the target relation
2374  * and Vars of other relations. In this case we want to replace the
2375  * other-relation Vars by OUTER_VAR references, while leaving target Vars
2376  * alone. Thus inner_itlist = NULL and acceptable_rel = the ID of the
2377  * target relation should be passed.
2378  * 3) ON CONFLICT UPDATE SET/WHERE clauses. Here references to EXCLUDED are
2379  * to be replaced with INNER_VAR references, while leaving target Vars (the
2380  * to-be-updated relation) alone. Correspondingly inner_itlist is to be
2381  * EXCLUDED elements, outer_itlist = NULL and acceptable_rel the target
2382  * relation.
2383  *
2384  * 'clauses' is the targetlist or list of join clauses
2385  * 'outer_itlist' is the indexed target list of the outer join relation,
2386  * or NULL
2387  * 'inner_itlist' is the indexed target list of the inner join relation,
2388  * or NULL
2389  * 'acceptable_rel' is either zero or the rangetable index of a relation
2390  * whose Vars may appear in the clause without provoking an error
2391  * 'rtoffset': how much to increment varnos by
2392  *
2393  * Returns the new expression tree. The original clause structure is
2394  * not modified.
2395  */
2396 static List *
2398  List *clauses,
2399  indexed_tlist *outer_itlist,
2400  indexed_tlist *inner_itlist,
2401  Index acceptable_rel,
2402  int rtoffset)
2403 {
2404  fix_join_expr_context context;
2405 
2406  context.root = root;
2407  context.outer_itlist = outer_itlist;
2408  context.inner_itlist = inner_itlist;
2409  context.acceptable_rel = acceptable_rel;
2410  context.rtoffset = rtoffset;
2411  return (List *) fix_join_expr_mutator((Node *) clauses, &context);
2412 }
2413 
2414 static Node *
2416 {
2417  Var *newvar;
2418 
2419  if (node == NULL)
2420  return NULL;
2421  if (IsA(node, Var))
2422  {
2423  Var *var = (Var *) node;
2424 
2425  /* Look for the var in the input tlists, first in the outer */
2426  if (context->outer_itlist)
2427  {
2428  newvar = search_indexed_tlist_for_var(var,
2429  context->outer_itlist,
2430  OUTER_VAR,
2431  context->rtoffset);
2432  if (newvar)
2433  return (Node *) newvar;
2434  }
2435 
2436  /* then in the inner. */
2437  if (context->inner_itlist)
2438  {
2439  newvar = search_indexed_tlist_for_var(var,
2440  context->inner_itlist,
2441  INNER_VAR,
2442  context->rtoffset);
2443  if (newvar)
2444  return (Node *) newvar;
2445  }
2446 
2447  /* If it's for acceptable_rel, adjust and return it */
2448  if (var->varno == context->acceptable_rel)
2449  {
2450  var = copyVar(var);
2451  var->varno += context->rtoffset;
2452  if (var->varnosyn > 0)
2453  var->varnosyn += context->rtoffset;
2454  return (Node *) var;
2455  }
2456 
2457  /* No referent found for Var */
2458  elog(ERROR, "variable not found in subplan target lists");
2459  }
2460  if (IsA(node, PlaceHolderVar))
2461  {
2462  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2463 
2464  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2465  if (context->outer_itlist && context->outer_itlist->has_ph_vars)
2466  {
2467  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2468  context->outer_itlist,
2469  OUTER_VAR);
2470  if (newvar)
2471  return (Node *) newvar;
2472  }
2473  if (context->inner_itlist && context->inner_itlist->has_ph_vars)
2474  {
2475  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2476  context->inner_itlist,
2477  INNER_VAR);
2478  if (newvar)
2479  return (Node *) newvar;
2480  }
2481 
2482  /* If not supplied by input plans, evaluate the contained expr */
2483  return fix_join_expr_mutator((Node *) phv->phexpr, context);
2484  }
2485  /* Try matching more complex expressions too, if tlists have any */
2486  if (context->outer_itlist && context->outer_itlist->has_non_vars)
2487  {
2488  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2489  context->outer_itlist,
2490  OUTER_VAR);
2491  if (newvar)
2492  return (Node *) newvar;
2493  }
2494  if (context->inner_itlist && context->inner_itlist->has_non_vars)
2495  {
2496  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2497  context->inner_itlist,
2498  INNER_VAR);
2499  if (newvar)
2500  return (Node *) newvar;
2501  }
2502  /* Special cases (apply only AFTER failing to match to lower tlist) */
2503  if (IsA(node, Param))
2504  return fix_param_node(context->root, (Param *) node);
2505  fix_expr_common(context->root, node);
2506  return expression_tree_mutator(node,
2508  (void *) context);
2509 }
2510 
2511 /*
2512  * fix_upper_expr
2513  * Modifies an expression tree so that all Var nodes reference outputs
2514  * of a subplan. Also looks for Aggref nodes that should be replaced
2515  * by initplan output Params. Also performs opcode lookup, and adds
2516  * regclass OIDs to root->glob->relationOids.
2517  *
2518  * This is used to fix up target and qual expressions of non-join upper-level
2519  * plan nodes, as well as index-only scan nodes.
2520  *
2521  * An error is raised if no matching var can be found in the subplan tlist
2522  * --- so this routine should only be applied to nodes whose subplans'
2523  * targetlists were generated by flattening the expressions used in the
2524  * parent node.
2525  *
2526  * If itlist->has_non_vars is true, then we try to match whole subexpressions
2527  * against elements of the subplan tlist, so that we can avoid recomputing
2528  * expressions that were already computed by the subplan. (This is relatively
2529  * expensive, so we don't want to try it in the common case where the
2530  * subplan tlist is just a flattened list of Vars.)
2531  *
2532  * 'node': the tree to be fixed (a target item or qual)
2533  * 'subplan_itlist': indexed target list for subplan (or index)
2534  * 'newvarno': varno to use for Vars referencing tlist elements
2535  * 'rtoffset': how much to increment varnos by
2536  *
2537  * The resulting tree is a copy of the original in which all Var nodes have
2538  * varno = newvarno, varattno = resno of corresponding targetlist element.
2539  * The original tree is not modified.
2540  */
2541 static Node *
2543  Node *node,
2544  indexed_tlist *subplan_itlist,
2545  Index newvarno,
2546  int rtoffset)
2547 {
2548  fix_upper_expr_context context;
2549 
2550  context.root = root;
2551  context.subplan_itlist = subplan_itlist;
2552  context.newvarno = newvarno;
2553  context.rtoffset = rtoffset;
2554  return fix_upper_expr_mutator(node, &context);
2555 }
2556 
2557 static Node *
2559 {
2560  Var *newvar;
2561 
2562  if (node == NULL)
2563  return NULL;
2564  if (IsA(node, Var))
2565  {
2566  Var *var = (Var *) node;
2567 
2568  newvar = search_indexed_tlist_for_var(var,
2569  context->subplan_itlist,
2570  context->newvarno,
2571  context->rtoffset);
2572  if (!newvar)
2573  elog(ERROR, "variable not found in subplan target list");
2574  return (Node *) newvar;
2575  }
2576  if (IsA(node, PlaceHolderVar))
2577  {
2578  PlaceHolderVar *phv = (PlaceHolderVar *) node;
2579 
2580  /* See if the PlaceHolderVar has bubbled up from a lower plan node */
2581  if (context->subplan_itlist->has_ph_vars)
2582  {
2583  newvar = search_indexed_tlist_for_non_var((Expr *) phv,
2584  context->subplan_itlist,
2585  context->newvarno);
2586  if (newvar)
2587  return (Node *) newvar;
2588  }
2589  /* If not supplied by input plan, evaluate the contained expr */
2590  return fix_upper_expr_mutator((Node *) phv->phexpr, context);
2591  }
2592  /* Try matching more complex expressions too, if tlist has any */
2593  if (context->subplan_itlist->has_non_vars)
2594  {
2595  newvar = search_indexed_tlist_for_non_var((Expr *) node,
2596  context->subplan_itlist,
2597  context->newvarno);
2598  if (newvar)
2599  return (Node *) newvar;
2600  }
2601  /* Special cases (apply only AFTER failing to match to lower tlist) */
2602  if (IsA(node, Param))
2603  return fix_param_node(context->root, (Param *) node);
2604  if (IsA(node, Aggref))
2605  {
2606  Aggref *aggref = (Aggref *) node;
2607 
2608  /* See if the Aggref should be replaced by a Param */
2609  if (context->root->minmax_aggs != NIL &&
2610  list_length(aggref->args) == 1)
2611  {
2612  TargetEntry *curTarget = (TargetEntry *) linitial(aggref->args);
2613  ListCell *lc;
2614 
2615  foreach(lc, context->root->minmax_aggs)
2616  {
2617  MinMaxAggInfo *mminfo = (MinMaxAggInfo *) lfirst(lc);
2618 
2619  if (mminfo->aggfnoid == aggref->aggfnoid &&
2620  equal(mminfo->target, curTarget->expr))
2621  return (Node *) copyObject(mminfo->param);
2622  }
2623  }
2624  /* If no match, just fall through to process it normally */
2625  }
2626  fix_expr_common(context->root, node);
2627  return expression_tree_mutator(node,
2629  (void *) context);
2630 }
2631 
2632 /*
2633  * set_returning_clause_references
2634  * Perform setrefs.c's work on a RETURNING targetlist
2635  *
2636  * If the query involves more than just the result table, we have to
2637  * adjust any Vars that refer to other tables to reference junk tlist
2638  * entries in the top subplan's targetlist. Vars referencing the result
2639  * table should be left alone, however (the executor will evaluate them
2640  * using the actual heap tuple, after firing triggers if any). In the
2641  * adjusted RETURNING list, result-table Vars will have their original
2642  * varno (plus rtoffset), but Vars for other rels will have varno OUTER_VAR.
2643  *
2644  * We also must perform opcode lookup and add regclass OIDs to
2645  * root->glob->relationOids.
2646  *
2647  * 'rlist': the RETURNING targetlist to be fixed
2648  * 'topplan': the top subplan node that will be just below the ModifyTable
2649  * node (note it's not yet passed through set_plan_refs)
2650  * 'resultRelation': RT index of the associated result relation
2651  * 'rtoffset': how much to increment varnos by
2652  *
2653  * Note: the given 'root' is for the parent query level, not the 'topplan'.
2654  * This does not matter currently since we only access the dependency-item
2655  * lists in root->glob, but it would need some hacking if we wanted a root
2656  * that actually matches the subplan.
2657  *
2658  * Note: resultRelation is not yet adjusted by rtoffset.
2659  */
2660 static List *
2662  List *rlist,
2663  Plan *topplan,
2664  Index resultRelation,
2665  int rtoffset)
2666 {
2667  indexed_tlist *itlist;
2668 
2669  /*
2670  * We can perform the desired Var fixup by abusing the fix_join_expr
2671  * machinery that formerly handled inner indexscan fixup. We search the
2672  * top plan's targetlist for Vars of non-result relations, and use
2673  * fix_join_expr to convert RETURNING Vars into references to those tlist
2674  * entries, while leaving result-rel Vars as-is.
2675  *
2676  * PlaceHolderVars will also be sought in the targetlist, but no
2677  * more-complex expressions will be. Note that it is not possible for a
2678  * PlaceHolderVar to refer to the result relation, since the result is
2679  * never below an outer join. If that case could happen, we'd have to be
2680  * prepared to pick apart the PlaceHolderVar and evaluate its contained
2681  * expression instead.
2682  */
2683  itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
2684 
2685  rlist = fix_join_expr(root,
2686  rlist,
2687  itlist,
2688  NULL,
2689  resultRelation,
2690  rtoffset);
2691 
2692  pfree(itlist);
2693 
2694  return rlist;
2695 }
2696 
2697 
2698 /*****************************************************************************
2699  * QUERY DEPENDENCY MANAGEMENT
2700  *****************************************************************************/
2701 
2702 /*
2703  * record_plan_function_dependency
2704  * Mark the current plan as depending on a particular function.
2705  *
2706  * This is exported so that the function-inlining code can record a
2707  * dependency on a function that it's removed from the plan tree.
2708  */
2709 void
2711 {
2712  /*
2713  * For performance reasons, we don't bother to track built-in functions;
2714  * we just assume they'll never change (or at least not in ways that'd
2715  * invalidate plans using them). For this purpose we can consider a
2716  * built-in function to be one with OID less than FirstBootstrapObjectId.
2717  * Note that the OID generator guarantees never to generate such an OID
2718  * after startup, even at OID wraparound.
2719  */
2720  if (funcid >= (Oid) FirstBootstrapObjectId)
2721  {
2722  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2723 
2724  /*
2725  * It would work to use any syscache on pg_proc, but the easiest is
2726  * PROCOID since we already have the function's OID at hand. Note
2727  * that plancache.c knows we use PROCOID.
2728  */
2729  inval_item->cacheId = PROCOID;
2730  inval_item->hashValue = GetSysCacheHashValue1(PROCOID,
2731  ObjectIdGetDatum(funcid));
2732 
2733  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2734  }
2735 }
2736 
2737 /*
2738  * record_plan_type_dependency
2739  * Mark the current plan as depending on a particular type.
2740  *
2741  * This is exported so that eval_const_expressions can record a
2742  * dependency on a domain that it's removed a CoerceToDomain node for.
2743  *
2744  * We don't currently need to record dependencies on domains that the
2745  * plan contains CoerceToDomain nodes for, though that might change in
2746  * future. Hence, this isn't actually called in this module, though
2747  * someday fix_expr_common might call it.
2748  */
2749 void
2751 {
2752  /*
2753  * As in record_plan_function_dependency, ignore the possibility that
2754  * someone would change a built-in domain.
2755  */
2756  if (typid >= (Oid) FirstBootstrapObjectId)
2757  {
2758  PlanInvalItem *inval_item = makeNode(PlanInvalItem);
2759 
2760  /*
2761  * It would work to use any syscache on pg_type, but the easiest is
2762  * TYPEOID since we already have the type's OID at hand. Note that
2763  * plancache.c knows we use TYPEOID.
2764  */
2765  inval_item->cacheId = TYPEOID;
2766  inval_item->hashValue = GetSysCacheHashValue1(TYPEOID,
2767  ObjectIdGetDatum(typid));
2768 
2769  root->glob->invalItems = lappend(root->glob->invalItems, inval_item);
2770  }
2771 }
2772 
2773 /*
2774  * extract_query_dependencies
2775  * Given a rewritten, but not yet planned, query or queries
2776  * (i.e. a Query node or list of Query nodes), extract dependencies
2777  * just as set_plan_references would do. Also detect whether any
2778  * rewrite steps were affected by RLS.
2779  *
2780  * This is needed by plancache.c to handle invalidation of cached unplanned
2781  * queries.
2782  *
2783  * Note: this does not go through eval_const_expressions, and hence doesn't
2784  * reflect its additions of inlined functions and elided CoerceToDomain nodes
2785  * to the invalItems list. This is obviously OK for functions, since we'll
2786  * see them in the original query tree anyway. For domains, it's OK because
2787  * we don't care about domains unless they get elided. That is, a plan might
2788  * have domain dependencies that the query tree doesn't.
2789  */
2790 void
2792  List **relationOids,
2793  List **invalItems,
2794  bool *hasRowSecurity)
2795 {
2796  PlannerGlobal glob;
2797  PlannerInfo root;
2798 
2799  /* Make up dummy planner state so we can use this module's machinery */
2800  MemSet(&glob, 0, sizeof(glob));
2801  glob.type = T_PlannerGlobal;
2802  glob.relationOids = NIL;
2803  glob.invalItems = NIL;
2804  /* Hack: we use glob.dependsOnRole to collect hasRowSecurity flags */
2805  glob.dependsOnRole = false;
2806 
2807  MemSet(&root, 0, sizeof(root));
2808  root.type = T_PlannerInfo;
2809  root.glob = &glob;
2810 
2811  (void) extract_query_dependencies_walker(query, &root);
2812 
2813  *relationOids = glob.relationOids;
2814  *invalItems = glob.invalItems;
2815  *hasRowSecurity = glob.dependsOnRole;
2816 }
2817 
2818 /*
2819  * Tree walker for extract_query_dependencies.
2820  *
2821  * This is exported so that expression_planner_with_deps can call it on
2822  * simple expressions (post-planning, not before planning, in that case).
2823  * In that usage, glob.dependsOnRole isn't meaningful, but the relationOids
2824  * and invalItems lists are added to as needed.
2825  */
2826 bool
2828 {
2829  if (node == NULL)
2830  return false;
2831  Assert(!IsA(node, PlaceHolderVar));
2832  if (IsA(node, Query))
2833  {
2834  Query *query = (Query *) node;
2835  ListCell *lc;
2836 
2837  if (query->commandType == CMD_UTILITY)
2838  {
2839  /*
2840  * Ignore utility statements, except those (such as EXPLAIN) that
2841  * contain a parsed-but-not-planned query.
2842  */
2843  query = UtilityContainsQuery(query->utilityStmt);
2844  if (query == NULL)
2845  return false;
2846  }
2847 
2848  /* Remember if any Query has RLS quals applied by rewriter */
2849  if (query->hasRowSecurity)
2850  context->glob->dependsOnRole = true;
2851 
2852  /* Collect relation OIDs in this Query's rtable */
2853  foreach(lc, query->rtable)
2854  {
2855  RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
2856 
2857  if (rte->rtekind == RTE_RELATION)
2858  context->glob->relationOids =
2859  lappend_oid(context->glob->relationOids, rte->relid);
2860  else if (rte->rtekind == RTE_NAMEDTUPLESTORE &&
2861  OidIsValid(rte->relid))
2862  context->glob->relationOids =
2863  lappend_oid(context->glob->relationOids,
2864  rte->relid);
2865  }
2866 
2867  /* And recurse into the query's subexpressions */
2869  (void *) context, 0);
2870  }
2871  /* Extract function dependencies and check for regclass Consts */
2872  fix_expr_common(context, node);
2874  (void *) context);
2875 }
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:79
Plan plan
Definition: plannodes.h:344
#define IsA(nodeptr, _type_)
Definition: nodes.h:580
Query * parse
Definition: pathnodes.h:179
indexed_tlist * inner_itlist
Definition: setrefs.c:58
List * joinaliasvars
Definition: parsenodes.h:1051
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:982
#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:1607
Definition: nodes.h:81
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:968
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:3033
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:1757
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:1125
#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:1102
Param * param
Definition: pathnodes.h:2329
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:5397
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:529
List * custom_exprs
Definition: plannodes.h:646
List * appendRelations
Definition: pathnodes.h:125
List * list_concat(List *list1, const List *list2)
Definition: list.c:515
Definition: nodes.h:49
int errcode(int sqlerrcode)
Definition: elog.c:610
List * args
Definition: primnodes.h:319
Index prti
Definition: plannodes.h:1078
#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:1961
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:1475
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:983
List * lappend_oid(List *list, Oid datum)
Definition: list.c:357
#define OidIsValid(objectId)
Definition: c.h:644
#define DO_AGGSPLIT_COMBINE(as)
Definition: nodes.h:791
List * colcollations
Definition: parsenodes.h:1103
static Plan * set_append_references(PlannerInfo *root, Append *aplan, int rtoffset)
Definition: setrefs.c:1319
List * translated_vars
Definition: pathnodes.h:2257
List * values_lists
Definition: parsenodes.h:1074
List * plans
Definition: plannodes.h:229
static bool trivial_subqueryscan(SubqueryScan *plan)
Definition: setrefs.c:1105
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:2415
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:1184
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:2397
List * rootResultRelations
Definition: pathnodes.h:123
List * multiexpr_params
Definition: pathnodes.h:263
Query * UtilityContainsQuery(Node *parsetree)
Definition: utility.c:2063
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:709
AttrNumber varattno
Definition: setrefs.c:35
Node * startOffset
Definition: plannodes.h:850
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:1069
#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:984
Scan scan
Definition: plannodes.h:404
#define IS_DUMMY_REL(r)
Definition: pathnodes.h:1418
int num_vars
Definition: setrefs.c:42
static Node * fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
Definition: setrefs.c:2558
Definition: nodes.h:78
RelOptInfo * fetch_upper_rel(PlannerInfo *root, UpperRelationKind kind, Relids relids)
Definition: relnode.c:1192
#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:1497
PlannerGlobal * glob
Definition: pathnodes.h:181
Node * endOffset
Definition: plannodes.h:851
List * aggorder
Definition: primnodes.h:320
AttrNumber resno
Definition: primnodes.h:1408
#define FirstBootstrapObjectId
Definition: transam.h:154
List * fdw_recheck_quals
Definition: plannodes.h:620
TargetEntry * flatCopyTargetEntry(TargetEntry *src_tle)
Definition: makefuncs.c:271
List * joinrightcols
Definition: parsenodes.h:1053
static SPIPlanPtr splan
Definition: regress.c:259
static void set_customscan_references(PlannerInfo *root, CustomScan *cscan, int rtoffset)
Definition: setrefs.c:1253
static Plan * set_subqueryscan_references(PlannerInfo *root, SubqueryScan *plan, int rtoffset)
Definition: setrefs.c:1056
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:2542
List * bitmapqualorig
Definition: plannodes.h:479
TargetEntry * makeTargetEntry(Expr *expr, AttrNumber resno, char *resname, bool resjunk)
Definition: makefuncs.c:238
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:339
Index relid
Definition: pathnodes.h:693
List * cols
Definition: primnodes.h:362
Index varnosyn
Definition: primnodes.h:194
List * lappend(List *list, void *datum)
Definition: list.c:321
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:1738
List * invalItems
Definition: pathnodes.h:129
static Node * fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
Definition: setrefs.c:1669
static Plan * set_indexonlyscan_references(PlannerInfo *root, IndexOnlyScan *plan, int rtoffset)
Definition: setrefs.c:1015
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:1901
static Plan * clean_up_removed_plan_level(Plan *parent, Plan *child)
Definition: setrefs.c:1163
Bitmapset * bms_intersect(const Bitmapset *a, const Bitmapset *b)
Definition: bitmapset.c:259
List * hashkeys
Definition: plannodes.h:930
bool has_non_vars
Definition: setrefs.c:44
void record_plan_function_dependency(PlannerInfo *root, Oid funcid)
Definition: setrefs.c:2710
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:84
uint32 hashValue
Definition: plannodes.h:1248
static Var * search_indexed_tlist_for_non_var(Expr *node, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2293
static Node * convert_combining_aggrefs(Node *node, void *context)
Definition: setrefs.c:2016
Oid aggfnoid
Definition: primnodes.h:312
#define ereport(elevel,...)
Definition: elog.h:144
List * joinleftcols
Definition: parsenodes.h:1052
bool extract_query_dependencies_walker(Node *node, PlannerInfo *context)
Definition: setrefs.c:2827
static void fix_expr_common(PlannerInfo *root, Node *node)
Definition: setrefs.c:1519
#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:577
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:2325
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:2791
AggSplit aggsplit
Definition: plannodes.h:820
List * functions
Definition: parsenodes.h:1063
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:2253
Expr * expr
Definition: primnodes.h:1407
List * rowMarks
Definition: plannodes.h:969
static indexed_tlist * build_tlist_index(List *tlist)
Definition: setrefs.c:2152
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:2202
List * indexqualorig
Definition: plannodes.h:464
#define nodeTag(nodeptr)
Definition: nodes.h:534
List * targetlist
Definition: plannodes.h:142
RTEKind rtekind
Definition: parsenodes.h:976
Definition: nodes.h:85
static List * set_returning_clause_references(PlannerInfo *root, List *rlist, Plan *topplan, Index resultRelation, int rtoffset)
Definition: setrefs.c:2661
List * mergeplans
Definition: plannodes.h:276
List * finalrtable
Definition: pathnodes.h:117
Query * subquery
Definition: parsenodes.h:1011
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:82
#define elog(elevel,...)
Definition: elog.h:214
int i
static Node * fix_scan_expr(PlannerInfo *root, Node *node, int rtoffset)
Definition: setrefs.c:1637
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:816
Index child_relid
Definition: pathnodes.h:2230
Plan * set_plan_references(PlannerInfo *root, Plan *plan)
Definition: setrefs.c:223
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
Definition: relnode.c:374
#define copyObject(obj)
Definition: nodes.h:645
static Var * search_indexed_tlist_for_sortgroupref(Expr *node, Index sortgroupref, indexed_tlist *itlist, Index newvarno)
Definition: setrefs.c:2333
Index exclRelRTI
Definition: plannodes.h:240
List * coltypes
Definition: parsenodes.h:1101
Index parent_relid
Definition: pathnodes.h:2229
#define INDEX_VAR
Definition: primnodes.h:173
static Plan * set_mergeappend_references(PlannerInfo *root, MergeAppend *mplan, int rtoffset)
Definition: setrefs.c:1383
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:1006
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:2085
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:1444
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:2750
Bitmapset * fs_relids
Definition: plannodes.h:621
Definition: nodes.h:87
Plan plan
Definition: plannodes.h:683
List * tlist
Definition: setrefs.c:41