OSDN Git Service

Fix typo in sslmode documentation
[pg-rex/syncrep.git] / 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-2011, 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/clauses.h"
23 #include "optimizer/planmain.h"
24 #include "optimizer/tlist.h"
25 #include "parser/parsetree.h"
26 #include "utils/lsyscache.h"
27 #include "utils/syscache.h"
28
29
30 typedef struct
31 {
32         Index           varno;                  /* RT index of Var */
33         AttrNumber      varattno;               /* attr number of Var */
34         AttrNumber      resno;                  /* TLE position of Var */
35 } tlist_vinfo;
36
37 typedef struct
38 {
39         List       *tlist;                      /* underlying target list */
40         int                     num_vars;               /* number of plain Var tlist entries */
41         bool            has_ph_vars;    /* are there PlaceHolderVar entries? */
42         bool            has_non_vars;   /* are there other entries? */
43         /* array of num_vars entries: */
44         tlist_vinfo vars[1];            /* VARIABLE LENGTH ARRAY */
45 } indexed_tlist;                                /* VARIABLE LENGTH STRUCT */
46
47 typedef struct
48 {
49         PlannerGlobal *glob;
50         int                     rtoffset;
51 } fix_scan_expr_context;
52
53 typedef struct
54 {
55         PlannerGlobal *glob;
56         indexed_tlist *outer_itlist;
57         indexed_tlist *inner_itlist;
58         Index           acceptable_rel;
59         int                     rtoffset;
60 } fix_join_expr_context;
61
62 typedef struct
63 {
64         PlannerGlobal *glob;
65         indexed_tlist *subplan_itlist;
66         int                     rtoffset;
67 } fix_upper_expr_context;
68
69 /*
70  * Check if a Const node is a regclass value.  We accept plain OID too,
71  * since a regclass Const will get folded to that type if it's an argument
72  * to oideq or similar operators.  (This might result in some extraneous
73  * values in a plan's list of relation dependencies, but the worst result
74  * would be occasional useless replans.)
75  */
76 #define ISREGCLASSCONST(con) \
77         (((con)->consttype == REGCLASSOID || (con)->consttype == OIDOID) && \
78          !(con)->constisnull)
79
80 #define fix_scan_list(glob, lst, rtoffset) \
81         ((List *) fix_scan_expr(glob, (Node *) (lst), rtoffset))
82
83 static Plan *set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset);
84 static Plan *set_subqueryscan_references(PlannerGlobal *glob,
85                                                         SubqueryScan *plan,
86                                                         int rtoffset);
87 static bool trivial_subqueryscan(SubqueryScan *plan);
88 static Node *fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset);
89 static Node *fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context);
90 static bool fix_scan_expr_walker(Node *node, fix_scan_expr_context *context);
91 static void set_join_references(PlannerGlobal *glob, Join *join, int rtoffset);
92 static void set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset);
93 static void set_dummy_tlist_references(Plan *plan, int rtoffset);
94 static indexed_tlist *build_tlist_index(List *tlist);
95 static Var *search_indexed_tlist_for_var(Var *var,
96                                                          indexed_tlist *itlist,
97                                                          Index newvarno,
98                                                          int rtoffset);
99 static Var *search_indexed_tlist_for_non_var(Node *node,
100                                                                  indexed_tlist *itlist,
101                                                                  Index newvarno);
102 static Var *search_indexed_tlist_for_sortgroupref(Node *node,
103                                                                           Index sortgroupref,
104                                                                           indexed_tlist *itlist,
105                                                                           Index newvarno);
106 static List *fix_join_expr(PlannerGlobal *glob,
107                           List *clauses,
108                           indexed_tlist *outer_itlist,
109                           indexed_tlist *inner_itlist,
110                           Index acceptable_rel, int rtoffset);
111 static Node *fix_join_expr_mutator(Node *node,
112                                           fix_join_expr_context *context);
113 static Node *fix_upper_expr(PlannerGlobal *glob,
114                            Node *node,
115                            indexed_tlist *subplan_itlist,
116                            int rtoffset);
117 static Node *fix_upper_expr_mutator(Node *node,
118                                            fix_upper_expr_context *context);
119 static bool fix_opfuncids_walker(Node *node, void *context);
120 static bool extract_query_dependencies_walker(Node *node,
121                                                                   PlannerGlobal *context);
122
123
124 /*****************************************************************************
125  *
126  *              SUBPLAN REFERENCES
127  *
128  *****************************************************************************/
129
130 /*
131  * set_plan_references
132  *
133  * This is the final processing pass of the planner/optimizer.  The plan
134  * tree is complete; we just have to adjust some representational details
135  * for the convenience of the executor:
136  *
137  * 1. We flatten the various subquery rangetables into a single list, and
138  * zero out RangeTblEntry fields that are not useful to the executor.
139  *
140  * 2. We adjust Vars in scan nodes to be consistent with the flat rangetable.
141  *
142  * 3. We adjust Vars in upper plan nodes to refer to the outputs of their
143  * subplans.
144  *
145  * 4. We compute regproc OIDs for operators (ie, we look up the function
146  * that implements each op).
147  *
148  * 5. We create lists of specific objects that the plan depends on.
149  * This will be used by plancache.c to drive invalidation of cached plans.
150  * Relation dependencies are represented by OIDs, and everything else by
151  * PlanInvalItems (this distinction is motivated by the shared-inval APIs).
152  * Currently, relations and user-defined functions are the only types of
153  * objects that are explicitly tracked this way.
154  *
155  * We also perform one final optimization step, which is to delete
156  * SubqueryScan plan nodes that aren't doing anything useful (ie, have
157  * no qual and a no-op targetlist).  The reason for doing this last is that
158  * it can't readily be done before set_plan_references, because it would
159  * break set_upper_references: the Vars in the subquery's top tlist
160  * wouldn't match up with the Vars in the outer plan tree.  The SubqueryScan
161  * serves a necessary function as a buffer between outer query and subquery
162  * variable numbering ... but after we've flattened the rangetable this is
163  * no longer a problem, since then there's only one rtindex namespace.
164  *
165  * set_plan_references recursively traverses the whole plan tree.
166  *
167  * Inputs:
168  *      glob: global data for planner run
169  *      plan: the topmost node of the plan
170  *      rtable: the rangetable for the current subquery
171  *      rowmarks: the PlanRowMark list for the current subquery
172  *
173  * The return value is normally the same Plan node passed in, but can be
174  * different when the passed-in Plan is a SubqueryScan we decide isn't needed.
175  *
176  * The flattened rangetable entries are appended to glob->finalrtable.
177  * Also, rowmarks entries are appended to glob->finalrowmarks, and the
178  * RT indexes of ModifyTable result relations to glob->resultRelations.
179  * Plan dependencies are appended to glob->relationOids (for relations)
180  * and glob->invalItems (for everything else).
181  *
182  * Notice that we modify Plan nodes in-place, but use expression_tree_mutator
183  * to process targetlist and qual expressions.  We can assume that the Plan
184  * nodes were just built by the planner and are not multiply referenced, but
185  * it's not so safe to assume that for expression tree nodes.
186  */
187 Plan *
188 set_plan_references(PlannerGlobal *glob, Plan *plan,
189                                         List *rtable, List *rowmarks)
190 {
191         int                     rtoffset = list_length(glob->finalrtable);
192         ListCell   *lc;
193
194         /*
195          * In the flat rangetable, we zero out substructure pointers that are not
196          * needed by the executor; this reduces the storage space and copying cost
197          * for cached plans.  We keep only the alias and eref Alias fields, which
198          * are needed by EXPLAIN, and the selectedCols and modifiedCols bitmaps,
199          * which are needed for executor-startup permissions checking and for
200          * trigger event checking.
201          */
202         foreach(lc, rtable)
203         {
204                 RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
205                 RangeTblEntry *newrte;
206
207                 /* flat copy to duplicate all the scalar fields */
208                 newrte = (RangeTblEntry *) palloc(sizeof(RangeTblEntry));
209                 memcpy(newrte, rte, sizeof(RangeTblEntry));
210
211                 /* zap unneeded sub-structure */
212                 newrte->subquery = NULL;
213                 newrte->joinaliasvars = NIL;
214                 newrte->funcexpr = NULL;
215                 newrte->funccoltypes = NIL;
216                 newrte->funccoltypmods = NIL;
217                 newrte->funccolcollations = NIL;
218                 newrte->values_lists = NIL;
219                 newrte->values_collations = NIL;
220                 newrte->ctecoltypes = NIL;
221                 newrte->ctecoltypmods = NIL;
222                 newrte->ctecolcollations = NIL;
223
224                 glob->finalrtable = lappend(glob->finalrtable, newrte);
225
226                 /*
227                  * If it's a plain relation RTE, add the table to relationOids.
228                  *
229                  * We do this even though the RTE might be unreferenced in the plan
230                  * tree; this would correspond to cases such as views that were
231                  * expanded, child tables that were eliminated by constraint
232                  * exclusion, etc.      Schema invalidation on such a rel must still force
233                  * rebuilding of the plan.
234                  *
235                  * Note we don't bother to avoid duplicate list entries.  We could,
236                  * but it would probably cost more cycles than it would save.
237                  */
238                 if (newrte->rtekind == RTE_RELATION)
239                         glob->relationOids = lappend_oid(glob->relationOids,
240                                                                                          newrte->relid);
241         }
242
243         /*
244          * Adjust RT indexes of PlanRowMarks and add to final rowmarks list
245          */
246         foreach(lc, rowmarks)
247         {
248                 PlanRowMark *rc = (PlanRowMark *) lfirst(lc);
249                 PlanRowMark *newrc;
250
251                 Assert(IsA(rc, PlanRowMark));
252
253                 /* flat copy is enough since all fields are scalars */
254                 newrc = (PlanRowMark *) palloc(sizeof(PlanRowMark));
255                 memcpy(newrc, rc, sizeof(PlanRowMark));
256
257                 /* adjust indexes ... but *not* the rowmarkId */
258                 newrc->rti += rtoffset;
259                 newrc->prti += rtoffset;
260
261                 glob->finalrowmarks = lappend(glob->finalrowmarks, newrc);
262         }
263
264         /* Now fix the Plan tree */
265         return set_plan_refs(glob, plan, rtoffset);
266 }
267
268 /*
269  * set_plan_refs: recurse through the Plan nodes of a single subquery level
270  */
271 static Plan *
272 set_plan_refs(PlannerGlobal *glob, Plan *plan, int rtoffset)
273 {
274         ListCell   *l;
275
276         if (plan == NULL)
277                 return NULL;
278
279         /*
280          * Plan-type-specific fixes
281          */
282         switch (nodeTag(plan))
283         {
284                 case T_SeqScan:
285                         {
286                                 SeqScan    *splan = (SeqScan *) plan;
287
288                                 splan->scanrelid += rtoffset;
289                                 splan->plan.targetlist =
290                                         fix_scan_list(glob, splan->plan.targetlist, rtoffset);
291                                 splan->plan.qual =
292                                         fix_scan_list(glob, splan->plan.qual, rtoffset);
293                         }
294                         break;
295                 case T_IndexScan:
296                         {
297                                 IndexScan  *splan = (IndexScan *) plan;
298
299                                 splan->scan.scanrelid += rtoffset;
300                                 splan->scan.plan.targetlist =
301                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
302                                 splan->scan.plan.qual =
303                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
304                                 splan->indexqual =
305                                         fix_scan_list(glob, splan->indexqual, rtoffset);
306                                 splan->indexqualorig =
307                                         fix_scan_list(glob, splan->indexqualorig, rtoffset);
308                                 splan->indexorderby =
309                                         fix_scan_list(glob, splan->indexorderby, rtoffset);
310                                 splan->indexorderbyorig =
311                                         fix_scan_list(glob, splan->indexorderbyorig, rtoffset);
312                         }
313                         break;
314                 case T_BitmapIndexScan:
315                         {
316                                 BitmapIndexScan *splan = (BitmapIndexScan *) plan;
317
318                                 splan->scan.scanrelid += rtoffset;
319                                 /* no need to fix targetlist and qual */
320                                 Assert(splan->scan.plan.targetlist == NIL);
321                                 Assert(splan->scan.plan.qual == NIL);
322                                 splan->indexqual =
323                                         fix_scan_list(glob, splan->indexqual, rtoffset);
324                                 splan->indexqualorig =
325                                         fix_scan_list(glob, splan->indexqualorig, rtoffset);
326                         }
327                         break;
328                 case T_BitmapHeapScan:
329                         {
330                                 BitmapHeapScan *splan = (BitmapHeapScan *) plan;
331
332                                 splan->scan.scanrelid += rtoffset;
333                                 splan->scan.plan.targetlist =
334                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
335                                 splan->scan.plan.qual =
336                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
337                                 splan->bitmapqualorig =
338                                         fix_scan_list(glob, splan->bitmapqualorig, rtoffset);
339                         }
340                         break;
341                 case T_TidScan:
342                         {
343                                 TidScan    *splan = (TidScan *) plan;
344
345                                 splan->scan.scanrelid += rtoffset;
346                                 splan->scan.plan.targetlist =
347                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
348                                 splan->scan.plan.qual =
349                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
350                                 splan->tidquals =
351                                         fix_scan_list(glob, splan->tidquals, rtoffset);
352                         }
353                         break;
354                 case T_SubqueryScan:
355                         /* Needs special treatment, see comments below */
356                         return set_subqueryscan_references(glob,
357                                                                                            (SubqueryScan *) plan,
358                                                                                            rtoffset);
359                 case T_FunctionScan:
360                         {
361                                 FunctionScan *splan = (FunctionScan *) plan;
362
363                                 splan->scan.scanrelid += rtoffset;
364                                 splan->scan.plan.targetlist =
365                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
366                                 splan->scan.plan.qual =
367                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
368                                 splan->funcexpr =
369                                         fix_scan_expr(glob, splan->funcexpr, rtoffset);
370                         }
371                         break;
372                 case T_ValuesScan:
373                         {
374                                 ValuesScan *splan = (ValuesScan *) plan;
375
376                                 splan->scan.scanrelid += rtoffset;
377                                 splan->scan.plan.targetlist =
378                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
379                                 splan->scan.plan.qual =
380                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
381                                 splan->values_lists =
382                                         fix_scan_list(glob, splan->values_lists, rtoffset);
383                         }
384                         break;
385                 case T_CteScan:
386                         {
387                                 CteScan    *splan = (CteScan *) plan;
388
389                                 splan->scan.scanrelid += rtoffset;
390                                 splan->scan.plan.targetlist =
391                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
392                                 splan->scan.plan.qual =
393                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
394                         }
395                         break;
396                 case T_WorkTableScan:
397                         {
398                                 WorkTableScan *splan = (WorkTableScan *) plan;
399
400                                 splan->scan.scanrelid += rtoffset;
401                                 splan->scan.plan.targetlist =
402                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
403                                 splan->scan.plan.qual =
404                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
405                         }
406                         break;
407                 case T_ForeignScan:
408                         {
409                                 ForeignScan *splan = (ForeignScan *) plan;
410
411                                 splan->scan.scanrelid += rtoffset;
412                                 splan->scan.plan.targetlist =
413                                         fix_scan_list(glob, splan->scan.plan.targetlist, rtoffset);
414                                 splan->scan.plan.qual =
415                                         fix_scan_list(glob, splan->scan.plan.qual, rtoffset);
416                         }
417                         break;
418
419                 case T_NestLoop:
420                 case T_MergeJoin:
421                 case T_HashJoin:
422                         set_join_references(glob, (Join *) plan, rtoffset);
423                         break;
424
425                 case T_Hash:
426                 case T_Material:
427                 case T_Sort:
428                 case T_Unique:
429                 case T_SetOp:
430
431                         /*
432                          * These plan types don't actually bother to evaluate their
433                          * targetlists, because they just return their unmodified input
434                          * tuples.      Even though the targetlist won't be used by the
435                          * executor, we fix it up for possible use by EXPLAIN (not to
436                          * mention ease of debugging --- wrong varnos are very confusing).
437                          */
438                         set_dummy_tlist_references(plan, rtoffset);
439
440                         /*
441                          * Since these plan types don't check quals either, we should not
442                          * find any qual expression attached to them.
443                          */
444                         Assert(plan->qual == NIL);
445                         break;
446                 case T_LockRows:
447                         {
448                                 LockRows   *splan = (LockRows *) plan;
449
450                                 /*
451                                  * Like the plan types above, LockRows doesn't evaluate its
452                                  * tlist or quals.      But we have to fix up the RT indexes in
453                                  * its rowmarks.
454                                  */
455                                 set_dummy_tlist_references(plan, rtoffset);
456                                 Assert(splan->plan.qual == NIL);
457
458                                 foreach(l, splan->rowMarks)
459                                 {
460                                         PlanRowMark *rc = (PlanRowMark *) lfirst(l);
461
462                                         rc->rti += rtoffset;
463                                         rc->prti += rtoffset;
464                                 }
465                         }
466                         break;
467                 case T_Limit:
468                         {
469                                 Limit      *splan = (Limit *) plan;
470
471                                 /*
472                                  * Like the plan types above, Limit doesn't evaluate its tlist
473                                  * or quals.  It does have live expressions for limit/offset,
474                                  * however; and those cannot contain subplan variable refs, so
475                                  * fix_scan_expr works for them.
476                                  */
477                                 set_dummy_tlist_references(plan, rtoffset);
478                                 Assert(splan->plan.qual == NIL);
479
480                                 splan->limitOffset =
481                                         fix_scan_expr(glob, splan->limitOffset, rtoffset);
482                                 splan->limitCount =
483                                         fix_scan_expr(glob, splan->limitCount, rtoffset);
484                         }
485                         break;
486                 case T_Agg:
487                 case T_Group:
488                         set_upper_references(glob, plan, rtoffset);
489                         break;
490                 case T_WindowAgg:
491                         {
492                                 WindowAgg  *wplan = (WindowAgg *) plan;
493
494                                 set_upper_references(glob, plan, rtoffset);
495
496                                 /*
497                                  * Like Limit node limit/offset expressions, WindowAgg has
498                                  * frame offset expressions, which cannot contain subplan
499                                  * variable refs, so fix_scan_expr works for them.
500                                  */
501                                 wplan->startOffset =
502                                         fix_scan_expr(glob, wplan->startOffset, rtoffset);
503                                 wplan->endOffset =
504                                         fix_scan_expr(glob, wplan->endOffset, rtoffset);
505                         }
506                         break;
507                 case T_Result:
508                         {
509                                 Result     *splan = (Result *) plan;
510
511                                 /*
512                                  * Result may or may not have a subplan; if not, it's more
513                                  * like a scan node than an upper node.
514                                  */
515                                 if (splan->plan.lefttree != NULL)
516                                         set_upper_references(glob, plan, rtoffset);
517                                 else
518                                 {
519                                         splan->plan.targetlist =
520                                                 fix_scan_list(glob, splan->plan.targetlist, rtoffset);
521                                         splan->plan.qual =
522                                                 fix_scan_list(glob, splan->plan.qual, rtoffset);
523                                 }
524                                 /* resconstantqual can't contain any subplan variable refs */
525                                 splan->resconstantqual =
526                                         fix_scan_expr(glob, splan->resconstantqual, rtoffset);
527                         }
528                         break;
529                 case T_ModifyTable:
530                         {
531                                 ModifyTable *splan = (ModifyTable *) plan;
532
533                                 /*
534                                  * planner.c already called set_returning_clause_references,
535                                  * so we should not process either the targetlist or the
536                                  * returningLists.
537                                  */
538                                 Assert(splan->plan.qual == NIL);
539
540                                 foreach(l, splan->resultRelations)
541                                 {
542                                         lfirst_int(l) += rtoffset;
543                                 }
544                                 foreach(l, splan->rowMarks)
545                                 {
546                                         PlanRowMark *rc = (PlanRowMark *) lfirst(l);
547
548                                         rc->rti += rtoffset;
549                                         rc->prti += rtoffset;
550                                 }
551                                 foreach(l, splan->plans)
552                                 {
553                                         lfirst(l) = set_plan_refs(glob,
554                                                                                           (Plan *) lfirst(l),
555                                                                                           rtoffset);
556                                 }
557
558                                 /*
559                                  * Append this ModifyTable node's final result relation RT
560                                  * index(es) to the global list for the plan, and set its
561                                  * resultRelIndex to reflect their starting position in the
562                                  * global list.
563                                  */
564                                 splan->resultRelIndex = list_length(glob->resultRelations);
565                                 glob->resultRelations =
566                                         list_concat(glob->resultRelations,
567                                                                 list_copy(splan->resultRelations));
568                         }
569                         break;
570                 case T_Append:
571                         {
572                                 Append     *splan = (Append *) plan;
573
574                                 /*
575                                  * Append, like Sort et al, doesn't actually evaluate its
576                                  * targetlist or check quals.
577                                  */
578                                 set_dummy_tlist_references(plan, rtoffset);
579                                 Assert(splan->plan.qual == NIL);
580                                 foreach(l, splan->appendplans)
581                                 {
582                                         lfirst(l) = set_plan_refs(glob,
583                                                                                           (Plan *) lfirst(l),
584                                                                                           rtoffset);
585                                 }
586                         }
587                         break;
588                 case T_MergeAppend:
589                         {
590                                 MergeAppend *splan = (MergeAppend *) plan;
591
592                                 /*
593                                  * MergeAppend, like Sort et al, doesn't actually evaluate its
594                                  * targetlist or check quals.
595                                  */
596                                 set_dummy_tlist_references(plan, rtoffset);
597                                 Assert(splan->plan.qual == NIL);
598                                 foreach(l, splan->mergeplans)
599                                 {
600                                         lfirst(l) = set_plan_refs(glob,
601                                                                                           (Plan *) lfirst(l),
602                                                                                           rtoffset);
603                                 }
604                         }
605                         break;
606                 case T_RecursiveUnion:
607                         /* This doesn't evaluate targetlist or check quals either */
608                         set_dummy_tlist_references(plan, rtoffset);
609                         Assert(plan->qual == NIL);
610                         break;
611                 case T_BitmapAnd:
612                         {
613                                 BitmapAnd  *splan = (BitmapAnd *) plan;
614
615                                 /* BitmapAnd works like Append, but has no tlist */
616                                 Assert(splan->plan.targetlist == NIL);
617                                 Assert(splan->plan.qual == NIL);
618                                 foreach(l, splan->bitmapplans)
619                                 {
620                                         lfirst(l) = set_plan_refs(glob,
621                                                                                           (Plan *) lfirst(l),
622                                                                                           rtoffset);
623                                 }
624                         }
625                         break;
626                 case T_BitmapOr:
627                         {
628                                 BitmapOr   *splan = (BitmapOr *) plan;
629
630                                 /* BitmapOr works like Append, but has no tlist */
631                                 Assert(splan->plan.targetlist == NIL);
632                                 Assert(splan->plan.qual == NIL);
633                                 foreach(l, splan->bitmapplans)
634                                 {
635                                         lfirst(l) = set_plan_refs(glob,
636                                                                                           (Plan *) lfirst(l),
637                                                                                           rtoffset);
638                                 }
639                         }
640                         break;
641                 default:
642                         elog(ERROR, "unrecognized node type: %d",
643                                  (int) nodeTag(plan));
644                         break;
645         }
646
647         /*
648          * Now recurse into child plans, if any
649          *
650          * NOTE: it is essential that we recurse into child plans AFTER we set
651          * subplan references in this plan's tlist and quals.  If we did the
652          * reference-adjustments bottom-up, then we would fail to match this
653          * plan's var nodes against the already-modified nodes of the children.
654          */
655         plan->lefttree = set_plan_refs(glob, plan->lefttree, rtoffset);
656         plan->righttree = set_plan_refs(glob, plan->righttree, rtoffset);
657
658         return plan;
659 }
660
661 /*
662  * set_subqueryscan_references
663  *              Do set_plan_references processing on a SubqueryScan
664  *
665  * We try to strip out the SubqueryScan entirely; if we can't, we have
666  * to do the normal processing on it.
667  */
668 static Plan *
669 set_subqueryscan_references(PlannerGlobal *glob,
670                                                         SubqueryScan *plan,
671                                                         int rtoffset)
672 {
673         Plan       *result;
674
675         /* First, recursively process the subplan */
676         plan->subplan = set_plan_references(glob, plan->subplan,
677                                                                                 plan->subrtable, plan->subrowmark);
678
679         /* subrtable/subrowmark are no longer needed in the plan tree */
680         plan->subrtable = NIL;
681         plan->subrowmark = NIL;
682
683         if (trivial_subqueryscan(plan))
684         {
685                 /*
686                  * We can omit the SubqueryScan node and just pull up the subplan.
687                  */
688                 ListCell   *lp,
689                                    *lc;
690
691                 result = plan->subplan;
692
693                 /* We have to be sure we don't lose any initplans */
694                 result->initPlan = list_concat(plan->scan.plan.initPlan,
695                                                                            result->initPlan);
696
697                 /*
698                  * We also have to transfer the SubqueryScan's result-column names
699                  * into the subplan, else columns sent to client will be improperly
700                  * labeled if this is the topmost plan level.  Copy the "source
701                  * column" information too.
702                  */
703                 forboth(lp, plan->scan.plan.targetlist, lc, result->targetlist)
704                 {
705                         TargetEntry *ptle = (TargetEntry *) lfirst(lp);
706                         TargetEntry *ctle = (TargetEntry *) lfirst(lc);
707
708                         ctle->resname = ptle->resname;
709                         ctle->resorigtbl = ptle->resorigtbl;
710                         ctle->resorigcol = ptle->resorigcol;
711                 }
712         }
713         else
714         {
715                 /*
716                  * Keep the SubqueryScan node.  We have to do the processing that
717                  * set_plan_references would otherwise have done on it.  Notice we do
718                  * not do set_upper_references() here, because a SubqueryScan will
719                  * always have been created with correct references to its subplan's
720                  * outputs to begin with.
721                  */
722                 plan->scan.scanrelid += rtoffset;
723                 plan->scan.plan.targetlist =
724                         fix_scan_list(glob, plan->scan.plan.targetlist, rtoffset);
725                 plan->scan.plan.qual =
726                         fix_scan_list(glob, plan->scan.plan.qual, rtoffset);
727
728                 result = (Plan *) plan;
729         }
730
731         return result;
732 }
733
734 /*
735  * trivial_subqueryscan
736  *              Detect whether a SubqueryScan can be deleted from the plan tree.
737  *
738  * We can delete it if it has no qual to check and the targetlist just
739  * regurgitates the output of the child plan.
740  */
741 static bool
742 trivial_subqueryscan(SubqueryScan *plan)
743 {
744         int                     attrno;
745         ListCell   *lp,
746                            *lc;
747
748         if (plan->scan.plan.qual != NIL)
749                 return false;
750
751         if (list_length(plan->scan.plan.targetlist) !=
752                 list_length(plan->subplan->targetlist))
753                 return false;                   /* tlists not same length */
754
755         attrno = 1;
756         forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
757         {
758                 TargetEntry *ptle = (TargetEntry *) lfirst(lp);
759                 TargetEntry *ctle = (TargetEntry *) lfirst(lc);
760
761                 if (ptle->resjunk != ctle->resjunk)
762                         return false;           /* tlist doesn't match junk status */
763
764                 /*
765                  * We accept either a Var referencing the corresponding element of the
766                  * subplan tlist, or a Const equaling the subplan element. See
767                  * generate_setop_tlist() for motivation.
768                  */
769                 if (ptle->expr && IsA(ptle->expr, Var))
770                 {
771                         Var                *var = (Var *) ptle->expr;
772
773                         Assert(var->varno == plan->scan.scanrelid);
774                         Assert(var->varlevelsup == 0);
775                         if (var->varattno != attrno)
776                                 return false;   /* out of order */
777                 }
778                 else if (ptle->expr && IsA(ptle->expr, Const))
779                 {
780                         if (!equal(ptle->expr, ctle->expr))
781                                 return false;
782                 }
783                 else
784                         return false;
785
786                 attrno++;
787         }
788
789         return true;
790 }
791
792 /*
793  * copyVar
794  *              Copy a Var node.
795  *
796  * fix_scan_expr and friends do this enough times that it's worth having
797  * a bespoke routine instead of using the generic copyObject() function.
798  */
799 static inline Var *
800 copyVar(Var *var)
801 {
802         Var                *newvar = (Var *) palloc(sizeof(Var));
803
804         *newvar = *var;
805         return newvar;
806 }
807
808 /*
809  * fix_expr_common
810  *              Do generic set_plan_references processing on an expression node
811  *
812  * This is code that is common to all variants of expression-fixing.
813  * We must look up operator opcode info for OpExpr and related nodes,
814  * add OIDs from regclass Const nodes into glob->relationOids,
815  * and add catalog TIDs for user-defined functions into glob->invalItems.
816  *
817  * We assume it's okay to update opcode info in-place.  So this could possibly
818  * scribble on the planner's input data structures, but it's OK.
819  */
820 static void
821 fix_expr_common(PlannerGlobal *glob, Node *node)
822 {
823         /* We assume callers won't call us on a NULL pointer */
824         if (IsA(node, Aggref))
825         {
826                 record_plan_function_dependency(glob,
827                                                                                 ((Aggref *) node)->aggfnoid);
828         }
829         else if (IsA(node, WindowFunc))
830         {
831                 record_plan_function_dependency(glob,
832                                                                                 ((WindowFunc *) node)->winfnoid);
833         }
834         else if (IsA(node, FuncExpr))
835         {
836                 record_plan_function_dependency(glob,
837                                                                                 ((FuncExpr *) node)->funcid);
838         }
839         else if (IsA(node, OpExpr))
840         {
841                 set_opfuncid((OpExpr *) node);
842                 record_plan_function_dependency(glob,
843                                                                                 ((OpExpr *) node)->opfuncid);
844         }
845         else if (IsA(node, DistinctExpr))
846         {
847                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
848                 record_plan_function_dependency(glob,
849                                                                                 ((DistinctExpr *) node)->opfuncid);
850         }
851         else if (IsA(node, NullIfExpr))
852         {
853                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
854                 record_plan_function_dependency(glob,
855                                                                                 ((NullIfExpr *) node)->opfuncid);
856         }
857         else if (IsA(node, ScalarArrayOpExpr))
858         {
859                 set_sa_opfuncid((ScalarArrayOpExpr *) node);
860                 record_plan_function_dependency(glob,
861                                                                          ((ScalarArrayOpExpr *) node)->opfuncid);
862         }
863         else if (IsA(node, ArrayCoerceExpr))
864         {
865                 if (OidIsValid(((ArrayCoerceExpr *) node)->elemfuncid))
866                         record_plan_function_dependency(glob,
867                                                                          ((ArrayCoerceExpr *) node)->elemfuncid);
868         }
869         else if (IsA(node, Const))
870         {
871                 Const      *con = (Const *) node;
872
873                 /* Check for regclass reference */
874                 if (ISREGCLASSCONST(con))
875                         glob->relationOids =
876                                 lappend_oid(glob->relationOids,
877                                                         DatumGetObjectId(con->constvalue));
878         }
879 }
880
881 /*
882  * fix_scan_expr
883  *              Do set_plan_references processing on a scan-level expression
884  *
885  * This consists of incrementing all Vars' varnos by rtoffset,
886  * looking up operator opcode info for OpExpr and related nodes,
887  * and adding OIDs from regclass Const nodes into glob->relationOids.
888  */
889 static Node *
890 fix_scan_expr(PlannerGlobal *glob, Node *node, int rtoffset)
891 {
892         fix_scan_expr_context context;
893
894         context.glob = glob;
895         context.rtoffset = rtoffset;
896
897         if (rtoffset != 0 || glob->lastPHId != 0)
898         {
899                 return fix_scan_expr_mutator(node, &context);
900         }
901         else
902         {
903                 /*
904                  * If rtoffset == 0, we don't need to change any Vars, and if there
905                  * are no placeholders anywhere we won't need to remove them.  Then
906                  * it's OK to just scribble on the input node tree instead of copying
907                  * (since the only change, filling in any unset opfuncid fields, is
908                  * harmless).  This saves just enough cycles to be noticeable on
909                  * trivial queries.
910                  */
911                 (void) fix_scan_expr_walker(node, &context);
912                 return node;
913         }
914 }
915
916 static Node *
917 fix_scan_expr_mutator(Node *node, fix_scan_expr_context *context)
918 {
919         if (node == NULL)
920                 return NULL;
921         if (IsA(node, Var))
922         {
923                 Var                *var = copyVar((Var *) node);
924
925                 Assert(var->varlevelsup == 0);
926
927                 /*
928                  * We should not see any Vars marked INNER or OUTER.
929                  */
930                 Assert(var->varno != INNER);
931                 Assert(var->varno != OUTER);
932                 var->varno += context->rtoffset;
933                 if (var->varnoold > 0)
934                         var->varnoold += context->rtoffset;
935                 return (Node *) var;
936         }
937         if (IsA(node, CurrentOfExpr))
938         {
939                 CurrentOfExpr *cexpr = (CurrentOfExpr *) copyObject(node);
940
941                 Assert(cexpr->cvarno != INNER);
942                 Assert(cexpr->cvarno != OUTER);
943                 cexpr->cvarno += context->rtoffset;
944                 return (Node *) cexpr;
945         }
946         if (IsA(node, PlaceHolderVar))
947         {
948                 /* At scan level, we should always just evaluate the contained expr */
949                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
950
951                 return fix_scan_expr_mutator((Node *) phv->phexpr, context);
952         }
953         fix_expr_common(context->glob, node);
954         return expression_tree_mutator(node, fix_scan_expr_mutator,
955                                                                    (void *) context);
956 }
957
958 static bool
959 fix_scan_expr_walker(Node *node, fix_scan_expr_context *context)
960 {
961         if (node == NULL)
962                 return false;
963         Assert(!IsA(node, PlaceHolderVar));
964         fix_expr_common(context->glob, node);
965         return expression_tree_walker(node, fix_scan_expr_walker,
966                                                                   (void *) context);
967 }
968
969 /*
970  * set_join_references
971  *        Modify the target list and quals of a join node to reference its
972  *        subplans, by setting the varnos to OUTER or INNER and setting attno
973  *        values to the result domain number of either the corresponding outer
974  *        or inner join tuple item.  Also perform opcode lookup for these
975  *        expressions. and add regclass OIDs to glob->relationOids.
976  */
977 static void
978 set_join_references(PlannerGlobal *glob, Join *join, int rtoffset)
979 {
980         Plan       *outer_plan = join->plan.lefttree;
981         Plan       *inner_plan = join->plan.righttree;
982         indexed_tlist *outer_itlist;
983         indexed_tlist *inner_itlist;
984
985         outer_itlist = build_tlist_index(outer_plan->targetlist);
986         inner_itlist = build_tlist_index(inner_plan->targetlist);
987
988         /* All join plans have tlist, qual, and joinqual */
989         join->plan.targetlist = fix_join_expr(glob,
990                                                                                   join->plan.targetlist,
991                                                                                   outer_itlist,
992                                                                                   inner_itlist,
993                                                                                   (Index) 0,
994                                                                                   rtoffset);
995         join->plan.qual = fix_join_expr(glob,
996                                                                         join->plan.qual,
997                                                                         outer_itlist,
998                                                                         inner_itlist,
999                                                                         (Index) 0,
1000                                                                         rtoffset);
1001         join->joinqual = fix_join_expr(glob,
1002                                                                    join->joinqual,
1003                                                                    outer_itlist,
1004                                                                    inner_itlist,
1005                                                                    (Index) 0,
1006                                                                    rtoffset);
1007
1008         /* Now do join-type-specific stuff */
1009         if (IsA(join, NestLoop))
1010         {
1011                 NestLoop   *nl = (NestLoop *) join;
1012                 ListCell   *lc;
1013
1014                 foreach(lc, nl->nestParams)
1015                 {
1016                         NestLoopParam *nlp = (NestLoopParam *) lfirst(lc);
1017
1018                         nlp->paramval = (Var *) fix_upper_expr(glob,
1019                                                                                                    (Node *) nlp->paramval,
1020                                                                                                    outer_itlist,
1021                                                                                                    rtoffset);
1022                 }
1023         }
1024         else if (IsA(join, MergeJoin))
1025         {
1026                 MergeJoin  *mj = (MergeJoin *) join;
1027
1028                 mj->mergeclauses = fix_join_expr(glob,
1029                                                                                  mj->mergeclauses,
1030                                                                                  outer_itlist,
1031                                                                                  inner_itlist,
1032                                                                                  (Index) 0,
1033                                                                                  rtoffset);
1034         }
1035         else if (IsA(join, HashJoin))
1036         {
1037                 HashJoin   *hj = (HashJoin *) join;
1038
1039                 hj->hashclauses = fix_join_expr(glob,
1040                                                                                 hj->hashclauses,
1041                                                                                 outer_itlist,
1042                                                                                 inner_itlist,
1043                                                                                 (Index) 0,
1044                                                                                 rtoffset);
1045         }
1046
1047         pfree(outer_itlist);
1048         pfree(inner_itlist);
1049 }
1050
1051 /*
1052  * set_upper_references
1053  *        Update the targetlist and quals of an upper-level plan node
1054  *        to refer to the tuples returned by its lefttree subplan.
1055  *        Also perform opcode lookup for these expressions, and
1056  *        add regclass OIDs to glob->relationOids.
1057  *
1058  * This is used for single-input plan types like Agg, Group, Result.
1059  *
1060  * In most cases, we have to match up individual Vars in the tlist and
1061  * qual expressions with elements of the subplan's tlist (which was
1062  * generated by flatten_tlist() from these selfsame expressions, so it
1063  * should have all the required variables).  There is an important exception,
1064  * however: GROUP BY and ORDER BY expressions will have been pushed into the
1065  * subplan tlist unflattened.  If these values are also needed in the output
1066  * then we want to reference the subplan tlist element rather than recomputing
1067  * the expression.
1068  */
1069 static void
1070 set_upper_references(PlannerGlobal *glob, Plan *plan, int rtoffset)
1071 {
1072         Plan       *subplan = plan->lefttree;
1073         indexed_tlist *subplan_itlist;
1074         List       *output_targetlist;
1075         ListCell   *l;
1076
1077         subplan_itlist = build_tlist_index(subplan->targetlist);
1078
1079         output_targetlist = NIL;
1080         foreach(l, plan->targetlist)
1081         {
1082                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1083                 Node       *newexpr;
1084
1085                 /* If it's a non-Var sort/group item, first try to match by sortref */
1086                 if (tle->ressortgroupref != 0 && !IsA(tle->expr, Var))
1087                 {
1088                         newexpr = (Node *)
1089                                 search_indexed_tlist_for_sortgroupref((Node *) tle->expr,
1090                                                                                                           tle->ressortgroupref,
1091                                                                                                           subplan_itlist,
1092                                                                                                           OUTER);
1093                         if (!newexpr)
1094                                 newexpr = fix_upper_expr(glob,
1095                                                                                  (Node *) tle->expr,
1096                                                                                  subplan_itlist,
1097                                                                                  rtoffset);
1098                 }
1099                 else
1100                         newexpr = fix_upper_expr(glob,
1101                                                                          (Node *) tle->expr,
1102                                                                          subplan_itlist,
1103                                                                          rtoffset);
1104                 tle = flatCopyTargetEntry(tle);
1105                 tle->expr = (Expr *) newexpr;
1106                 output_targetlist = lappend(output_targetlist, tle);
1107         }
1108         plan->targetlist = output_targetlist;
1109
1110         plan->qual = (List *)
1111                 fix_upper_expr(glob,
1112                                            (Node *) plan->qual,
1113                                            subplan_itlist,
1114                                            rtoffset);
1115
1116         pfree(subplan_itlist);
1117 }
1118
1119 /*
1120  * set_dummy_tlist_references
1121  *        Replace the targetlist of an upper-level plan node with a simple
1122  *        list of OUTER references to its child.
1123  *
1124  * This is used for plan types like Sort and Append that don't evaluate
1125  * their targetlists.  Although the executor doesn't care at all what's in
1126  * the tlist, EXPLAIN needs it to be realistic.
1127  *
1128  * Note: we could almost use set_upper_references() here, but it fails for
1129  * Append for lack of a lefttree subplan.  Single-purpose code is faster
1130  * anyway.
1131  */
1132 static void
1133 set_dummy_tlist_references(Plan *plan, int rtoffset)
1134 {
1135         List       *output_targetlist;
1136         ListCell   *l;
1137
1138         output_targetlist = NIL;
1139         foreach(l, plan->targetlist)
1140         {
1141                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1142                 Var                *oldvar = (Var *) tle->expr;
1143                 Var                *newvar;
1144
1145                 newvar = makeVar(OUTER,
1146                                                  tle->resno,
1147                                                  exprType((Node *) oldvar),
1148                                                  exprTypmod((Node *) oldvar),
1149                                                  exprCollation((Node *) oldvar),
1150                                                  0);
1151                 if (IsA(oldvar, Var))
1152                 {
1153                         newvar->varnoold = oldvar->varno + rtoffset;
1154                         newvar->varoattno = oldvar->varattno;
1155                 }
1156                 else
1157                 {
1158                         newvar->varnoold = 0;           /* wasn't ever a plain Var */
1159                         newvar->varoattno = 0;
1160                 }
1161
1162                 tle = flatCopyTargetEntry(tle);
1163                 tle->expr = (Expr *) newvar;
1164                 output_targetlist = lappend(output_targetlist, tle);
1165         }
1166         plan->targetlist = output_targetlist;
1167
1168         /* We don't touch plan->qual here */
1169 }
1170
1171
1172 /*
1173  * build_tlist_index --- build an index data structure for a child tlist
1174  *
1175  * In most cases, subplan tlists will be "flat" tlists with only Vars,
1176  * so we try to optimize that case by extracting information about Vars
1177  * in advance.  Matching a parent tlist to a child is still an O(N^2)
1178  * operation, but at least with a much smaller constant factor than plain
1179  * tlist_member() searches.
1180  *
1181  * The result of this function is an indexed_tlist struct to pass to
1182  * search_indexed_tlist_for_var() or search_indexed_tlist_for_non_var().
1183  * When done, the indexed_tlist may be freed with a single pfree().
1184  */
1185 static indexed_tlist *
1186 build_tlist_index(List *tlist)
1187 {
1188         indexed_tlist *itlist;
1189         tlist_vinfo *vinfo;
1190         ListCell   *l;
1191
1192         /* Create data structure with enough slots for all tlist entries */
1193         itlist = (indexed_tlist *)
1194                 palloc(offsetof(indexed_tlist, vars) +
1195                            list_length(tlist) * sizeof(tlist_vinfo));
1196
1197         itlist->tlist = tlist;
1198         itlist->has_ph_vars = false;
1199         itlist->has_non_vars = false;
1200
1201         /* Find the Vars and fill in the index array */
1202         vinfo = itlist->vars;
1203         foreach(l, tlist)
1204         {
1205                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1206
1207                 if (tle->expr && IsA(tle->expr, Var))
1208                 {
1209                         Var                *var = (Var *) tle->expr;
1210
1211                         vinfo->varno = var->varno;
1212                         vinfo->varattno = var->varattno;
1213                         vinfo->resno = tle->resno;
1214                         vinfo++;
1215                 }
1216                 else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
1217                         itlist->has_ph_vars = true;
1218                 else
1219                         itlist->has_non_vars = true;
1220         }
1221
1222         itlist->num_vars = (vinfo - itlist->vars);
1223
1224         return itlist;
1225 }
1226
1227 /*
1228  * build_tlist_index_other_vars --- build a restricted tlist index
1229  *
1230  * This is like build_tlist_index, but we only index tlist entries that
1231  * are Vars belonging to some rel other than the one specified.  We will set
1232  * has_ph_vars (allowing PlaceHolderVars to be matched), but not has_non_vars
1233  * (so nothing other than Vars and PlaceHolderVars can be matched).
1234  */
1235 static indexed_tlist *
1236 build_tlist_index_other_vars(List *tlist, Index ignore_rel)
1237 {
1238         indexed_tlist *itlist;
1239         tlist_vinfo *vinfo;
1240         ListCell   *l;
1241
1242         /* Create data structure with enough slots for all tlist entries */
1243         itlist = (indexed_tlist *)
1244                 palloc(offsetof(indexed_tlist, vars) +
1245                            list_length(tlist) * sizeof(tlist_vinfo));
1246
1247         itlist->tlist = tlist;
1248         itlist->has_ph_vars = false;
1249         itlist->has_non_vars = false;
1250
1251         /* Find the desired Vars and fill in the index array */
1252         vinfo = itlist->vars;
1253         foreach(l, tlist)
1254         {
1255                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1256
1257                 if (tle->expr && IsA(tle->expr, Var))
1258                 {
1259                         Var                *var = (Var *) tle->expr;
1260
1261                         if (var->varno != ignore_rel)
1262                         {
1263                                 vinfo->varno = var->varno;
1264                                 vinfo->varattno = var->varattno;
1265                                 vinfo->resno = tle->resno;
1266                                 vinfo++;
1267                         }
1268                 }
1269                 else if (tle->expr && IsA(tle->expr, PlaceHolderVar))
1270                         itlist->has_ph_vars = true;
1271         }
1272
1273         itlist->num_vars = (vinfo - itlist->vars);
1274
1275         return itlist;
1276 }
1277
1278 /*
1279  * search_indexed_tlist_for_var --- find a Var in an indexed tlist
1280  *
1281  * If a match is found, return a copy of the given Var with suitably
1282  * modified varno/varattno (to wit, newvarno and the resno of the TLE entry).
1283  * Also ensure that varnoold is incremented by rtoffset.
1284  * If no match, return NULL.
1285  */
1286 static Var *
1287 search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist,
1288                                                          Index newvarno, int rtoffset)
1289 {
1290         Index           varno = var->varno;
1291         AttrNumber      varattno = var->varattno;
1292         tlist_vinfo *vinfo;
1293         int                     i;
1294
1295         vinfo = itlist->vars;
1296         i = itlist->num_vars;
1297         while (i-- > 0)
1298         {
1299                 if (vinfo->varno == varno && vinfo->varattno == varattno)
1300                 {
1301                         /* Found a match */
1302                         Var                *newvar = copyVar(var);
1303
1304                         newvar->varno = newvarno;
1305                         newvar->varattno = vinfo->resno;
1306                         if (newvar->varnoold > 0)
1307                                 newvar->varnoold += rtoffset;
1308                         return newvar;
1309                 }
1310                 vinfo++;
1311         }
1312         return NULL;                            /* no match */
1313 }
1314
1315 /*
1316  * search_indexed_tlist_for_non_var --- find a non-Var in an indexed tlist
1317  *
1318  * If a match is found, return a Var constructed to reference the tlist item.
1319  * If no match, return NULL.
1320  *
1321  * NOTE: it is a waste of time to call this unless itlist->has_ph_vars or
1322  * itlist->has_non_vars
1323  */
1324 static Var *
1325 search_indexed_tlist_for_non_var(Node *node,
1326                                                                  indexed_tlist *itlist, Index newvarno)
1327 {
1328         TargetEntry *tle;
1329
1330         tle = tlist_member(node, itlist->tlist);
1331         if (tle)
1332         {
1333                 /* Found a matching subplan output expression */
1334                 Var                *newvar;
1335
1336                 newvar = makeVarFromTargetEntry(newvarno, tle);
1337                 newvar->varnoold = 0;   /* wasn't ever a plain Var */
1338                 newvar->varoattno = 0;
1339                 return newvar;
1340         }
1341         return NULL;                            /* no match */
1342 }
1343
1344 /*
1345  * search_indexed_tlist_for_sortgroupref --- find a sort/group expression
1346  *              (which is assumed not to be just a Var)
1347  *
1348  * If a match is found, return a Var constructed to reference the tlist item.
1349  * If no match, return NULL.
1350  *
1351  * This is needed to ensure that we select the right subplan TLE in cases
1352  * where there are multiple textually-equal()-but-volatile sort expressions.
1353  * And it's also faster than search_indexed_tlist_for_non_var.
1354  */
1355 static Var *
1356 search_indexed_tlist_for_sortgroupref(Node *node,
1357                                                                           Index sortgroupref,
1358                                                                           indexed_tlist *itlist,
1359                                                                           Index newvarno)
1360 {
1361         ListCell   *lc;
1362
1363         foreach(lc, itlist->tlist)
1364         {
1365                 TargetEntry *tle = (TargetEntry *) lfirst(lc);
1366
1367                 /* The equal() check should be redundant, but let's be paranoid */
1368                 if (tle->ressortgroupref == sortgroupref &&
1369                         equal(node, tle->expr))
1370                 {
1371                         /* Found a matching subplan output expression */
1372                         Var                *newvar;
1373
1374                         newvar = makeVarFromTargetEntry(newvarno, tle);
1375                         newvar->varnoold = 0;           /* wasn't ever a plain Var */
1376                         newvar->varoattno = 0;
1377                         return newvar;
1378                 }
1379         }
1380         return NULL;                            /* no match */
1381 }
1382
1383 /*
1384  * fix_join_expr
1385  *         Create a new set of targetlist entries or join qual clauses by
1386  *         changing the varno/varattno values of variables in the clauses
1387  *         to reference target list values from the outer and inner join
1388  *         relation target lists.  Also perform opcode lookup and add
1389  *         regclass OIDs to glob->relationOids.
1390  *
1391  * This is used in two different scenarios: a normal join clause, where
1392  * all the Vars in the clause *must* be replaced by OUTER or INNER references;
1393  * and a RETURNING clause, which may contain both Vars of the target relation
1394  * and Vars of other relations.  In the latter case we want to replace the
1395  * other-relation Vars by OUTER references, while leaving target Vars alone.
1396  *
1397  * For a normal join, acceptable_rel should be zero so that any failure to
1398  * match a Var will be reported as an error.  For the RETURNING case, pass
1399  * inner_itlist = NULL and acceptable_rel = the ID of the target relation.
1400  *
1401  * 'clauses' is the targetlist or list of join clauses
1402  * 'outer_itlist' is the indexed target list of the outer join relation
1403  * 'inner_itlist' is the indexed target list of the inner join relation,
1404  *              or NULL
1405  * 'acceptable_rel' is either zero or the rangetable index of a relation
1406  *              whose Vars may appear in the clause without provoking an error
1407  * 'rtoffset': how much to increment varnoold by
1408  *
1409  * Returns the new expression tree.  The original clause structure is
1410  * not modified.
1411  */
1412 static List *
1413 fix_join_expr(PlannerGlobal *glob,
1414                           List *clauses,
1415                           indexed_tlist *outer_itlist,
1416                           indexed_tlist *inner_itlist,
1417                           Index acceptable_rel,
1418                           int rtoffset)
1419 {
1420         fix_join_expr_context context;
1421
1422         context.glob = glob;
1423         context.outer_itlist = outer_itlist;
1424         context.inner_itlist = inner_itlist;
1425         context.acceptable_rel = acceptable_rel;
1426         context.rtoffset = rtoffset;
1427         return (List *) fix_join_expr_mutator((Node *) clauses, &context);
1428 }
1429
1430 static Node *
1431 fix_join_expr_mutator(Node *node, fix_join_expr_context *context)
1432 {
1433         Var                *newvar;
1434
1435         if (node == NULL)
1436                 return NULL;
1437         if (IsA(node, Var))
1438         {
1439                 Var                *var = (Var *) node;
1440
1441                 /* First look for the var in the input tlists */
1442                 newvar = search_indexed_tlist_for_var(var,
1443                                                                                           context->outer_itlist,
1444                                                                                           OUTER,
1445                                                                                           context->rtoffset);
1446                 if (newvar)
1447                         return (Node *) newvar;
1448                 if (context->inner_itlist)
1449                 {
1450                         newvar = search_indexed_tlist_for_var(var,
1451                                                                                                   context->inner_itlist,
1452                                                                                                   INNER,
1453                                                                                                   context->rtoffset);
1454                         if (newvar)
1455                                 return (Node *) newvar;
1456                 }
1457
1458                 /* If it's for acceptable_rel, adjust and return it */
1459                 if (var->varno == context->acceptable_rel)
1460                 {
1461                         var = copyVar(var);
1462                         if (var->varnoold > 0)
1463                                 var->varnoold += context->rtoffset;
1464                         return (Node *) var;
1465                 }
1466
1467                 /* No referent found for Var */
1468                 elog(ERROR, "variable not found in subplan target lists");
1469         }
1470         if (IsA(node, PlaceHolderVar))
1471         {
1472                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1473
1474                 /* See if the PlaceHolderVar has bubbled up from a lower plan node */
1475                 if (context->outer_itlist->has_ph_vars)
1476                 {
1477                         newvar = search_indexed_tlist_for_non_var((Node *) phv,
1478                                                                                                           context->outer_itlist,
1479                                                                                                           OUTER);
1480                         if (newvar)
1481                                 return (Node *) newvar;
1482                 }
1483                 if (context->inner_itlist && context->inner_itlist->has_ph_vars)
1484                 {
1485                         newvar = search_indexed_tlist_for_non_var((Node *) phv,
1486                                                                                                           context->inner_itlist,
1487                                                                                                           INNER);
1488                         if (newvar)
1489                                 return (Node *) newvar;
1490                 }
1491
1492                 /* If not supplied by input plans, evaluate the contained expr */
1493                 return fix_join_expr_mutator((Node *) phv->phexpr, context);
1494         }
1495         /* Try matching more complex expressions too, if tlists have any */
1496         if (context->outer_itlist->has_non_vars)
1497         {
1498                 newvar = search_indexed_tlist_for_non_var(node,
1499                                                                                                   context->outer_itlist,
1500                                                                                                   OUTER);
1501                 if (newvar)
1502                         return (Node *) newvar;
1503         }
1504         if (context->inner_itlist && context->inner_itlist->has_non_vars)
1505         {
1506                 newvar = search_indexed_tlist_for_non_var(node,
1507                                                                                                   context->inner_itlist,
1508                                                                                                   INNER);
1509                 if (newvar)
1510                         return (Node *) newvar;
1511         }
1512         fix_expr_common(context->glob, node);
1513         return expression_tree_mutator(node,
1514                                                                    fix_join_expr_mutator,
1515                                                                    (void *) context);
1516 }
1517
1518 /*
1519  * fix_upper_expr
1520  *              Modifies an expression tree so that all Var nodes reference outputs
1521  *              of a subplan.  Also performs opcode lookup, and adds regclass OIDs to
1522  *              glob->relationOids.
1523  *
1524  * This is used to fix up target and qual expressions of non-join upper-level
1525  * plan nodes.
1526  *
1527  * An error is raised if no matching var can be found in the subplan tlist
1528  * --- so this routine should only be applied to nodes whose subplans'
1529  * targetlists were generated via flatten_tlist() or some such method.
1530  *
1531  * If itlist->has_non_vars is true, then we try to match whole subexpressions
1532  * against elements of the subplan tlist, so that we can avoid recomputing
1533  * expressions that were already computed by the subplan.  (This is relatively
1534  * expensive, so we don't want to try it in the common case where the
1535  * subplan tlist is just a flattened list of Vars.)
1536  *
1537  * 'node': the tree to be fixed (a target item or qual)
1538  * 'subplan_itlist': indexed target list for subplan
1539  * 'rtoffset': how much to increment varnoold by
1540  *
1541  * The resulting tree is a copy of the original in which all Var nodes have
1542  * varno = OUTER, varattno = resno of corresponding subplan target.
1543  * The original tree is not modified.
1544  */
1545 static Node *
1546 fix_upper_expr(PlannerGlobal *glob,
1547                            Node *node,
1548                            indexed_tlist *subplan_itlist,
1549                            int rtoffset)
1550 {
1551         fix_upper_expr_context context;
1552
1553         context.glob = glob;
1554         context.subplan_itlist = subplan_itlist;
1555         context.rtoffset = rtoffset;
1556         return fix_upper_expr_mutator(node, &context);
1557 }
1558
1559 static Node *
1560 fix_upper_expr_mutator(Node *node, fix_upper_expr_context *context)
1561 {
1562         Var                *newvar;
1563
1564         if (node == NULL)
1565                 return NULL;
1566         if (IsA(node, Var))
1567         {
1568                 Var                *var = (Var *) node;
1569
1570                 newvar = search_indexed_tlist_for_var(var,
1571                                                                                           context->subplan_itlist,
1572                                                                                           OUTER,
1573                                                                                           context->rtoffset);
1574                 if (!newvar)
1575                         elog(ERROR, "variable not found in subplan target list");
1576                 return (Node *) newvar;
1577         }
1578         if (IsA(node, PlaceHolderVar))
1579         {
1580                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
1581
1582                 /* See if the PlaceHolderVar has bubbled up from a lower plan node */
1583                 if (context->subplan_itlist->has_ph_vars)
1584                 {
1585                         newvar = search_indexed_tlist_for_non_var((Node *) phv,
1586                                                                                                           context->subplan_itlist,
1587                                                                                                           OUTER);
1588                         if (newvar)
1589                                 return (Node *) newvar;
1590                 }
1591                 /* If not supplied by input plan, evaluate the contained expr */
1592                 return fix_upper_expr_mutator((Node *) phv->phexpr, context);
1593         }
1594         /* Try matching more complex expressions too, if tlist has any */
1595         if (context->subplan_itlist->has_non_vars)
1596         {
1597                 newvar = search_indexed_tlist_for_non_var(node,
1598                                                                                                   context->subplan_itlist,
1599                                                                                                   OUTER);
1600                 if (newvar)
1601                         return (Node *) newvar;
1602         }
1603         fix_expr_common(context->glob, node);
1604         return expression_tree_mutator(node,
1605                                                                    fix_upper_expr_mutator,
1606                                                                    (void *) context);
1607 }
1608
1609 /*
1610  * set_returning_clause_references
1611  *              Perform setrefs.c's work on a RETURNING targetlist
1612  *
1613  * If the query involves more than just the result table, we have to
1614  * adjust any Vars that refer to other tables to reference junk tlist
1615  * entries in the top subplan's targetlist.  Vars referencing the result
1616  * table should be left alone, however (the executor will evaluate them
1617  * using the actual heap tuple, after firing triggers if any).  In the
1618  * adjusted RETURNING list, result-table Vars will still have their
1619  * original varno, but Vars for other rels will have varno OUTER.
1620  *
1621  * We also must perform opcode lookup and add regclass OIDs to
1622  * glob->relationOids.
1623  *
1624  * 'rlist': the RETURNING targetlist to be fixed
1625  * 'topplan': the top subplan node that will be just below the ModifyTable
1626  *              node (note it's not yet passed through set_plan_references)
1627  * 'resultRelation': RT index of the associated result relation
1628  *
1629  * Note: we assume that result relations will have rtoffset zero, that is,
1630  * they are not coming from a subplan.
1631  */
1632 List *
1633 set_returning_clause_references(PlannerGlobal *glob,
1634                                                                 List *rlist,
1635                                                                 Plan *topplan,
1636                                                                 Index resultRelation)
1637 {
1638         indexed_tlist *itlist;
1639
1640         /*
1641          * We can perform the desired Var fixup by abusing the fix_join_expr
1642          * machinery that formerly handled inner indexscan fixup.  We search the
1643          * top plan's targetlist for Vars of non-result relations, and use
1644          * fix_join_expr to convert RETURNING Vars into references to those tlist
1645          * entries, while leaving result-rel Vars as-is.
1646          *
1647          * PlaceHolderVars will also be sought in the targetlist, but no
1648          * more-complex expressions will be.  Note that it is not possible for a
1649          * PlaceHolderVar to refer to the result relation, since the result is
1650          * never below an outer join.  If that case could happen, we'd have to be
1651          * prepared to pick apart the PlaceHolderVar and evaluate its contained
1652          * expression instead.
1653          */
1654         itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
1655
1656         rlist = fix_join_expr(glob,
1657                                                   rlist,
1658                                                   itlist,
1659                                                   NULL,
1660                                                   resultRelation,
1661                                                   0);
1662
1663         pfree(itlist);
1664
1665         return rlist;
1666 }
1667
1668 /*****************************************************************************
1669  *                                      OPERATOR REGPROC LOOKUP
1670  *****************************************************************************/
1671
1672 /*
1673  * fix_opfuncids
1674  *        Calculate opfuncid field from opno for each OpExpr node in given tree.
1675  *        The given tree can be anything expression_tree_walker handles.
1676  *
1677  * The argument is modified in-place.  (This is OK since we'd want the
1678  * same change for any node, even if it gets visited more than once due to
1679  * shared structure.)
1680  */
1681 void
1682 fix_opfuncids(Node *node)
1683 {
1684         /* This tree walk requires no special setup, so away we go... */
1685         fix_opfuncids_walker(node, NULL);
1686 }
1687
1688 static bool
1689 fix_opfuncids_walker(Node *node, void *context)
1690 {
1691         if (node == NULL)
1692                 return false;
1693         if (IsA(node, OpExpr))
1694                 set_opfuncid((OpExpr *) node);
1695         else if (IsA(node, DistinctExpr))
1696                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1697         else if (IsA(node, NullIfExpr))
1698                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1699         else if (IsA(node, ScalarArrayOpExpr))
1700                 set_sa_opfuncid((ScalarArrayOpExpr *) node);
1701         return expression_tree_walker(node, fix_opfuncids_walker, context);
1702 }
1703
1704 /*
1705  * set_opfuncid
1706  *              Set the opfuncid (procedure OID) in an OpExpr node,
1707  *              if it hasn't been set already.
1708  *
1709  * Because of struct equivalence, this can also be used for
1710  * DistinctExpr and NullIfExpr nodes.
1711  */
1712 void
1713 set_opfuncid(OpExpr *opexpr)
1714 {
1715         if (opexpr->opfuncid == InvalidOid)
1716                 opexpr->opfuncid = get_opcode(opexpr->opno);
1717 }
1718
1719 /*
1720  * set_sa_opfuncid
1721  *              As above, for ScalarArrayOpExpr nodes.
1722  */
1723 void
1724 set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
1725 {
1726         if (opexpr->opfuncid == InvalidOid)
1727                 opexpr->opfuncid = get_opcode(opexpr->opno);
1728 }
1729
1730 /*****************************************************************************
1731  *                                      QUERY DEPENDENCY MANAGEMENT
1732  *****************************************************************************/
1733
1734 /*
1735  * record_plan_function_dependency
1736  *              Mark the current plan as depending on a particular function.
1737  *
1738  * This is exported so that the function-inlining code can record a
1739  * dependency on a function that it's removed from the plan tree.
1740  */
1741 void
1742 record_plan_function_dependency(PlannerGlobal *glob, Oid funcid)
1743 {
1744         /*
1745          * For performance reasons, we don't bother to track built-in functions;
1746          * we just assume they'll never change (or at least not in ways that'd
1747          * invalidate plans using them).  For this purpose we can consider a
1748          * built-in function to be one with OID less than FirstBootstrapObjectId.
1749          * Note that the OID generator guarantees never to generate such an OID
1750          * after startup, even at OID wraparound.
1751          */
1752         if (funcid >= (Oid) FirstBootstrapObjectId)
1753         {
1754                 HeapTuple       func_tuple;
1755                 PlanInvalItem *inval_item;
1756
1757                 func_tuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(funcid));
1758                 if (!HeapTupleIsValid(func_tuple))
1759                         elog(ERROR, "cache lookup failed for function %u", funcid);
1760
1761                 inval_item = makeNode(PlanInvalItem);
1762
1763                 /*
1764                  * It would work to use any syscache on pg_proc, but plancache.c
1765                  * expects us to use PROCOID.
1766                  */
1767                 inval_item->cacheId = PROCOID;
1768                 inval_item->tupleId = func_tuple->t_self;
1769
1770                 glob->invalItems = lappend(glob->invalItems, inval_item);
1771
1772                 ReleaseSysCache(func_tuple);
1773         }
1774 }
1775
1776 /*
1777  * extract_query_dependencies
1778  *              Given a not-yet-planned query or queries (i.e. a Query node or list
1779  *              of Query nodes), extract dependencies just as set_plan_references
1780  *              would do.
1781  *
1782  * This is needed by plancache.c to handle invalidation of cached unplanned
1783  * queries.
1784  */
1785 void
1786 extract_query_dependencies(Node *query,
1787                                                    List **relationOids,
1788                                                    List **invalItems)
1789 {
1790         PlannerGlobal glob;
1791
1792         /* Make up a dummy PlannerGlobal so we can use this module's machinery */
1793         MemSet(&glob, 0, sizeof(glob));
1794         glob.type = T_PlannerGlobal;
1795         glob.relationOids = NIL;
1796         glob.invalItems = NIL;
1797
1798         (void) extract_query_dependencies_walker(query, &glob);
1799
1800         *relationOids = glob.relationOids;
1801         *invalItems = glob.invalItems;
1802 }
1803
1804 static bool
1805 extract_query_dependencies_walker(Node *node, PlannerGlobal *context)
1806 {
1807         if (node == NULL)
1808                 return false;
1809         Assert(!IsA(node, PlaceHolderVar));
1810         /* Extract function dependencies and check for regclass Consts */
1811         fix_expr_common(context, node);
1812         if (IsA(node, Query))
1813         {
1814                 Query      *query = (Query *) node;
1815                 ListCell   *lc;
1816
1817                 if (query->commandType == CMD_UTILITY)
1818                 {
1819                         /* Ignore utility statements, except EXPLAIN */
1820                         if (IsA(query->utilityStmt, ExplainStmt))
1821                         {
1822                                 query = (Query *) ((ExplainStmt *) query->utilityStmt)->query;
1823                                 Assert(IsA(query, Query));
1824                                 Assert(query->commandType != CMD_UTILITY);
1825                         }
1826                         else
1827                                 return false;
1828                 }
1829
1830                 /* Collect relation OIDs in this Query's rtable */
1831                 foreach(lc, query->rtable)
1832                 {
1833                         RangeTblEntry *rte = (RangeTblEntry *) lfirst(lc);
1834
1835                         if (rte->rtekind == RTE_RELATION)
1836                                 context->relationOids = lappend_oid(context->relationOids,
1837                                                                                                         rte->relid);
1838                 }
1839
1840                 /* And recurse into the query's subexpressions */
1841                 return query_tree_walker(query, extract_query_dependencies_walker,
1842                                                                  (void *) context, 0);
1843         }
1844         return expression_tree_walker(node, extract_query_dependencies_walker,
1845                                                                   (void *) context);
1846 }