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