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