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