]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/plan/setrefs.c
Fix typo
[postgresql] / src / backend / optimizer / plan / setrefs.c
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-2018, 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 */
48 } indexed_tlist;
49
50 typedef struct
51 {
52         PlannerInfo *root;
53         int                     rtoffset;
54 } fix_scan_expr_context;
55
56 typedef struct
57 {
58         PlannerInfo *root;
59         indexed_tlist *outer_itlist;
60         indexed_tlist *inner_itlist;
61         Index           acceptable_rel;
62         int                     rtoffset;
63 } fix_join_expr_context;
64
65 typedef struct
66 {
67         PlannerInfo *root;
68         indexed_tlist *subplan_itlist;
69         Index           newvarno;
70         int                     rtoffset;
71 } fix_upper_expr_context;
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);
92 static Plan *set_indexonlyscan_references(PlannerInfo *root,
93                                                          IndexOnlyScan *plan,
94                                                          int rtoffset);
95 static Plan *set_subqueryscan_references(PlannerInfo *root,
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);
114 static Var *search_indexed_tlist_for_var(Var *var,
115                                                          indexed_tlist *itlist,
116                                                          Index newvarno,
117                                                          int rtoffset);
118 static Var *search_indexed_tlist_for_non_var(Expr *node,
119                                                                  indexed_tlist *itlist,
120                                                                  Index newvarno);
121 static Var *search_indexed_tlist_for_sortgroupref(Expr *node,
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);
139 static List *set_returning_clause_references(PlannerInfo *root,
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 *
214 set_plan_references(PlannerInfo *root, Plan *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         {
232                 PlanRowMark *rc = lfirst_node(PlanRowMark, lc);
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 ||
329                                                  IS_DUMMY_REL(fetch_upper_rel(rel->subroot,
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
342 flatten_unplanned_rtes(PlannerGlobal *glob, RangeTblEntry *rte)
343 {
344         /* Use query_tree_walker to find all RTEs in the parse tree */
345         (void) query_tree_walker(rte->subquery,
346                                                          flatten_rtes_walker,
347                                                          (void *) glob,
348                                                          QTW_EXAMINE_RTES);
349 }
350
351 static bool
352 flatten_rtes_walker(Node *node, PlannerGlobal *glob)
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,
369                                                                  flatten_rtes_walker,
370                                                                  (void *) glob,
371                                                                  QTW_EXAMINE_RTES);
372         }
373         return expression_tree_walker(node, flatten_rtes_walker,
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
388 add_rte_to_flat_rtable(PlannerGlobal *glob, RangeTblEntry *rte)
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          */
415         if (IS_SPECIAL_VARNO(list_length(glob->finalrtable)))
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                         {
506                                 BitmapIndexScan *splan = (BitmapIndexScan *) plan;
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;
599                 case T_NamedTuplestoreScan:
600                         {
601                                 NamedTuplestoreScan *splan = (NamedTuplestoreScan *) plan;
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                                          */
792                                         Assert(list_length(splan->returningLists) == list_length(splan->resultRelations));
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,
839                                                                           linitial_int(splan->resultRelations),
840                                                                           rtoffset);
841
842                                         splan->onConflictWhere = (Node *)
843                                                 fix_join_expr(root, (List *) splan->onConflictWhere,
844                                                                           NULL, itlist,
845                                                                           linitial_int(splan->resultRelations),
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                                  */
885                                 splan->resultRelIndex = list_length(root->glob->resultRelations);
886                                 root->glob->resultRelations =
887                                         list_concat(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 identified as such during the executor
896                                  * initialization.
897                                  */
898                                 if (splan->partitioned_rels != NIL)
899                                 {
900                                         root->glob->nonleafResultRelations =
901                                                 list_concat(root->glob->nonleafResultRelations,
902                                                                         list_copy(splan->partitioned_rels));
903                                         /* Remember where this root will be in the global list. */
904                                         splan->rootResultRelIndex =
905                                                 list_length(root->glob->rootResultRelations);
906                                         root->glob->rootResultRelations =
907                                                 lappend_int(root->glob->rootResultRelations,
908                                                                         linitial_int(splan->partitioned_rels));
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 *
1021 set_indexonlyscan_references(PlannerInfo *root,
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 *
1062 set_subqueryscan_references(PlannerInfo *root,
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
1134 trivial_subqueryscan(SubqueryScan *plan)
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
1189 set_foreignscan_references(PlannerInfo *root,
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                  */
1203                 indexed_tlist *itlist = build_tlist_index(fscan->fdw_scan_tlist);
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
1267 set_customscan_references(PlannerInfo *root,
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 */
1280                 indexed_tlist *itlist = build_tlist_index(cscan->custom_scan_tlist);
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 *
1342 copyVar(Var *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
1364 fix_expr_common(PlannerInfo *root, Node *node)
1365 {
1366         /* We assume callers won't call us on a NULL pointer */
1367         if (IsA(node, Aggref))
1368         {
1369                 record_plan_function_dependency(root,
1370                                                                                 ((Aggref *) node)->aggfnoid);
1371         }
1372         else if (IsA(node, WindowFunc))
1373         {
1374                 record_plan_function_dependency(root,
1375                                                                                 ((WindowFunc *) node)->winfnoid);
1376         }
1377         else if (IsA(node, FuncExpr))
1378         {
1379                 record_plan_function_dependency(root,
1380                                                                                 ((FuncExpr *) node)->funcid);
1381         }
1382         else if (IsA(node, OpExpr))
1383         {
1384                 set_opfuncid((OpExpr *) node);
1385                 record_plan_function_dependency(root,
1386                                                                                 ((OpExpr *) node)->opfuncid);
1387         }
1388         else if (IsA(node, DistinctExpr))
1389         {
1390                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1391                 record_plan_function_dependency(root,
1392                                                                                 ((DistinctExpr *) node)->opfuncid);
1393         }
1394         else if (IsA(node, NullIfExpr))
1395         {
1396                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1397                 record_plan_function_dependency(root,
1398                                                                                 ((NullIfExpr *) node)->opfuncid);
1399         }
1400         else if (IsA(node, ScalarArrayOpExpr))
1401         {
1402                 set_sa_opfuncid((ScalarArrayOpExpr *) node);
1403                 record_plan_function_dependency(root,
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,
1414                                                         DatumGetObjectId(con->constvalue));
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 *
1452 fix_param_node(PlannerInfo *root, Param *p)
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 *
1514 fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
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);
1578         return expression_tree_mutator(node, fix_scan_expr_mutator,
1579                                                                    (void *) context);
1580 }
1581
1582 static bool
1583 fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
1584 {
1585         if (node == NULL)
1586                 return false;
1587         Assert(!IsA(node, PlaceHolderVar));
1588         fix_expr_common(context->root, node);
1589         return expression_tree_walker(node, fix_scan_expr_walker,
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 *)
1755                                 search_indexed_tlist_for_sortgroupref(tle->expr,
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
1796 set_param_references(PlannerInfo *root, Plan *plan)
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                  */
1891                 mark_partial_aggref(child_agg, AGGSPLIT_INITIAL_SERIAL);
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));
1898                 mark_partial_aggref(parent_agg, AGGSPLIT_FINAL_DESERIAL);
1899
1900                 return (Node *) parent_agg;
1901         }
1902         return expression_tree_mutator(node, convert_combining_aggrefs,
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 *
1986 build_tlist_index(List *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 *)
1994                 palloc(offsetof(indexed_tlist, vars) +
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 *
2042 build_tlist_index_other_vars(List *tlist, Index ignore_rel)
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 *)
2050                 palloc(offsetof(indexed_tlist, vars) +
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 *
2094 search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
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 *
2134 search_indexed_tlist_for_non_var(Expr *node,
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 *
2174 search_indexed_tlist_for_sortgroupref(Expr *node,
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 *
2238 fix_join_expr(PlannerInfo *root,
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 *
2256 fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
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,
2354                                                                    fix_join_expr_mutator,
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 *
2389 fix_upper_expr(PlannerInfo *root,
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 *
2405 fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
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 &&
2466                  is_converted_whole_row_reference(node)))
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,
2476                                                                    fix_upper_expr_mutator,
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 *
2509 set_returning_clause_references(PlannerInfo *root,
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
2558 record_plan_function_dependency(PlannerInfo *root, Oid funcid)
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
2596 extract_query_dependencies(Node *query,
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
2624 extract_query_dependencies_walker(Node *node, PlannerInfo *context)
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 */
2667                 return query_tree_walker(query, extract_query_dependencies_walker,
2668                                                                  (void *) context, 0);
2669         }
2670         return expression_tree_walker(node, extract_query_dependencies_walker,
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
2680 is_converted_whole_row_reference(Node *node)
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 }