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