]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/plan/setrefs.c
c356d265e84ec8b8e9e4f86475cfec5810fc56e5
[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, and compute regproc values for operators
6  *
7  * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
8  * Portions Copyright (c) 1994, Regents of the University of California
9  *
10  *
11  * IDENTIFICATION
12  *        $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.128 2007/01/22 01:35:20 tgl Exp $
13  *
14  *-------------------------------------------------------------------------
15  */
16 #include "postgres.h"
17
18 #include "nodes/makefuncs.h"
19 #include "optimizer/clauses.h"
20 #include "optimizer/planmain.h"
21 #include "optimizer/tlist.h"
22 #include "parser/parse_expr.h"
23 #include "parser/parsetree.h"
24 #include "utils/lsyscache.h"
25
26
27 typedef struct
28 {
29         Index           varno;                  /* RT index of Var */
30         AttrNumber      varattno;               /* attr number of Var */
31         AttrNumber      resno;                  /* TLE position of Var */
32 } tlist_vinfo;
33
34 typedef struct
35 {
36         List       *tlist;                      /* underlying target list */
37         int                     num_vars;               /* number of plain Var tlist entries */
38         bool            has_non_vars;   /* are there non-plain-Var entries? */
39         /* array of num_vars entries: */
40         tlist_vinfo vars[1];            /* VARIABLE LENGTH ARRAY */
41 } indexed_tlist;                                /* VARIABLE LENGTH STRUCT */
42
43 typedef struct
44 {
45         indexed_tlist *outer_itlist;
46         indexed_tlist *inner_itlist;
47         Index           acceptable_rel;
48 } join_references_context;
49
50 typedef struct
51 {
52         indexed_tlist *subplan_itlist;
53         Index           subvarno;
54 } replace_vars_with_subplan_refs_context;
55
56 static Plan *set_subqueryscan_references(SubqueryScan *plan, List *rtable);
57 static bool trivial_subqueryscan(SubqueryScan *plan);
58 static void adjust_plan_varnos(Plan *plan, int rtoffset);
59 static void adjust_expr_varnos(Node *node, int rtoffset);
60 static bool adjust_expr_varnos_walker(Node *node, int *context);
61 static void fix_expr_references(Plan *plan, Node *node);
62 static bool fix_expr_references_walker(Node *node, void *context);
63 static void set_join_references(Join *join);
64 static void set_inner_join_references(Plan *inner_plan,
65                                                   indexed_tlist *outer_itlist);
66 static void set_uppernode_references(Plan *plan, Index subvarno);
67 static indexed_tlist *build_tlist_index(List *tlist);
68 static Var *search_indexed_tlist_for_var(Var *var,
69                                                          indexed_tlist *itlist,
70                                                          Index newvarno);
71 static Var *search_indexed_tlist_for_non_var(Node *node,
72                                                                  indexed_tlist *itlist,
73                                                                  Index newvarno);
74 static List *join_references(List *clauses,
75                                 indexed_tlist *outer_itlist,
76                                 indexed_tlist *inner_itlist,
77                                 Index acceptable_rel);
78 static Node *join_references_mutator(Node *node,
79                                                 join_references_context *context);
80 static Node *replace_vars_with_subplan_refs(Node *node,
81                                                            indexed_tlist *subplan_itlist,
82                                                            Index subvarno);
83 static Node *replace_vars_with_subplan_refs_mutator(Node *node,
84                                                         replace_vars_with_subplan_refs_context *context);
85 static bool fix_opfuncids_walker(Node *node, void *context);
86
87
88 /*****************************************************************************
89  *
90  *              SUBPLAN REFERENCES
91  *
92  *****************************************************************************/
93
94 /*
95  * set_plan_references
96  *
97  * This is the final processing pass of the planner/optimizer.  The plan
98  * tree is complete; we just have to adjust some representational details
99  * for the convenience of the executor.  We update Vars in upper plan nodes
100  * to refer to the outputs of their subplans, and we compute regproc OIDs
101  * for operators (ie, we look up the function that implements each op).
102  *
103  * We also perform one final optimization step, which is to delete
104  * SubqueryScan plan nodes that aren't doing anything useful (ie, have
105  * no qual and a no-op targetlist).  The reason for doing this last is that
106  * it can't readily be done before set_plan_references, because it would
107  * break set_uppernode_references: the Vars in the subquery's top tlist
108  * won't match up with the Vars in the outer plan tree.  The SubqueryScan
109  * serves a necessary function as a buffer between outer query and subquery
110  * variable numbering ... but the executor doesn't care about that, only the
111  * planner.
112  *
113  * set_plan_references recursively traverses the whole plan tree.
114  *
115  * The return value is normally the same Plan node passed in, but can be
116  * different when the passed-in Plan is a SubqueryScan we decide isn't needed.
117  *
118  * Note: to delete a SubqueryScan, we have to renumber Vars in its child nodes
119  * and append the modified subquery rangetable to the outer rangetable.
120  * Therefore "rtable" is an in/out argument and really should be declared
121  * "List **".  But in the interest of notational simplicity we don't do that.
122  * (Since rtable can't be NIL if there's a SubqueryScan, the list header
123  * address won't change when we append a subquery rangetable.)
124  */
125 Plan *
126 set_plan_references(Plan *plan, List *rtable)
127 {
128         ListCell   *l;
129
130         if (plan == NULL)
131                 return NULL;
132
133         /*
134          * Plan-type-specific fixes
135          */
136         switch (nodeTag(plan))
137         {
138                 case T_SeqScan:
139                         fix_expr_references(plan, (Node *) plan->targetlist);
140                         fix_expr_references(plan, (Node *) plan->qual);
141                         break;
142                 case T_IndexScan:
143                         fix_expr_references(plan, (Node *) plan->targetlist);
144                         fix_expr_references(plan, (Node *) plan->qual);
145                         fix_expr_references(plan,
146                                                                 (Node *) ((IndexScan *) plan)->indexqual);
147                         fix_expr_references(plan,
148                                                                 (Node *) ((IndexScan *) plan)->indexqualorig);
149                         break;
150                 case T_BitmapIndexScan:
151                         /* no need to fix targetlist and qual */
152                         Assert(plan->targetlist == NIL);
153                         Assert(plan->qual == NIL);
154                         fix_expr_references(plan,
155                                                          (Node *) ((BitmapIndexScan *) plan)->indexqual);
156                         fix_expr_references(plan,
157                                                  (Node *) ((BitmapIndexScan *) plan)->indexqualorig);
158                         break;
159                 case T_BitmapHeapScan:
160                         fix_expr_references(plan, (Node *) plan->targetlist);
161                         fix_expr_references(plan, (Node *) plan->qual);
162                         fix_expr_references(plan,
163                                                  (Node *) ((BitmapHeapScan *) plan)->bitmapqualorig);
164                         break;
165                 case T_TidScan:
166                         fix_expr_references(plan, (Node *) plan->targetlist);
167                         fix_expr_references(plan, (Node *) plan->qual);
168                         fix_expr_references(plan, (Node *) ((TidScan *) plan)->tidquals);
169                         break;
170                 case T_SubqueryScan:
171                         /* Needs special treatment, see comments below */
172                         return set_subqueryscan_references((SubqueryScan *) plan, rtable);
173                 case T_FunctionScan:
174                         {
175                                 RangeTblEntry *rte;
176
177                                 fix_expr_references(plan, (Node *) plan->targetlist);
178                                 fix_expr_references(plan, (Node *) plan->qual);
179                                 rte = rt_fetch(((FunctionScan *) plan)->scan.scanrelid,
180                                                            rtable);
181                                 Assert(rte->rtekind == RTE_FUNCTION);
182                                 fix_expr_references(plan, rte->funcexpr);
183                         }
184                         break;
185                 case T_ValuesScan:
186                         {
187                                 RangeTblEntry *rte;
188
189                                 fix_expr_references(plan, (Node *) plan->targetlist);
190                                 fix_expr_references(plan, (Node *) plan->qual);
191                                 rte = rt_fetch(((ValuesScan *) plan)->scan.scanrelid,
192                                                            rtable);
193                                 Assert(rte->rtekind == RTE_VALUES);
194                                 fix_expr_references(plan, (Node *) rte->values_lists);
195                         }
196                         break;
197                 case T_NestLoop:
198                         set_join_references((Join *) plan);
199                         fix_expr_references(plan, (Node *) plan->targetlist);
200                         fix_expr_references(plan, (Node *) plan->qual);
201                         fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
202                         break;
203                 case T_MergeJoin:
204                         set_join_references((Join *) plan);
205                         fix_expr_references(plan, (Node *) plan->targetlist);
206                         fix_expr_references(plan, (Node *) plan->qual);
207                         fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
208                         fix_expr_references(plan,
209                                                                 (Node *) ((MergeJoin *) plan)->mergeclauses);
210                         break;
211                 case T_HashJoin:
212                         set_join_references((Join *) plan);
213                         fix_expr_references(plan, (Node *) plan->targetlist);
214                         fix_expr_references(plan, (Node *) plan->qual);
215                         fix_expr_references(plan, (Node *) ((Join *) plan)->joinqual);
216                         fix_expr_references(plan,
217                                                                 (Node *) ((HashJoin *) plan)->hashclauses);
218                         break;
219                 case T_Hash:
220                 case T_Material:
221                 case T_Sort:
222                 case T_Unique:
223                 case T_SetOp:
224
225                         /*
226                          * These plan types don't actually bother to evaluate their
227                          * targetlists (because they just return their unmodified input
228                          * tuples).  The optimizer is lazy about creating really valid
229                          * targetlists for them --- it tends to just put in a pointer to
230                          * the child plan node's tlist.  Hence, we leave the tlist alone.
231                          * In particular, we do not want to process subplans in the tlist,
232                          * since we will likely end up reprocessing subplans that also
233                          * appear in lower levels of the plan tree!
234                          *
235                          * Since these plan types don't check quals either, we should not
236                          * find any qual expression attached to them.
237                          */
238                         Assert(plan->qual == NIL);
239                         break;
240                 case T_Limit:
241
242                         /*
243                          * Like the plan types above, Limit doesn't evaluate its tlist or
244                          * quals.  It does have live expressions for limit/offset,
245                          * however.
246                          */
247                         Assert(plan->qual == NIL);
248                         fix_expr_references(plan, ((Limit *) plan)->limitOffset);
249                         fix_expr_references(plan, ((Limit *) plan)->limitCount);
250                         break;
251                 case T_Agg:
252                 case T_Group:
253                         set_uppernode_references(plan, (Index) 0);
254                         fix_expr_references(plan, (Node *) plan->targetlist);
255                         fix_expr_references(plan, (Node *) plan->qual);
256                         break;
257                 case T_Result:
258
259                         /*
260                          * Result may or may not have a subplan; no need to fix up subplan
261                          * references if it hasn't got one...
262                          *
263                          * XXX why does Result use a different subvarno from Agg/Group?
264                          */
265                         if (plan->lefttree != NULL)
266                                 set_uppernode_references(plan, (Index) OUTER);
267                         fix_expr_references(plan, (Node *) plan->targetlist);
268                         fix_expr_references(plan, (Node *) plan->qual);
269                         fix_expr_references(plan, ((Result *) plan)->resconstantqual);
270                         break;
271                 case T_Append:
272
273                         /*
274                          * Append, like Sort et al, doesn't actually evaluate its
275                          * targetlist or check quals, and we haven't bothered to give it
276                          * its own tlist copy. So, don't fix targetlist/qual. But do
277                          * recurse into child plans.
278                          */
279                         Assert(plan->qual == NIL);
280                         foreach(l, ((Append *) plan)->appendplans)
281                                 lfirst(l) = set_plan_references((Plan *) lfirst(l), rtable);
282                         break;
283                 case T_BitmapAnd:
284                         /* BitmapAnd works like Append, but has no tlist */
285                         Assert(plan->targetlist == NIL);
286                         Assert(plan->qual == NIL);
287                         foreach(l, ((BitmapAnd *) plan)->bitmapplans)
288                                 lfirst(l) = set_plan_references((Plan *) lfirst(l), rtable);
289                         break;
290                 case T_BitmapOr:
291                         /* BitmapOr works like Append, but has no tlist */
292                         Assert(plan->targetlist == NIL);
293                         Assert(plan->qual == NIL);
294                         foreach(l, ((BitmapOr *) plan)->bitmapplans)
295                                 lfirst(l) = set_plan_references((Plan *) lfirst(l), rtable);
296                         break;
297                 default:
298                         elog(ERROR, "unrecognized node type: %d",
299                                  (int) nodeTag(plan));
300                         break;
301         }
302
303         /*
304          * Now recurse into child plans and initplans, if any
305          *
306          * NOTE: it is essential that we recurse into child plans AFTER we set
307          * subplan references in this plan's tlist and quals.  If we did the
308          * reference-adjustments bottom-up, then we would fail to match this
309          * plan's var nodes against the already-modified nodes of the children.
310          * Fortunately, that consideration doesn't apply to SubPlan nodes; else
311          * we'd need two passes over the expression trees.
312          */
313         plan->lefttree = set_plan_references(plan->lefttree, rtable);
314         plan->righttree = set_plan_references(plan->righttree, rtable);
315
316         foreach(l, plan->initPlan)
317         {
318                 SubPlan    *sp = (SubPlan *) lfirst(l);
319
320                 Assert(IsA(sp, SubPlan));
321                 sp->plan = set_plan_references(sp->plan, sp->rtable);
322         }
323
324         return plan;
325 }
326
327 /*
328  * set_subqueryscan_references
329  *              Do set_plan_references processing on a SubqueryScan
330  *
331  * We try to strip out the SubqueryScan entirely; if we can't, we have
332  * to do the normal processing on it.
333  */
334 static Plan *
335 set_subqueryscan_references(SubqueryScan *plan, List *rtable)
336 {
337         Plan       *result;
338         RangeTblEntry *rte;
339         ListCell   *l;
340
341         /* First, recursively process the subplan */
342         rte = rt_fetch(plan->scan.scanrelid, rtable);
343         Assert(rte->rtekind == RTE_SUBQUERY);
344         plan->subplan = set_plan_references(plan->subplan,
345                                                                                 rte->subquery->rtable);
346
347         /*
348          * We have to process any initplans too; set_plan_references can't do it
349          * for us because of the possibility of double-processing.
350          */
351         foreach(l, plan->scan.plan.initPlan)
352         {
353                 SubPlan    *sp = (SubPlan *) lfirst(l);
354
355                 Assert(IsA(sp, SubPlan));
356                 sp->plan = set_plan_references(sp->plan, sp->rtable);
357         }
358
359         if (trivial_subqueryscan(plan))
360         {
361                 /*
362                  * We can omit the SubqueryScan node and just pull up the subplan. We
363                  * have to merge its rtable into the outer rtable, which means
364                  * adjusting varnos throughout the subtree.
365                  */
366                 int                     rtoffset = list_length(rtable);
367                 List       *sub_rtable;
368                 ListCell   *lp,
369                                    *lc;
370
371                 sub_rtable = copyObject(rte->subquery->rtable);
372                 range_table_walker(sub_rtable,
373                                                    adjust_expr_varnos_walker,
374                                                    (void *) &rtoffset,
375                                                    QTW_IGNORE_RT_SUBQUERIES);
376                 rtable = list_concat(rtable, sub_rtable);
377
378                 /*
379                  * we have to copy the subplan to make sure there are no duplicately
380                  * linked nodes in it, else adjust_plan_varnos might increment some
381                  * varnos twice
382                  */
383                 result = copyObject(plan->subplan);
384
385                 adjust_plan_varnos(result, rtoffset);
386
387                 result->initPlan = list_concat(plan->scan.plan.initPlan,
388                                                                            result->initPlan);
389
390                 /*
391                  * We also have to transfer the SubqueryScan's result-column names
392                  * into the subplan, else columns sent to client will be improperly
393                  * labeled if this is the topmost plan level.  Copy the "source
394                  * column" information too.
395                  */
396                 forboth(lp, plan->scan.plan.targetlist, lc, result->targetlist)
397                 {
398                         TargetEntry *ptle = (TargetEntry *) lfirst(lp);
399                         TargetEntry *ctle = (TargetEntry *) lfirst(lc);
400
401                         ctle->resname = ptle->resname;
402                         ctle->resorigtbl = ptle->resorigtbl;
403                         ctle->resorigcol = ptle->resorigcol;
404                 }
405         }
406         else
407         {
408                 /*
409                  * Keep the SubqueryScan node.  We have to do the processing that
410                  * set_plan_references would otherwise have done on it.  Notice we do
411                  * not do set_uppernode_references() here, because a SubqueryScan will
412                  * always have been created with correct references to its subplan's
413                  * outputs to begin with.
414                  */
415                 result = (Plan *) plan;
416
417                 fix_expr_references(result, (Node *) result->targetlist);
418                 fix_expr_references(result, (Node *) result->qual);
419         }
420
421         return result;
422 }
423
424 /*
425  * trivial_subqueryscan
426  *              Detect whether a SubqueryScan can be deleted from the plan tree.
427  *
428  * We can delete it if it has no qual to check and the targetlist just
429  * regurgitates the output of the child plan.
430  */
431 static bool
432 trivial_subqueryscan(SubqueryScan *plan)
433 {
434         int                     attrno;
435         ListCell   *lp,
436                            *lc;
437
438         if (plan->scan.plan.qual != NIL)
439                 return false;
440
441         if (list_length(plan->scan.plan.targetlist) !=
442                 list_length(plan->subplan->targetlist))
443                 return false;                   /* tlists not same length */
444
445         attrno = 1;
446         forboth(lp, plan->scan.plan.targetlist, lc, plan->subplan->targetlist)
447         {
448                 TargetEntry *ptle = (TargetEntry *) lfirst(lp);
449                 TargetEntry *ctle = (TargetEntry *) lfirst(lc);
450
451                 if (ptle->resjunk != ctle->resjunk)
452                         return false;           /* tlist doesn't match junk status */
453
454                 /*
455                  * We accept either a Var referencing the corresponding element of the
456                  * subplan tlist, or a Const equaling the subplan element. See
457                  * generate_setop_tlist() for motivation.
458                  */
459                 if (ptle->expr && IsA(ptle->expr, Var))
460                 {
461                         Var                *var = (Var *) ptle->expr;
462
463                         Assert(var->varno == plan->scan.scanrelid);
464                         Assert(var->varlevelsup == 0);
465                         if (var->varattno != attrno)
466                                 return false;   /* out of order */
467                 }
468                 else if (ptle->expr && IsA(ptle->expr, Const))
469                 {
470                         if (!equal(ptle->expr, ctle->expr))
471                                 return false;
472                 }
473                 else
474                         return false;
475
476                 attrno++;
477         }
478
479         return true;
480 }
481
482 /*
483  * adjust_plan_varnos
484  *              Offset varnos and other rangetable indexes in a plan tree by rtoffset.
485  */
486 static void
487 adjust_plan_varnos(Plan *plan, int rtoffset)
488 {
489         ListCell   *l;
490
491         if (plan == NULL)
492                 return;
493
494         /*
495          * Plan-type-specific fixes
496          */
497         switch (nodeTag(plan))
498         {
499                 case T_SeqScan:
500                         ((SeqScan *) plan)->scanrelid += rtoffset;
501                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
502                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
503                         break;
504                 case T_IndexScan:
505                         ((IndexScan *) plan)->scan.scanrelid += rtoffset;
506                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
507                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
508                         adjust_expr_varnos((Node *) ((IndexScan *) plan)->indexqual,
509                                                            rtoffset);
510                         adjust_expr_varnos((Node *) ((IndexScan *) plan)->indexqualorig,
511                                                            rtoffset);
512                         break;
513                 case T_BitmapIndexScan:
514                         ((BitmapIndexScan *) plan)->scan.scanrelid += rtoffset;
515                         /* no need to fix targetlist and qual */
516                         Assert(plan->targetlist == NIL);
517                         Assert(plan->qual == NIL);
518                         adjust_expr_varnos((Node *) ((BitmapIndexScan *) plan)->indexqual,
519                                                            rtoffset);
520                         adjust_expr_varnos((Node *) ((BitmapIndexScan *) plan)->indexqualorig,
521                                                            rtoffset);
522                         break;
523                 case T_BitmapHeapScan:
524                         ((BitmapHeapScan *) plan)->scan.scanrelid += rtoffset;
525                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
526                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
527                         adjust_expr_varnos((Node *) ((BitmapHeapScan *) plan)->bitmapqualorig,
528                                                            rtoffset);
529                         break;
530                 case T_TidScan:
531                         ((TidScan *) plan)->scan.scanrelid += rtoffset;
532                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
533                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
534                         adjust_expr_varnos((Node *) ((TidScan *) plan)->tidquals,
535                                                            rtoffset);
536                         break;
537                 case T_SubqueryScan:
538                         ((SubqueryScan *) plan)->scan.scanrelid += rtoffset;
539                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
540                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
541                         /* we should not recurse into the subquery! */
542                         break;
543                 case T_FunctionScan:
544                         ((FunctionScan *) plan)->scan.scanrelid += rtoffset;
545                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
546                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
547                         /* rte was already fixed by set_subqueryscan_references */
548                         break;
549                 case T_ValuesScan:
550                         ((ValuesScan *) plan)->scan.scanrelid += rtoffset;
551                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
552                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
553                         /* rte was already fixed by set_subqueryscan_references */
554                         break;
555                 case T_NestLoop:
556                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
557                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
558                         adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset);
559                         break;
560                 case T_MergeJoin:
561                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
562                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
563                         adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset);
564                         adjust_expr_varnos((Node *) ((MergeJoin *) plan)->mergeclauses,
565                                                            rtoffset);
566                         break;
567                 case T_HashJoin:
568                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
569                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
570                         adjust_expr_varnos((Node *) ((Join *) plan)->joinqual, rtoffset);
571                         adjust_expr_varnos((Node *) ((HashJoin *) plan)->hashclauses,
572                                                            rtoffset);
573                         break;
574                 case T_Hash:
575                 case T_Material:
576                 case T_Sort:
577                 case T_Unique:
578                 case T_SetOp:
579
580                         /*
581                          * Even though the targetlist won't be used by the executor, we
582                          * fix it up for possible use by EXPLAIN (not to mention ease of
583                          * debugging --- wrong varnos are very confusing).
584                          */
585                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
586                         Assert(plan->qual == NIL);
587                         break;
588                 case T_Limit:
589
590                         /*
591                          * Like the plan types above, Limit doesn't evaluate its tlist or
592                          * quals.  It does have live expressions for limit/offset,
593                          * however.
594                          */
595                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
596                         Assert(plan->qual == NIL);
597                         adjust_expr_varnos(((Limit *) plan)->limitOffset, rtoffset);
598                         adjust_expr_varnos(((Limit *) plan)->limitCount, rtoffset);
599                         break;
600                 case T_Agg:
601                 case T_Group:
602                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
603                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
604                         break;
605                 case T_Result:
606                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
607                         adjust_expr_varnos((Node *) plan->qual, rtoffset);
608                         adjust_expr_varnos(((Result *) plan)->resconstantqual, rtoffset);
609                         break;
610                 case T_Append:
611                         adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
612                         Assert(plan->qual == NIL);
613                         foreach(l, ((Append *) plan)->appendplans)
614                                 adjust_plan_varnos((Plan *) lfirst(l), rtoffset);
615                         break;
616                 case T_BitmapAnd:
617                         /* BitmapAnd works like Append, but has no tlist */
618                         Assert(plan->targetlist == NIL);
619                         Assert(plan->qual == NIL);
620                         foreach(l, ((BitmapAnd *) plan)->bitmapplans)
621                                 adjust_plan_varnos((Plan *) lfirst(l), rtoffset);
622                         break;
623                 case T_BitmapOr:
624                         /* BitmapOr works like Append, but has no tlist */
625                         Assert(plan->targetlist == NIL);
626                         Assert(plan->qual == NIL);
627                         foreach(l, ((BitmapOr *) plan)->bitmapplans)
628                                 adjust_plan_varnos((Plan *) lfirst(l), rtoffset);
629                         break;
630                 default:
631                         elog(ERROR, "unrecognized node type: %d",
632                                  (int) nodeTag(plan));
633                         break;
634         }
635
636         /*
637          * Now recurse into child plans.
638          *
639          * We don't need to (and in fact mustn't) recurse into subqueries, so no
640          * need to examine initPlan list.
641          */
642         adjust_plan_varnos(plan->lefttree, rtoffset);
643         adjust_plan_varnos(plan->righttree, rtoffset);
644 }
645
646 /*
647  * adjust_expr_varnos
648  *              Offset varnos of Vars in an expression by rtoffset.
649  *
650  * This is different from the rewriter's OffsetVarNodes in that it has to
651  * work on an already-planned expression tree; in particular, we should not
652  * disturb INNER and OUTER references.  On the other hand, we don't have to
653  * recurse into subqueries nor deal with outer-level Vars, so it's pretty
654  * simple.
655  */
656 static void
657 adjust_expr_varnos(Node *node, int rtoffset)
658 {
659         /* This tree walk requires no special setup, so away we go... */
660         adjust_expr_varnos_walker(node, &rtoffset);
661 }
662
663 static bool
664 adjust_expr_varnos_walker(Node *node, int *context)
665 {
666         if (node == NULL)
667                 return false;
668         if (IsA(node, Var))
669         {
670                 Var                *var = (Var *) node;
671
672                 Assert(var->varlevelsup == 0);
673                 if (var->varno > 0 && var->varno != INNER && var->varno != OUTER)
674                         var->varno += *context;
675                 if (var->varnoold > 0)
676                         var->varnoold += *context;
677                 return false;
678         }
679         return expression_tree_walker(node, adjust_expr_varnos_walker,
680                                                                   (void *) context);
681 }
682
683 /*
684  * fix_expr_references
685  *        Do final cleanup on expressions (targetlists or quals).
686  *
687  * This consists of looking up operator opcode info for OpExpr nodes
688  * and recursively performing set_plan_references on subplans.
689  *
690  * The Plan argument is currently unused, but might be needed again someday.
691  */
692 static void
693 fix_expr_references(Plan *plan, Node *node)
694 {
695         /* This tree walk requires no special setup, so away we go... */
696         fix_expr_references_walker(node, NULL);
697 }
698
699 static bool
700 fix_expr_references_walker(Node *node, void *context)
701 {
702         if (node == NULL)
703                 return false;
704         if (IsA(node, OpExpr))
705                 set_opfuncid((OpExpr *) node);
706         else if (IsA(node, DistinctExpr))
707                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
708         else if (IsA(node, ScalarArrayOpExpr))
709                 set_sa_opfuncid((ScalarArrayOpExpr *) node);
710         else if (IsA(node, NullIfExpr))
711                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
712         else if (IsA(node, SubPlan))
713         {
714                 SubPlan    *sp = (SubPlan *) node;
715
716                 sp->plan = set_plan_references(sp->plan, sp->rtable);
717         }
718         return expression_tree_walker(node, fix_expr_references_walker, context);
719 }
720
721 /*
722  * set_join_references
723  *        Modifies the target list and quals of a join node to reference its
724  *        subplans, by setting the varnos to OUTER or INNER and setting attno
725  *        values to the result domain number of either the corresponding outer
726  *        or inner join tuple item.
727  *
728  * In the case of a nestloop with inner indexscan, we will also need to
729  * apply the same transformation to any outer vars appearing in the
730  * quals of the child indexscan.  set_inner_join_references does that.
731  *
732  *      'join' is a join plan node
733  */
734 static void
735 set_join_references(Join *join)
736 {
737         Plan       *outer_plan = join->plan.lefttree;
738         Plan       *inner_plan = join->plan.righttree;
739         indexed_tlist *outer_itlist;
740         indexed_tlist *inner_itlist;
741
742         outer_itlist = build_tlist_index(outer_plan->targetlist);
743         inner_itlist = build_tlist_index(inner_plan->targetlist);
744
745         /* All join plans have tlist, qual, and joinqual */
746         join->plan.targetlist = join_references(join->plan.targetlist,
747                                                                                         outer_itlist,
748                                                                                         inner_itlist,
749                                                                                         (Index) 0);
750         join->plan.qual = join_references(join->plan.qual,
751                                                                           outer_itlist,
752                                                                           inner_itlist,
753                                                                           (Index) 0);
754         join->joinqual = join_references(join->joinqual,
755                                                                          outer_itlist,
756                                                                          inner_itlist,
757                                                                          (Index) 0);
758
759         /* Now do join-type-specific stuff */
760         if (IsA(join, NestLoop))
761         {
762                 /* This processing is split out to handle possible recursion */
763                 set_inner_join_references(inner_plan,
764                                                                   outer_itlist);
765         }
766         else if (IsA(join, MergeJoin))
767         {
768                 MergeJoin  *mj = (MergeJoin *) join;
769
770                 mj->mergeclauses = join_references(mj->mergeclauses,
771                                                                                    outer_itlist,
772                                                                                    inner_itlist,
773                                                                                    (Index) 0);
774         }
775         else if (IsA(join, HashJoin))
776         {
777                 HashJoin   *hj = (HashJoin *) join;
778
779                 hj->hashclauses = join_references(hj->hashclauses,
780                                                                                   outer_itlist,
781                                                                                   inner_itlist,
782                                                                                   (Index) 0);
783         }
784
785         pfree(outer_itlist);
786         pfree(inner_itlist);
787 }
788
789 /*
790  * set_inner_join_references
791  *              Handle join references appearing in an inner indexscan's quals
792  *
793  * To handle bitmap-scan plan trees, we have to be able to recurse down
794  * to the bottom BitmapIndexScan nodes; likewise, appendrel indexscans
795  * require recursing through Append nodes.      This is split out as a separate
796  * function so that it can recurse.
797  */
798 static void
799 set_inner_join_references(Plan *inner_plan, indexed_tlist *outer_itlist)
800 {
801         if (IsA(inner_plan, IndexScan))
802         {
803                 /*
804                  * An index is being used to reduce the number of tuples scanned in
805                  * the inner relation.  If there are join clauses being used with the
806                  * index, we must update their outer-rel var nodes to refer to the
807                  * outer side of the join.
808                  */
809                 IndexScan  *innerscan = (IndexScan *) inner_plan;
810                 List       *indexqualorig = innerscan->indexqualorig;
811
812                 /* No work needed if indexqual refers only to its own rel... */
813                 if (NumRelids((Node *) indexqualorig) > 1)
814                 {
815                         Index           innerrel = innerscan->scan.scanrelid;
816
817                         /* only refs to outer vars get changed in the inner qual */
818                         innerscan->indexqualorig = join_references(indexqualorig,
819                                                                                                            outer_itlist,
820                                                                                                            NULL,
821                                                                                                            innerrel);
822                         innerscan->indexqual = join_references(innerscan->indexqual,
823                                                                                                    outer_itlist,
824                                                                                                    NULL,
825                                                                                                    innerrel);
826
827                         /*
828                          * We must fix the inner qpqual too, if it has join clauses (this
829                          * could happen if special operators are involved: some indexquals
830                          * may get rechecked as qpquals).
831                          */
832                         if (NumRelids((Node *) inner_plan->qual) > 1)
833                                 inner_plan->qual = join_references(inner_plan->qual,
834                                                                                                    outer_itlist,
835                                                                                                    NULL,
836                                                                                                    innerrel);
837                 }
838         }
839         else if (IsA(inner_plan, BitmapIndexScan))
840         {
841                 /*
842                  * Same, but index is being used within a bitmap plan.
843                  */
844                 BitmapIndexScan *innerscan = (BitmapIndexScan *) inner_plan;
845                 List       *indexqualorig = innerscan->indexqualorig;
846
847                 /* No work needed if indexqual refers only to its own rel... */
848                 if (NumRelids((Node *) indexqualorig) > 1)
849                 {
850                         Index           innerrel = innerscan->scan.scanrelid;
851
852                         /* only refs to outer vars get changed in the inner qual */
853                         innerscan->indexqualorig = join_references(indexqualorig,
854                                                                                                            outer_itlist,
855                                                                                                            NULL,
856                                                                                                            innerrel);
857                         innerscan->indexqual = join_references(innerscan->indexqual,
858                                                                                                    outer_itlist,
859                                                                                                    NULL,
860                                                                                                    innerrel);
861                         /* no need to fix inner qpqual */
862                         Assert(inner_plan->qual == NIL);
863                 }
864         }
865         else if (IsA(inner_plan, BitmapHeapScan))
866         {
867                 /*
868                  * The inner side is a bitmap scan plan.  Fix the top node, and
869                  * recurse to get the lower nodes.
870                  *
871                  * Note: create_bitmap_scan_plan removes clauses from bitmapqualorig
872                  * if they are duplicated in qpqual, so must test these independently.
873                  */
874                 BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan;
875                 Index           innerrel = innerscan->scan.scanrelid;
876                 List       *bitmapqualorig = innerscan->bitmapqualorig;
877
878                 /* only refs to outer vars get changed in the inner qual */
879                 if (NumRelids((Node *) bitmapqualorig) > 1)
880                         innerscan->bitmapqualorig = join_references(bitmapqualorig,
881                                                                                                                 outer_itlist,
882                                                                                                                 NULL,
883                                                                                                                 innerrel);
884
885                 /*
886                  * We must fix the inner qpqual too, if it has join clauses (this
887                  * could happen if special operators are involved: some indexquals may
888                  * get rechecked as qpquals).
889                  */
890                 if (NumRelids((Node *) inner_plan->qual) > 1)
891                         inner_plan->qual = join_references(inner_plan->qual,
892                                                                                            outer_itlist,
893                                                                                            NULL,
894                                                                                            innerrel);
895
896                 /* Now recurse */
897                 set_inner_join_references(inner_plan->lefttree,
898                                                                   outer_itlist);
899         }
900         else if (IsA(inner_plan, BitmapAnd))
901         {
902                 /* All we need do here is recurse */
903                 BitmapAnd  *innerscan = (BitmapAnd *) inner_plan;
904                 ListCell   *l;
905
906                 foreach(l, innerscan->bitmapplans)
907                 {
908                         set_inner_join_references((Plan *) lfirst(l),
909                                                                           outer_itlist);
910                 }
911         }
912         else if (IsA(inner_plan, BitmapOr))
913         {
914                 /* All we need do here is recurse */
915                 BitmapOr   *innerscan = (BitmapOr *) inner_plan;
916                 ListCell   *l;
917
918                 foreach(l, innerscan->bitmapplans)
919                 {
920                         set_inner_join_references((Plan *) lfirst(l),
921                                                                           outer_itlist);
922                 }
923         }
924         else if (IsA(inner_plan, Append))
925         {
926                 /*
927                  * The inner side is an append plan.  Recurse to see if it contains
928                  * indexscans that need to be fixed.
929                  */
930                 Append     *appendplan = (Append *) inner_plan;
931                 ListCell   *l;
932
933                 foreach(l, appendplan->appendplans)
934                 {
935                         set_inner_join_references((Plan *) lfirst(l),
936                                                                           outer_itlist);
937                 }
938         }
939         else if (IsA(inner_plan, TidScan))
940         {
941                 TidScan    *innerscan = (TidScan *) inner_plan;
942                 Index           innerrel = innerscan->scan.scanrelid;
943
944                 innerscan->tidquals = join_references(innerscan->tidquals,
945                                                                                           outer_itlist,
946                                                                                           NULL,
947                                                                                           innerrel);
948         }
949 }
950
951 /*
952  * set_uppernode_references
953  *        Update the targetlist and quals of an upper-level plan node
954  *        to refer to the tuples returned by its lefttree subplan.
955  *
956  * This is used for single-input plan types like Agg, Group, Result.
957  *
958  * In most cases, we have to match up individual Vars in the tlist and
959  * qual expressions with elements of the subplan's tlist (which was
960  * generated by flatten_tlist() from these selfsame expressions, so it
961  * should have all the required variables).  There is an important exception,
962  * however: GROUP BY and ORDER BY expressions will have been pushed into the
963  * subplan tlist unflattened.  If these values are also needed in the output
964  * then we want to reference the subplan tlist element rather than recomputing
965  * the expression.
966  */
967 static void
968 set_uppernode_references(Plan *plan, Index subvarno)
969 {
970         Plan       *subplan = plan->lefttree;
971         indexed_tlist *subplan_itlist;
972         List       *output_targetlist;
973         ListCell   *l;
974
975         if (subplan != NULL)
976                 subplan_itlist = build_tlist_index(subplan->targetlist);
977         else
978                 subplan_itlist = build_tlist_index(NIL);
979
980         output_targetlist = NIL;
981         foreach(l, plan->targetlist)
982         {
983                 TargetEntry *tle = (TargetEntry *) lfirst(l);
984                 Node       *newexpr;
985
986                 newexpr = replace_vars_with_subplan_refs((Node *) tle->expr,
987                                                                                                  subplan_itlist,
988                                                                                                  subvarno);
989                 tle = flatCopyTargetEntry(tle);
990                 tle->expr = (Expr *) newexpr;
991                 output_targetlist = lappend(output_targetlist, tle);
992         }
993         plan->targetlist = output_targetlist;
994
995         plan->qual = (List *)
996                 replace_vars_with_subplan_refs((Node *) plan->qual,
997                                                                            subplan_itlist,
998                                                                            subvarno);
999
1000         pfree(subplan_itlist);
1001 }
1002
1003 /*
1004  * build_tlist_index --- build an index data structure for a child tlist
1005  *
1006  * In most cases, subplan tlists will be "flat" tlists with only Vars,
1007  * so we try to optimize that case by extracting information about Vars
1008  * in advance.  Matching a parent tlist to a child is still an O(N^2)
1009  * operation, but at least with a much smaller constant factor than plain
1010  * tlist_member() searches.
1011  *
1012  * The result of this function is an indexed_tlist struct to pass to
1013  * search_indexed_tlist_for_var() or search_indexed_tlist_for_non_var().
1014  * When done, the indexed_tlist may be freed with a single pfree().
1015  */
1016 static indexed_tlist *
1017 build_tlist_index(List *tlist)
1018 {
1019         indexed_tlist *itlist;
1020         tlist_vinfo *vinfo;
1021         ListCell   *l;
1022
1023         /* Create data structure with enough slots for all tlist entries */
1024         itlist = (indexed_tlist *)
1025                 palloc(offsetof(indexed_tlist, vars) +
1026                            list_length(tlist) * sizeof(tlist_vinfo));
1027
1028         itlist->tlist = tlist;
1029         itlist->has_non_vars = false;
1030
1031         /* Find the Vars and fill in the index array */
1032         vinfo = itlist->vars;
1033         foreach(l, tlist)
1034         {
1035                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1036
1037                 if (tle->expr && IsA(tle->expr, Var))
1038                 {
1039                         Var                *var = (Var *) tle->expr;
1040
1041                         vinfo->varno = var->varno;
1042                         vinfo->varattno = var->varattno;
1043                         vinfo->resno = tle->resno;
1044                         vinfo++;
1045                 }
1046                 else
1047                         itlist->has_non_vars = true;
1048         }
1049
1050         itlist->num_vars = (vinfo - itlist->vars);
1051
1052         return itlist;
1053 }
1054
1055 /*
1056  * build_tlist_index_other_vars --- build a restricted tlist index
1057  *
1058  * This is like build_tlist_index, but we only index tlist entries that
1059  * are Vars and belong to some rel other than the one specified.
1060  */
1061 static indexed_tlist *
1062 build_tlist_index_other_vars(List *tlist, Index ignore_rel)
1063 {
1064         indexed_tlist *itlist;
1065         tlist_vinfo *vinfo;
1066         ListCell   *l;
1067
1068         /* Create data structure with enough slots for all tlist entries */
1069         itlist = (indexed_tlist *)
1070                 palloc(offsetof(indexed_tlist, vars) +
1071                            list_length(tlist) * sizeof(tlist_vinfo));
1072
1073         itlist->tlist = tlist;
1074         itlist->has_non_vars = false;
1075
1076         /* Find the desired Vars and fill in the index array */
1077         vinfo = itlist->vars;
1078         foreach(l, tlist)
1079         {
1080                 TargetEntry *tle = (TargetEntry *) lfirst(l);
1081
1082                 if (tle->expr && IsA(tle->expr, Var))
1083                 {
1084                         Var                *var = (Var *) tle->expr;
1085
1086                         if (var->varno != ignore_rel)
1087                         {
1088                                 vinfo->varno = var->varno;
1089                                 vinfo->varattno = var->varattno;
1090                                 vinfo->resno = tle->resno;
1091                                 vinfo++;
1092                         }
1093                 }
1094         }
1095
1096         itlist->num_vars = (vinfo - itlist->vars);
1097
1098         return itlist;
1099 }
1100
1101 /*
1102  * search_indexed_tlist_for_var --- find a Var in an indexed tlist
1103  *
1104  * If a match is found, return a copy of the given Var with suitably
1105  * modified varno/varattno (to wit, newvarno and the resno of the TLE entry).
1106  * If no match, return NULL.
1107  */
1108 static Var *
1109 search_indexed_tlist_for_var(Var *var, indexed_tlist *itlist, Index newvarno)
1110 {
1111         Index           varno = var->varno;
1112         AttrNumber      varattno = var->varattno;
1113         tlist_vinfo *vinfo;
1114         int                     i;
1115
1116         vinfo = itlist->vars;
1117         i = itlist->num_vars;
1118         while (i-- > 0)
1119         {
1120                 if (vinfo->varno == varno && vinfo->varattno == varattno)
1121                 {
1122                         /* Found a match */
1123                         Var                *newvar = (Var *) copyObject(var);
1124
1125                         newvar->varno = newvarno;
1126                         newvar->varattno = vinfo->resno;
1127                         return newvar;
1128                 }
1129                 vinfo++;
1130         }
1131         return NULL;                            /* no match */
1132 }
1133
1134 /*
1135  * search_indexed_tlist_for_non_var --- find a non-Var in an indexed tlist
1136  *
1137  * If a match is found, return a Var constructed to reference the tlist item.
1138  * If no match, return NULL.
1139  *
1140  * NOTE: it is a waste of time to call this if !itlist->has_non_vars
1141  */
1142 static Var *
1143 search_indexed_tlist_for_non_var(Node *node,
1144                                                                  indexed_tlist *itlist, Index newvarno)
1145 {
1146         TargetEntry *tle;
1147
1148         tle = tlist_member(node, itlist->tlist);
1149         if (tle)
1150         {
1151                 /* Found a matching subplan output expression */
1152                 Var                *newvar;
1153
1154                 newvar = makeVar(newvarno,
1155                                                  tle->resno,
1156                                                  exprType((Node *) tle->expr),
1157                                                  exprTypmod((Node *) tle->expr),
1158                                                  0);
1159                 newvar->varnoold = 0;   /* wasn't ever a plain Var */
1160                 newvar->varoattno = 0;
1161                 return newvar;
1162         }
1163         return NULL;                            /* no match */
1164 }
1165
1166 /*
1167  * join_references
1168  *         Creates a new set of targetlist entries or join qual clauses by
1169  *         changing the varno/varattno values of variables in the clauses
1170  *         to reference target list values from the outer and inner join
1171  *         relation target lists.
1172  *
1173  * This is used in two different scenarios: a normal join clause, where
1174  * all the Vars in the clause *must* be replaced by OUTER or INNER references;
1175  * and an indexscan being used on the inner side of a nestloop join.
1176  * In the latter case we want to replace the outer-relation Vars by OUTER
1177  * references, but not touch the Vars of the inner relation.  (We also
1178  * implement RETURNING clause fixup using this second scenario.)
1179  *
1180  * For a normal join, acceptable_rel should be zero so that any failure to
1181  * match a Var will be reported as an error.  For the indexscan case,
1182  * pass inner_itlist = NULL and acceptable_rel = the ID of the inner relation.
1183  *
1184  * 'clauses' is the targetlist or list of join clauses
1185  * 'outer_itlist' is the indexed target list of the outer join relation
1186  * 'inner_itlist' is the indexed target list of the inner join relation,
1187  *              or NULL
1188  * 'acceptable_rel' is either zero or the rangetable index of a relation
1189  *              whose Vars may appear in the clause without provoking an error.
1190  *
1191  * Returns the new expression tree.  The original clause structure is
1192  * not modified.
1193  */
1194 static List *
1195 join_references(List *clauses,
1196                                 indexed_tlist *outer_itlist,
1197                                 indexed_tlist *inner_itlist,
1198                                 Index acceptable_rel)
1199 {
1200         join_references_context context;
1201
1202         context.outer_itlist = outer_itlist;
1203         context.inner_itlist = inner_itlist;
1204         context.acceptable_rel = acceptable_rel;
1205         return (List *) join_references_mutator((Node *) clauses, &context);
1206 }
1207
1208 static Node *
1209 join_references_mutator(Node *node,
1210                                                 join_references_context *context)
1211 {
1212         Var                *newvar;
1213
1214         if (node == NULL)
1215                 return NULL;
1216         if (IsA(node, Var))
1217         {
1218                 Var                *var = (Var *) node;
1219
1220                 /* First look for the var in the input tlists */
1221                 newvar = search_indexed_tlist_for_var(var,
1222                                                                                           context->outer_itlist,
1223                                                                                           OUTER);
1224                 if (newvar)
1225                         return (Node *) newvar;
1226                 if (context->inner_itlist)
1227                 {
1228                         newvar = search_indexed_tlist_for_var(var,
1229                                                                                                   context->inner_itlist,
1230                                                                                                   INNER);
1231                         if (newvar)
1232                                 return (Node *) newvar;
1233                 }
1234
1235                 /* Return the Var unmodified, if it's for acceptable_rel */
1236                 if (var->varno == context->acceptable_rel)
1237                         return (Node *) copyObject(var);
1238
1239                 /* No referent found for Var */
1240                 elog(ERROR, "variable not found in subplan target lists");
1241         }
1242         /* Try matching more complex expressions too, if tlists have any */
1243         if (context->outer_itlist->has_non_vars)
1244         {
1245                 newvar = search_indexed_tlist_for_non_var(node,
1246                                                                                                   context->outer_itlist,
1247                                                                                                   OUTER);
1248                 if (newvar)
1249                         return (Node *) newvar;
1250         }
1251         if (context->inner_itlist && context->inner_itlist->has_non_vars)
1252         {
1253                 newvar = search_indexed_tlist_for_non_var(node,
1254                                                                                                   context->inner_itlist,
1255                                                                                                   INNER);
1256                 if (newvar)
1257                         return (Node *) newvar;
1258         }
1259         return expression_tree_mutator(node,
1260                                                                    join_references_mutator,
1261                                                                    (void *) context);
1262 }
1263
1264 /*
1265  * replace_vars_with_subplan_refs
1266  *              This routine modifies an expression tree so that all Var nodes
1267  *              reference target nodes of a subplan.  It is used to fix up
1268  *              target and qual expressions of non-join upper-level plan nodes.
1269  *
1270  * An error is raised if no matching var can be found in the subplan tlist
1271  * --- so this routine should only be applied to nodes whose subplans'
1272  * targetlists were generated via flatten_tlist() or some such method.
1273  *
1274  * If itlist->has_non_vars is true, then we try to match whole subexpressions
1275  * against elements of the subplan tlist, so that we can avoid recomputing
1276  * expressions that were already computed by the subplan.  (This is relatively
1277  * expensive, so we don't want to try it in the common case where the
1278  * subplan tlist is just a flattened list of Vars.)
1279  *
1280  * 'node': the tree to be fixed (a target item or qual)
1281  * 'subplan_itlist': indexed target list for subplan
1282  * 'subvarno': varno to be assigned to all Vars
1283  *
1284  * The resulting tree is a copy of the original in which all Var nodes have
1285  * varno = subvarno, varattno = resno of corresponding subplan target.
1286  * The original tree is not modified.
1287  */
1288 static Node *
1289 replace_vars_with_subplan_refs(Node *node,
1290                                                            indexed_tlist *subplan_itlist,
1291                                                            Index subvarno)
1292 {
1293         replace_vars_with_subplan_refs_context context;
1294
1295         context.subplan_itlist = subplan_itlist;
1296         context.subvarno = subvarno;
1297         return replace_vars_with_subplan_refs_mutator(node, &context);
1298 }
1299
1300 static Node *
1301 replace_vars_with_subplan_refs_mutator(Node *node,
1302                                                          replace_vars_with_subplan_refs_context *context)
1303 {
1304         Var                *newvar;
1305
1306         if (node == NULL)
1307                 return NULL;
1308         if (IsA(node, Var))
1309         {
1310                 Var                *var = (Var *) node;
1311
1312                 newvar = search_indexed_tlist_for_var(var,
1313                                                                                           context->subplan_itlist,
1314                                                                                           context->subvarno);
1315                 if (!newvar)
1316                         elog(ERROR, "variable not found in subplan target list");
1317                 return (Node *) newvar;
1318         }
1319         /* Try matching more complex expressions too, if tlist has any */
1320         if (context->subplan_itlist->has_non_vars)
1321         {
1322                 newvar = search_indexed_tlist_for_non_var(node,
1323                                                                                                   context->subplan_itlist,
1324                                                                                                   context->subvarno);
1325                 if (newvar)
1326                         return (Node *) newvar;
1327         }
1328         return expression_tree_mutator(node,
1329                                                                    replace_vars_with_subplan_refs_mutator,
1330                                                                    (void *) context);
1331 }
1332
1333 /*
1334  * set_returning_clause_references
1335  *              Perform setrefs.c's work on a RETURNING targetlist
1336  *
1337  * If the query involves more than just the result table, we have to
1338  * adjust any Vars that refer to other tables to reference junk tlist
1339  * entries in the top plan's targetlist.  Vars referencing the result
1340  * table should be left alone, however (the executor will evaluate them
1341  * using the actual heap tuple, after firing triggers if any).  In the
1342  * adjusted RETURNING list, result-table Vars will still have their
1343  * original varno, but Vars for other rels will have varno OUTER.
1344  *
1345  * We also must apply fix_expr_references to the list.
1346  *
1347  * 'rlist': the RETURNING targetlist to be fixed
1348  * 'topplan': the top Plan node for the query (not yet passed through
1349  *              set_plan_references)
1350  * 'resultRelation': RT index of the query's result relation
1351  */
1352 List *
1353 set_returning_clause_references(List *rlist,
1354                                                                 Plan *topplan,
1355                                                                 Index resultRelation)
1356 {
1357         indexed_tlist *itlist;
1358
1359         /*
1360          * We can perform the desired Var fixup by abusing the join_references
1361          * machinery that normally handles inner indexscan fixup.  We search the
1362          * top plan's targetlist for Vars of non-result relations, and use
1363          * join_references to convert RETURNING Vars into references to those
1364          * tlist entries, while leaving result-rel Vars as-is.
1365          */
1366         itlist = build_tlist_index_other_vars(topplan->targetlist, resultRelation);
1367
1368         rlist = join_references(rlist,
1369                                                         itlist,
1370                                                         NULL,
1371                                                         resultRelation);
1372
1373         fix_expr_references(topplan, (Node *) rlist);
1374
1375         pfree(itlist);
1376
1377         return rlist;
1378 }
1379
1380 /*****************************************************************************
1381  *                                      OPERATOR REGPROC LOOKUP
1382  *****************************************************************************/
1383
1384 /*
1385  * fix_opfuncids
1386  *        Calculate opfuncid field from opno for each OpExpr node in given tree.
1387  *        The given tree can be anything expression_tree_walker handles.
1388  *
1389  * The argument is modified in-place.  (This is OK since we'd want the
1390  * same change for any node, even if it gets visited more than once due to
1391  * shared structure.)
1392  */
1393 void
1394 fix_opfuncids(Node *node)
1395 {
1396         /* This tree walk requires no special setup, so away we go... */
1397         fix_opfuncids_walker(node, NULL);
1398 }
1399
1400 static bool
1401 fix_opfuncids_walker(Node *node, void *context)
1402 {
1403         if (node == NULL)
1404                 return false;
1405         if (IsA(node, OpExpr))
1406                 set_opfuncid((OpExpr *) node);
1407         else if (IsA(node, DistinctExpr))
1408                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1409         else if (IsA(node, ScalarArrayOpExpr))
1410                 set_sa_opfuncid((ScalarArrayOpExpr *) node);
1411         else if (IsA(node, NullIfExpr))
1412                 set_opfuncid((OpExpr *) node);  /* rely on struct equivalence */
1413         return expression_tree_walker(node, fix_opfuncids_walker, context);
1414 }
1415
1416 /*
1417  * set_opfuncid
1418  *              Set the opfuncid (procedure OID) in an OpExpr node,
1419  *              if it hasn't been set already.
1420  *
1421  * Because of struct equivalence, this can also be used for
1422  * DistinctExpr and NullIfExpr nodes.
1423  */
1424 void
1425 set_opfuncid(OpExpr *opexpr)
1426 {
1427         if (opexpr->opfuncid == InvalidOid)
1428                 opexpr->opfuncid = get_opcode(opexpr->opno);
1429 }
1430
1431 /*
1432  * set_sa_opfuncid
1433  *              As above, for ScalarArrayOpExpr nodes.
1434  */
1435 void
1436 set_sa_opfuncid(ScalarArrayOpExpr *opexpr)
1437 {
1438         if (opexpr->opfuncid == InvalidOid)
1439                 opexpr->opfuncid = get_opcode(opexpr->opno);
1440 }