]> granicus.if.org Git - postgresql/blob - src/backend/optimizer/util/var.c
31749e46c0536e09b4cabca13a166eae6354a035
[postgresql] / src / backend / optimizer / util / var.c
1 /*-------------------------------------------------------------------------
2  *
3  * var.c
4  *        Var node manipulation routines
5  *
6  * Note: for most purposes, PlaceHolderVar is considered a Var too,
7  * even if its contained expression is variable-free.  Also, CurrentOfExpr
8  * is treated as a Var for purposes of determining whether an expression
9  * contains variables.
10  *
11  *
12  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
13  * Portions Copyright (c) 1994, Regents of the University of California
14  *
15  *
16  * IDENTIFICATION
17  *        $PostgreSQL: pgsql/src/backend/optimizer/util/var.c,v 1.81 2008/10/21 20:42:53 tgl Exp $
18  *
19  *-------------------------------------------------------------------------
20  */
21 #include "postgres.h"
22
23 #include "access/sysattr.h"
24 #include "nodes/nodeFuncs.h"
25 #include "optimizer/prep.h"
26 #include "optimizer/var.h"
27 #include "parser/parsetree.h"
28 #include "rewrite/rewriteManip.h"
29
30
31 typedef struct
32 {
33         Relids          varnos;
34         int                     sublevels_up;
35 } pull_varnos_context;
36
37 typedef struct
38 {
39         int                     var_location;
40         int                     sublevels_up;
41 } locate_var_of_level_context;
42
43 typedef struct
44 {
45         int                     var_location;
46         int                     relid;
47         int                     sublevels_up;
48 } locate_var_of_relation_context;
49
50 typedef struct
51 {
52         int                     min_varlevel;
53         int                     sublevels_up;
54 } find_minimum_var_level_context;
55
56 typedef struct
57 {
58         List       *varlist;
59         bool            includePlaceHolderVars;
60 } pull_var_clause_context;
61
62 typedef struct
63 {
64         PlannerInfo *root;
65         int                     sublevels_up;
66 } flatten_join_alias_vars_context;
67
68 static bool pull_varnos_walker(Node *node,
69                                    pull_varnos_context *context);
70 static bool pull_varattnos_walker(Node *node, Bitmapset **varattnos);
71 static bool contain_var_clause_walker(Node *node, void *context);
72 static bool contain_vars_of_level_walker(Node *node, int *sublevels_up);
73 static bool locate_var_of_level_walker(Node *node,
74                                                                            locate_var_of_level_context *context);
75 static bool locate_var_of_relation_walker(Node *node,
76                                                                         locate_var_of_relation_context *context);
77 static bool find_minimum_var_level_walker(Node *node,
78                                                           find_minimum_var_level_context *context);
79 static bool pull_var_clause_walker(Node *node,
80                                            pull_var_clause_context *context);
81 static Node *flatten_join_alias_vars_mutator(Node *node,
82                                                                 flatten_join_alias_vars_context *context);
83 static Relids alias_relid_set(PlannerInfo *root, Relids relids);
84
85
86 /*
87  * pull_varnos
88  *              Create a set of all the distinct varnos present in a parsetree.
89  *              Only varnos that reference level-zero rtable entries are considered.
90  *
91  * NOTE: this is used on not-yet-planned expressions.  It may therefore find
92  * bare SubLinks, and if so it needs to recurse into them to look for uplevel
93  * references to the desired rtable level!      But when we find a completed
94  * SubPlan, we only need to look at the parameters passed to the subplan.
95  */
96 Relids
97 pull_varnos(Node *node)
98 {
99         pull_varnos_context context;
100
101         context.varnos = NULL;
102         context.sublevels_up = 0;
103
104         /*
105          * Must be prepared to start with a Query or a bare expression tree; if
106          * it's a Query, we don't want to increment sublevels_up.
107          */
108         query_or_expression_tree_walker(node,
109                                                                         pull_varnos_walker,
110                                                                         (void *) &context,
111                                                                         0);
112
113         return context.varnos;
114 }
115
116 static bool
117 pull_varnos_walker(Node *node, pull_varnos_context *context)
118 {
119         if (node == NULL)
120                 return false;
121         if (IsA(node, Var))
122         {
123                 Var                *var = (Var *) node;
124
125                 if (var->varlevelsup == context->sublevels_up)
126                         context->varnos = bms_add_member(context->varnos, var->varno);
127                 return false;
128         }
129         if (IsA(node, CurrentOfExpr))
130         {
131                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
132
133                 if (context->sublevels_up == 0)
134                         context->varnos = bms_add_member(context->varnos, cexpr->cvarno);
135                 return false;
136         }
137         if (IsA(node, PlaceHolderVar))
138         {
139                 /*
140                  * Normally, we can just take the varnos in the contained expression.
141                  * But if it is variable-free, use the PHV's syntactic relids.
142                  */
143                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
144                 pull_varnos_context subcontext;
145
146                 subcontext.varnos = NULL;
147                 subcontext.sublevels_up = context->sublevels_up;
148                 (void) pull_varnos_walker((Node *) phv->phexpr, &subcontext);
149
150                 if (bms_is_empty(subcontext.varnos) &&
151                         phv->phlevelsup == context->sublevels_up)
152                         context->varnos = bms_add_members(context->varnos, phv->phrels);
153                 else
154                         context->varnos = bms_join(context->varnos, subcontext.varnos);
155                 return false;
156         }
157         if (IsA(node, Query))
158         {
159                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
160                 bool            result;
161
162                 context->sublevels_up++;
163                 result = query_tree_walker((Query *) node, pull_varnos_walker,
164                                                                    (void *) context, 0);
165                 context->sublevels_up--;
166                 return result;
167         }
168         return expression_tree_walker(node, pull_varnos_walker,
169                                                                   (void *) context);
170 }
171
172
173 /*
174  * pull_varattnos
175  *              Find all the distinct attribute numbers present in an expression tree,
176  *              and add them to the initial contents of *varattnos.
177  *              Only Vars that reference RTE 1 of rtable level zero are considered.
178  *
179  * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that
180  * we can include system attributes (e.g., OID) in the bitmap representation.
181  *
182  * Currently, this does not support subqueries nor expressions containing
183  * references to multiple tables; not needed since it's only applied to
184  * index expressions and predicates.
185  */
186 void
187 pull_varattnos(Node *node, Bitmapset **varattnos)
188 {
189         (void) pull_varattnos_walker(node, varattnos);
190 }
191
192 static bool
193 pull_varattnos_walker(Node *node, Bitmapset **varattnos)
194 {
195         if (node == NULL)
196                 return false;
197         if (IsA(node, Var))
198         {
199                 Var                *var = (Var *) node;
200
201                 Assert(var->varno == 1);
202                 *varattnos = bms_add_member(*varattnos,
203                                                  var->varattno - FirstLowInvalidHeapAttributeNumber);
204                 return false;
205         }
206         /* Should not find a subquery or subplan */
207         Assert(!IsA(node, Query));
208         Assert(!IsA(node, SubPlan));
209
210         return expression_tree_walker(node, pull_varattnos_walker,
211                                                                   (void *) varattnos);
212 }
213
214
215 /*
216  * contain_var_clause
217  *        Recursively scan a clause to discover whether it contains any Var nodes
218  *        (of the current query level).
219  *
220  *        Returns true if any varnode found.
221  *
222  * Does not examine subqueries, therefore must only be used after reduction
223  * of sublinks to subplans!
224  */
225 bool
226 contain_var_clause(Node *node)
227 {
228         return contain_var_clause_walker(node, NULL);
229 }
230
231 static bool
232 contain_var_clause_walker(Node *node, void *context)
233 {
234         if (node == NULL)
235                 return false;
236         if (IsA(node, Var))
237         {
238                 if (((Var *) node)->varlevelsup == 0)
239                         return true;            /* abort the tree traversal and return true */
240                 return false;
241         }
242         if (IsA(node, CurrentOfExpr))
243                 return true;
244         if (IsA(node, PlaceHolderVar))
245         {
246                 if (((PlaceHolderVar *) node)->phlevelsup == 0)
247                         return true;            /* abort the tree traversal and return true */
248                 /* else fall through to check the contained expr */
249         }
250         return expression_tree_walker(node, contain_var_clause_walker, context);
251 }
252
253
254 /*
255  * contain_vars_of_level
256  *        Recursively scan a clause to discover whether it contains any Var nodes
257  *        of the specified query level.
258  *
259  *        Returns true if any such Var found.
260  *
261  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
262  */
263 bool
264 contain_vars_of_level(Node *node, int levelsup)
265 {
266         int                     sublevels_up = levelsup;
267
268         return query_or_expression_tree_walker(node,
269                                                                                    contain_vars_of_level_walker,
270                                                                                    (void *) &sublevels_up,
271                                                                                    0);
272 }
273
274 static bool
275 contain_vars_of_level_walker(Node *node, int *sublevels_up)
276 {
277         if (node == NULL)
278                 return false;
279         if (IsA(node, Var))
280         {
281                 if (((Var *) node)->varlevelsup == *sublevels_up)
282                         return true;            /* abort tree traversal and return true */
283                 return false;
284         }
285         if (IsA(node, CurrentOfExpr))
286         {
287                 if (*sublevels_up == 0)
288                         return true;
289                 return false;
290         }
291         if (IsA(node, PlaceHolderVar))
292         {
293                 if (((PlaceHolderVar *) node)->phlevelsup == *sublevels_up)
294                         return true;            /* abort the tree traversal and return true */
295                 /* else fall through to check the contained expr */
296         }
297         if (IsA(node, Query))
298         {
299                 /* Recurse into subselects */
300                 bool            result;
301
302                 (*sublevels_up)++;
303                 result = query_tree_walker((Query *) node,
304                                                                    contain_vars_of_level_walker,
305                                                                    (void *) sublevels_up,
306                                                                    0);
307                 (*sublevels_up)--;
308                 return result;
309         }
310         return expression_tree_walker(node,
311                                                                   contain_vars_of_level_walker,
312                                                                   (void *) sublevels_up);
313 }
314
315
316 /*
317  * locate_var_of_level
318  *        Find the parse location of any Var of the specified query level.
319  *
320  * Returns -1 if no such Var is in the querytree, or if they all have
321  * unknown parse location.  (The former case is probably caller error,
322  * but we don't bother to distinguish it from the latter case.)
323  *
324  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
325  *
326  * Note: it might seem appropriate to merge this functionality into
327  * contain_vars_of_level, but that would complicate that function's API.
328  * Currently, the only uses of this function are for error reporting,
329  * and so shaving cycles probably isn't very important.
330  */
331 int
332 locate_var_of_level(Node *node, int levelsup)
333 {
334         locate_var_of_level_context context;
335
336         context.var_location = -1;              /* in case we find nothing */
337         context.sublevels_up = levelsup;
338
339         (void) query_or_expression_tree_walker(node,
340                                                                                    locate_var_of_level_walker,
341                                                                                    (void *) &context,
342                                                                                    0);
343
344         return context.var_location;
345 }
346
347 static bool
348 locate_var_of_level_walker(Node *node,
349                                                    locate_var_of_level_context *context)
350 {
351         if (node == NULL)
352                 return false;
353         if (IsA(node, Var))
354         {
355                 Var        *var = (Var *) node;
356
357                 if (var->varlevelsup == context->sublevels_up &&
358                         var->location >= 0)
359                 {
360                         context->var_location = var->location;
361                         return true;            /* abort tree traversal and return true */
362                 }
363                 return false;
364         }
365         if (IsA(node, CurrentOfExpr))
366         {
367                 /* since CurrentOfExpr doesn't carry location, nothing we can do */
368                 return false;
369         }
370         /* No extra code needed for PlaceHolderVar; just look in contained expr */
371         if (IsA(node, Query))
372         {
373                 /* Recurse into subselects */
374                 bool            result;
375
376                 context->sublevels_up++;
377                 result = query_tree_walker((Query *) node,
378                                                                    locate_var_of_level_walker,
379                                                                    (void *) context,
380                                                                    0);
381                 context->sublevels_up--;
382                 return result;
383         }
384         return expression_tree_walker(node,
385                                                                   locate_var_of_level_walker,
386                                                                   (void *) context);
387 }
388
389
390 /*
391  * locate_var_of_relation
392  *        Find the parse location of any Var of the specified relation.
393  *
394  * Returns -1 if no such Var is in the querytree, or if they all have
395  * unknown parse location.
396  *
397  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
398  */
399 int
400 locate_var_of_relation(Node *node, int relid, int levelsup)
401 {
402         locate_var_of_relation_context context;
403
404         context.var_location = -1;              /* in case we find nothing */
405         context.relid = relid;
406         context.sublevels_up = levelsup;
407
408         (void) query_or_expression_tree_walker(node,
409                                                                                    locate_var_of_relation_walker,
410                                                                                    (void *) &context,
411                                                                                    0);
412
413         return context.var_location;
414 }
415
416 static bool
417 locate_var_of_relation_walker(Node *node,
418                                                           locate_var_of_relation_context *context)
419 {
420         if (node == NULL)
421                 return false;
422         if (IsA(node, Var))
423         {
424                 Var        *var = (Var *) node;
425
426                 if (var->varno == context->relid &&
427                         var->varlevelsup == context->sublevels_up &&
428                         var->location >= 0)
429                 {
430                         context->var_location = var->location;
431                         return true;            /* abort tree traversal and return true */
432                 }
433                 return false;
434         }
435         if (IsA(node, CurrentOfExpr))
436         {
437                 /* since CurrentOfExpr doesn't carry location, nothing we can do */
438                 return false;
439         }
440         /* No extra code needed for PlaceHolderVar; just look in contained expr */
441         if (IsA(node, Query))
442         {
443                 /* Recurse into subselects */
444                 bool            result;
445
446                 context->sublevels_up++;
447                 result = query_tree_walker((Query *) node,
448                                                                    locate_var_of_relation_walker,
449                                                                    (void *) context,
450                                                                    0);
451                 context->sublevels_up--;
452                 return result;
453         }
454         return expression_tree_walker(node,
455                                                                   locate_var_of_relation_walker,
456                                                                   (void *) context);
457 }
458
459
460 /*
461  * find_minimum_var_level
462  *        Recursively scan a clause to find the lowest variable level it
463  *        contains --- for example, zero is returned if there are any local
464  *        variables, one if there are no local variables but there are
465  *        one-level-up outer references, etc.  Subqueries are scanned to see
466  *        if they possess relevant outer references.  (But any local variables
467  *        within subqueries are not relevant.)
468  *
469  *        -1 is returned if the clause has no variables at all.
470  *
471  * Will recurse into sublinks.  Also, may be invoked directly on a Query.
472  */
473 int
474 find_minimum_var_level(Node *node)
475 {
476         find_minimum_var_level_context context;
477
478         context.min_varlevel = -1;      /* signifies nothing found yet */
479         context.sublevels_up = 0;
480
481         (void) query_or_expression_tree_walker(node,
482                                                                                    find_minimum_var_level_walker,
483                                                                                    (void *) &context,
484                                                                                    0);
485
486         return context.min_varlevel;
487 }
488
489 static bool
490 find_minimum_var_level_walker(Node *node,
491                                                           find_minimum_var_level_context *context)
492 {
493         if (node == NULL)
494                 return false;
495         if (IsA(node, Var))
496         {
497                 int                     varlevelsup = ((Var *) node)->varlevelsup;
498
499                 /* convert levelsup to frame of reference of original query */
500                 varlevelsup -= context->sublevels_up;
501                 /* ignore local vars of subqueries */
502                 if (varlevelsup >= 0)
503                 {
504                         if (context->min_varlevel < 0 ||
505                                 context->min_varlevel > varlevelsup)
506                         {
507                                 context->min_varlevel = varlevelsup;
508
509                                 /*
510                                  * As soon as we find a local variable, we can abort the tree
511                                  * traversal, since min_varlevel is then certainly 0.
512                                  */
513                                 if (varlevelsup == 0)
514                                         return true;
515                         }
516                 }
517         }
518         if (IsA(node, CurrentOfExpr))
519         {
520                 int                     varlevelsup = 0;
521
522                 /* convert levelsup to frame of reference of original query */
523                 varlevelsup -= context->sublevels_up;
524                 /* ignore local vars of subqueries */
525                 if (varlevelsup >= 0)
526                 {
527                         if (context->min_varlevel < 0 ||
528                                 context->min_varlevel > varlevelsup)
529                         {
530                                 context->min_varlevel = varlevelsup;
531
532                                 /*
533                                  * As soon as we find a local variable, we can abort the tree
534                                  * traversal, since min_varlevel is then certainly 0.
535                                  */
536                                 if (varlevelsup == 0)
537                                         return true;
538                         }
539                 }
540         }
541
542         /*
543          * An Aggref must be treated like a Var of its level.  Normally we'd get
544          * the same result from looking at the Vars in the aggregate's argument,
545          * but this fails in the case of a Var-less aggregate call (COUNT(*)).
546          */
547         if (IsA(node, Aggref))
548         {
549                 int                     agglevelsup = ((Aggref *) node)->agglevelsup;
550
551                 /* convert levelsup to frame of reference of original query */
552                 agglevelsup -= context->sublevels_up;
553                 /* ignore local aggs of subqueries */
554                 if (agglevelsup >= 0)
555                 {
556                         if (context->min_varlevel < 0 ||
557                                 context->min_varlevel > agglevelsup)
558                         {
559                                 context->min_varlevel = agglevelsup;
560
561                                 /*
562                                  * As soon as we find a local aggregate, we can abort the tree
563                                  * traversal, since min_varlevel is then certainly 0.
564                                  */
565                                 if (agglevelsup == 0)
566                                         return true;
567                         }
568                 }
569         }
570         /* Likewise, make sure PlaceHolderVar is treated correctly */
571         if (IsA(node, PlaceHolderVar))
572         {
573                 int                     phlevelsup = ((PlaceHolderVar *) node)->phlevelsup;
574
575                 /* convert levelsup to frame of reference of original query */
576                 phlevelsup -= context->sublevels_up;
577                 /* ignore local vars of subqueries */
578                 if (phlevelsup >= 0)
579                 {
580                         if (context->min_varlevel < 0 ||
581                                 context->min_varlevel > phlevelsup)
582                         {
583                                 context->min_varlevel = phlevelsup;
584
585                                 /*
586                                  * As soon as we find a local variable, we can abort the tree
587                                  * traversal, since min_varlevel is then certainly 0.
588                                  */
589                                 if (phlevelsup == 0)
590                                         return true;
591                         }
592                 }
593         }
594         if (IsA(node, Query))
595         {
596                 /* Recurse into subselects */
597                 bool            result;
598
599                 context->sublevels_up++;
600                 result = query_tree_walker((Query *) node,
601                                                                    find_minimum_var_level_walker,
602                                                                    (void *) context,
603                                                                    0);
604                 context->sublevels_up--;
605                 return result;
606         }
607         return expression_tree_walker(node,
608                                                                   find_minimum_var_level_walker,
609                                                                   (void *) context);
610 }
611
612
613 /*
614  * pull_var_clause
615  *        Recursively pulls all Var nodes from an expression clause.
616  *
617  *        PlaceHolderVars are included too, if includePlaceHolderVars is true.
618  *        If it isn't true, an error is thrown if any are found.
619  *        Note that Vars within a PHV's expression are *not* included.
620  *
621  *        CurrentOfExpr nodes are *not* included.
622  *
623  *        Upper-level vars (with varlevelsup > 0) are not included.
624  *        (These probably represent errors too, but we don't complain.)
625  *
626  *        Returns list of nodes found.  Note the nodes themselves are not
627  *        copied, only referenced.
628  *
629  * Does not examine subqueries, therefore must only be used after reduction
630  * of sublinks to subplans!
631  */
632 List *
633 pull_var_clause(Node *node, bool includePlaceHolderVars)
634 {
635         pull_var_clause_context context;
636
637         context.varlist = NIL;
638         context.includePlaceHolderVars = includePlaceHolderVars;
639
640         pull_var_clause_walker(node, &context);
641         return context.varlist;
642 }
643
644 static bool
645 pull_var_clause_walker(Node *node, pull_var_clause_context *context)
646 {
647         if (node == NULL)
648                 return false;
649         if (IsA(node, Var))
650         {
651                 if (((Var *) node)->varlevelsup == 0)
652                         context->varlist = lappend(context->varlist, node);
653                 return false;
654         }
655         if (IsA(node, PlaceHolderVar))
656         {
657                 if (!context->includePlaceHolderVars)
658                         elog(ERROR, "PlaceHolderVar found where not expected");
659                 if (((PlaceHolderVar *) node)->phlevelsup == 0)
660                         context->varlist = lappend(context->varlist, node);
661                 /* we do NOT descend into the contained expression */
662                 return false;
663         }
664         return expression_tree_walker(node, pull_var_clause_walker,
665                                                                   (void *) context);
666 }
667
668
669 /*
670  * flatten_join_alias_vars
671  *        Replace Vars that reference JOIN outputs with references to the original
672  *        relation variables instead.  This allows quals involving such vars to be
673  *        pushed down.  Whole-row Vars that reference JOIN relations are expanded
674  *        into RowExpr constructs that name the individual output Vars.  This
675  *        is necessary since we will not scan the JOIN as a base relation, which
676  *        is the only way that the executor can directly handle whole-row Vars.
677  *
678  * This also adjusts relid sets found in some expression node types to
679  * substitute the contained base rels for any join relid.
680  *
681  * NOTE: this is used on not-yet-planned expressions.  We do not expect it
682  * to be applied directly to a Query node.
683  */
684 Node *
685 flatten_join_alias_vars(PlannerInfo *root, Node *node)
686 {
687         flatten_join_alias_vars_context context;
688
689         context.root = root;
690         context.sublevels_up = 0;
691
692         return flatten_join_alias_vars_mutator(node, &context);
693 }
694
695 static Node *
696 flatten_join_alias_vars_mutator(Node *node,
697                                                                 flatten_join_alias_vars_context *context)
698 {
699         if (node == NULL)
700                 return NULL;
701         if (IsA(node, Var))
702         {
703                 Var                *var = (Var *) node;
704                 RangeTblEntry *rte;
705                 Node       *newvar;
706
707                 /* No change unless Var belongs to a JOIN of the target level */
708                 if (var->varlevelsup != context->sublevels_up)
709                         return node;            /* no need to copy, really */
710                 rte = rt_fetch(var->varno, context->root->parse->rtable);
711                 if (rte->rtekind != RTE_JOIN)
712                         return node;
713                 if (var->varattno == InvalidAttrNumber)
714                 {
715                         /* Must expand whole-row reference */
716                         RowExpr    *rowexpr;
717                         List       *fields = NIL;
718                         AttrNumber      attnum;
719                         ListCell   *l;
720
721                         attnum = 0;
722                         foreach(l, rte->joinaliasvars)
723                         {
724                                 newvar = (Node *) lfirst(l);
725                                 attnum++;
726                                 /* Ignore dropped columns */
727                                 if (IsA(newvar, Const))
728                                         continue;
729
730                                 /*
731                                  * If we are expanding an alias carried down from an upper
732                                  * query, must adjust its varlevelsup fields.
733                                  */
734                                 if (context->sublevels_up != 0)
735                                 {
736                                         newvar = copyObject(newvar);
737                                         IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
738                                 }
739                                 /* Recurse in case join input is itself a join */
740                                 newvar = flatten_join_alias_vars_mutator(newvar, context);
741                                 fields = lappend(fields, newvar);
742                         }
743                         rowexpr = makeNode(RowExpr);
744                         rowexpr->args = fields;
745                         rowexpr->row_typeid = var->vartype;
746                         rowexpr->row_format = COERCE_IMPLICIT_CAST;
747                         rowexpr->colnames = NIL;
748                         rowexpr->location = -1;
749
750                         return (Node *) rowexpr;
751                 }
752
753                 /* Expand join alias reference */
754                 Assert(var->varattno > 0);
755                 newvar = (Node *) list_nth(rte->joinaliasvars, var->varattno - 1);
756
757                 /*
758                  * If we are expanding an alias carried down from an upper query, must
759                  * adjust its varlevelsup fields.
760                  */
761                 if (context->sublevels_up != 0)
762                 {
763                         newvar = copyObject(newvar);
764                         IncrementVarSublevelsUp(newvar, context->sublevels_up, 0);
765                 }
766                 /* Recurse in case join input is itself a join */
767                 return flatten_join_alias_vars_mutator(newvar, context);
768         }
769         if (IsA(node, FlattenedSubLink))
770         {
771                 /* Copy the FlattenedSubLink node with correct mutation of subnodes */
772                 FlattenedSubLink *fslink;
773
774                 fslink = (FlattenedSubLink *) expression_tree_mutator(node,
775                                                                                          flatten_join_alias_vars_mutator,
776                                                                                                                          (void *) context);
777                 /* now fix FlattenedSubLink's relid sets */
778                 if (context->sublevels_up == 0)
779                 {
780                         fslink->lefthand = alias_relid_set(context->root,
781                                                                                            fslink->lefthand);
782                         fslink->righthand = alias_relid_set(context->root,
783                                                                                                 fslink->righthand);
784                 }
785                 return (Node *) fslink;
786         }
787         if (IsA(node, PlaceHolderVar))
788         {
789                 /* Copy the PlaceHolderVar node with correct mutation of subnodes */
790                 PlaceHolderVar *phv;
791
792                 phv = (PlaceHolderVar *) expression_tree_mutator(node,
793                                                                                          flatten_join_alias_vars_mutator,
794                                                                                                                  (void *) context);
795                 /* now fix PlaceHolderVar's relid sets */
796                 if (phv->phlevelsup == context->sublevels_up)
797                 {
798                         phv->phrels = alias_relid_set(context->root,
799                                                                                   phv->phrels);
800                 }
801                 return (Node *) phv;
802         }
803         if (IsA(node, PlaceHolderInfo))
804         {
805                 /* Copy the PlaceHolderInfo node with correct mutation of subnodes */
806                 PlaceHolderInfo *phinfo;
807
808                 phinfo = (PlaceHolderInfo *) expression_tree_mutator(node,
809                                                                                          flatten_join_alias_vars_mutator,
810                                                                                                                          (void *) context);
811                 /* now fix PlaceHolderInfo's relid sets */
812                 if (context->sublevels_up == 0)
813                 {
814                         phinfo->ph_eval_at = alias_relid_set(context->root,
815                                                                                                  phinfo->ph_eval_at);
816                         phinfo->ph_needed = alias_relid_set(context->root,
817                                                                                                 phinfo->ph_needed);
818                 }
819                 return (Node *) phinfo;
820         }
821
822         if (IsA(node, Query))
823         {
824                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
825                 Query      *newnode;
826
827                 context->sublevels_up++;
828                 newnode = query_tree_mutator((Query *) node,
829                                                                          flatten_join_alias_vars_mutator,
830                                                                          (void *) context,
831                                                                          QTW_IGNORE_JOINALIASES);
832                 context->sublevels_up--;
833                 return (Node *) newnode;
834         }
835         /* Already-planned tree not supported */
836         Assert(!IsA(node, SubPlan));
837
838         return expression_tree_mutator(node, flatten_join_alias_vars_mutator,
839                                                                    (void *) context);
840 }
841
842 /*
843  * alias_relid_set: in a set of RT indexes, replace joins by their
844  * underlying base relids
845  */
846 static Relids
847 alias_relid_set(PlannerInfo *root, Relids relids)
848 {
849         Relids          result = NULL;
850         Relids          tmprelids;
851         int                     rtindex;
852
853         tmprelids = bms_copy(relids);
854         while ((rtindex = bms_first_member(tmprelids)) >= 0)
855         {
856                 RangeTblEntry *rte = rt_fetch(rtindex, root->parse->rtable);
857
858                 if (rte->rtekind == RTE_JOIN)
859                         result = bms_join(result, get_relids_for_join(root, rtindex));
860                 else
861                         result = bms_add_member(result, rtindex);
862         }
863         bms_free(tmprelids);
864         return result;
865 }