]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
0322c58f3f02a687f40394f9d477f63976832012
[postgresql] / src / backend / rewrite / rewriteManip.c
1 /*-------------------------------------------------------------------------
2  *
3  * rewriteManip.c
4  *
5  * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
6  * Portions Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * IDENTIFICATION
10  *        $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.117 2008/10/22 20:17:52 tgl Exp $
11  *
12  *-------------------------------------------------------------------------
13  */
14 #include "postgres.h"
15
16 #include "catalog/pg_type.h"
17 #include "nodes/makefuncs.h"
18 #include "nodes/nodeFuncs.h"
19 #include "optimizer/clauses.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_relation.h"
22 #include "parser/parsetree.h"
23 #include "rewrite/rewriteManip.h"
24
25
26 typedef struct
27 {
28         int                     sublevels_up;
29 } contain_aggs_of_level_context;
30
31 typedef struct
32 {
33         int                     agg_location;
34         int                     sublevels_up;
35 } locate_agg_of_level_context;
36
37 static bool contain_aggs_of_level_walker(Node *node,
38                                                 contain_aggs_of_level_context *context);
39 static bool locate_agg_of_level_walker(Node *node,
40                                                 locate_agg_of_level_context *context);
41 static bool checkExprHasSubLink_walker(Node *node, void *context);
42 static Relids offset_relid_set(Relids relids, int offset);
43 static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
44
45
46 /*
47  * checkExprHasAggs -
48  *      Check if an expression contains an aggregate function call of the
49  *      current query level.
50  */
51 bool
52 checkExprHasAggs(Node *node)
53 {
54         return contain_aggs_of_level(node, 0);
55 }
56
57 /*
58  * contain_aggs_of_level -
59  *      Check if an expression contains an aggregate function call of a
60  *      specified query level.
61  *
62  * The objective of this routine is to detect whether there are aggregates
63  * belonging to the given query level.  Aggregates belonging to subqueries
64  * or outer queries do NOT cause a true result.  We must recurse into
65  * subqueries to detect outer-reference aggregates that logically belong to
66  * the specified query level.
67  */
68 bool
69 contain_aggs_of_level(Node *node, int levelsup)
70 {
71         contain_aggs_of_level_context context;
72
73         context.sublevels_up = levelsup;
74
75         /*
76          * Must be prepared to start with a Query or a bare expression tree; if
77          * it's a Query, we don't want to increment sublevels_up.
78          */
79         return query_or_expression_tree_walker(node,
80                                                                                    contain_aggs_of_level_walker,
81                                                                                    (void *) &context,
82                                                                                    0);
83 }
84
85 static bool
86 contain_aggs_of_level_walker(Node *node,
87                                                          contain_aggs_of_level_context *context)
88 {
89         if (node == NULL)
90                 return false;
91         if (IsA(node, Aggref))
92         {
93                 if (((Aggref *) node)->agglevelsup == context->sublevels_up)
94                         return true;            /* abort the tree traversal and return true */
95                 /* else fall through to examine argument */
96         }
97         if (IsA(node, Query))
98         {
99                 /* Recurse into subselects */
100                 bool            result;
101
102                 context->sublevels_up++;
103                 result = query_tree_walker((Query *) node,
104                                                                    contain_aggs_of_level_walker,
105                                                                    (void *) context, 0);
106                 context->sublevels_up--;
107                 return result;
108         }
109         return expression_tree_walker(node, contain_aggs_of_level_walker,
110                                                                   (void *) context);
111 }
112
113 /*
114  * locate_agg_of_level -
115  *        Find the parse location of any aggregate of the specified query level.
116  *
117  * Returns -1 if no such agg is in the querytree, or if they all have
118  * unknown parse location.  (The former case is probably caller error,
119  * but we don't bother to distinguish it from the latter case.)
120  *
121  * Note: it might seem appropriate to merge this functionality into
122  * contain_aggs_of_level, but that would complicate that function's API.
123  * Currently, the only uses of this function are for error reporting,
124  * and so shaving cycles probably isn't very important.
125  */
126 int
127 locate_agg_of_level(Node *node, int levelsup)
128 {
129         locate_agg_of_level_context context;
130
131         context.agg_location = -1;              /* in case we find nothing */
132         context.sublevels_up = levelsup;
133
134         /*
135          * Must be prepared to start with a Query or a bare expression tree; if
136          * it's a Query, we don't want to increment sublevels_up.
137          */
138         (void) query_or_expression_tree_walker(node,
139                                                                                    locate_agg_of_level_walker,
140                                                                                    (void *) &context,
141                                                                                    0);
142
143         return context.agg_location;
144 }
145
146 static bool
147 locate_agg_of_level_walker(Node *node,
148                                                    locate_agg_of_level_context *context)
149 {
150         if (node == NULL)
151                 return false;
152         if (IsA(node, Aggref))
153         {
154                 if (((Aggref *) node)->agglevelsup == context->sublevels_up &&
155                         ((Aggref *) node)->location >= 0)
156                 {
157                         context->agg_location = ((Aggref *) node)->location;
158                         return true;            /* abort the tree traversal and return true */
159                 }
160                 /* else fall through to examine argument */
161         }
162         if (IsA(node, Query))
163         {
164                 /* Recurse into subselects */
165                 bool            result;
166
167                 context->sublevels_up++;
168                 result = query_tree_walker((Query *) node,
169                                                                    locate_agg_of_level_walker,
170                                                                    (void *) context, 0);
171                 context->sublevels_up--;
172                 return result;
173         }
174         return expression_tree_walker(node, locate_agg_of_level_walker,
175                                                                   (void *) context);
176 }
177
178 /*
179  * checkExprHasSubLink -
180  *      Check if an expression contains a SubLink.
181  */
182 bool
183 checkExprHasSubLink(Node *node)
184 {
185         /*
186          * If a Query is passed, examine it --- but we should not recurse into
187          * sub-Queries that are in its rangetable or CTE list.
188          */
189         return query_or_expression_tree_walker(node,
190                                                                                    checkExprHasSubLink_walker,
191                                                                                    NULL,
192                                                                                    QTW_IGNORE_RC_SUBQUERIES);
193 }
194
195 static bool
196 checkExprHasSubLink_walker(Node *node, void *context)
197 {
198         if (node == NULL)
199                 return false;
200         if (IsA(node, SubLink))
201                 return true;                    /* abort the tree traversal and return true */
202         return expression_tree_walker(node, checkExprHasSubLink_walker, context);
203 }
204
205
206 /*
207  * OffsetVarNodes - adjust Vars when appending one query's RT to another
208  *
209  * Find all Var nodes in the given tree with varlevelsup == sublevels_up,
210  * and increment their varno fields (rangetable indexes) by 'offset'.
211  * The varnoold fields are adjusted similarly.  Also, adjust other nodes
212  * that contain rangetable indexes, such as RangeTblRef and JoinExpr.
213  *
214  * NOTE: although this has the form of a walker, we cheat and modify the
215  * nodes in-place.      The given expression tree should have been copied
216  * earlier to ensure that no unwanted side-effects occur!
217  */
218
219 typedef struct
220 {
221         int                     offset;
222         int                     sublevels_up;
223 } OffsetVarNodes_context;
224
225 static bool
226 OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
227 {
228         if (node == NULL)
229                 return false;
230         if (IsA(node, Var))
231         {
232                 Var                *var = (Var *) node;
233
234                 if (var->varlevelsup == context->sublevels_up)
235                 {
236                         var->varno += context->offset;
237                         var->varnoold += context->offset;
238                 }
239                 return false;
240         }
241         if (IsA(node, CurrentOfExpr))
242         {
243                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
244
245                 if (context->sublevels_up == 0)
246                         cexpr->cvarno += context->offset;
247                 return false;
248         }
249         if (IsA(node, RangeTblRef))
250         {
251                 RangeTblRef *rtr = (RangeTblRef *) node;
252
253                 if (context->sublevels_up == 0)
254                         rtr->rtindex += context->offset;
255                 /* the subquery itself is visited separately */
256                 return false;
257         }
258         if (IsA(node, JoinExpr))
259         {
260                 JoinExpr   *j = (JoinExpr *) node;
261
262                 if (context->sublevels_up == 0)
263                         j->rtindex += context->offset;
264                 /* fall through to examine children */
265         }
266         if (IsA(node, FlattenedSubLink))
267         {
268                 FlattenedSubLink *fslink = (FlattenedSubLink *) node;
269
270                 if (context->sublevels_up == 0)
271                 {
272                         fslink->lefthand = offset_relid_set(fslink->lefthand,
273                                                                                                 context->offset);
274                         fslink->righthand = offset_relid_set(fslink->righthand,
275                                                                                                  context->offset);
276                 }
277                 /* fall through to examine children */
278         }
279         if (IsA(node, PlaceHolderVar))
280         {
281                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
282
283                 if (phv->phlevelsup == context->sublevels_up)
284                 {
285                         phv->phrels = offset_relid_set(phv->phrels,
286                                                                                    context->offset);
287                 }
288                 /* fall through to examine children */
289         }
290         if (IsA(node, AppendRelInfo))
291         {
292                 AppendRelInfo *appinfo = (AppendRelInfo *) node;
293
294                 if (context->sublevels_up == 0)
295                 {
296                         appinfo->parent_relid += context->offset;
297                         appinfo->child_relid += context->offset;
298                 }
299                 /* fall through to examine children */
300         }
301         /* Shouldn't need to handle other planner auxiliary nodes here */
302         Assert(!IsA(node, SpecialJoinInfo));
303         Assert(!IsA(node, PlaceHolderInfo));
304
305         if (IsA(node, Query))
306         {
307                 /* Recurse into subselects */
308                 bool            result;
309
310                 context->sublevels_up++;
311                 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
312                                                                    (void *) context, 0);
313                 context->sublevels_up--;
314                 return result;
315         }
316         return expression_tree_walker(node, OffsetVarNodes_walker,
317                                                                   (void *) context);
318 }
319
320 void
321 OffsetVarNodes(Node *node, int offset, int sublevels_up)
322 {
323         OffsetVarNodes_context context;
324
325         context.offset = offset;
326         context.sublevels_up = sublevels_up;
327
328         /*
329          * Must be prepared to start with a Query or a bare expression tree; if
330          * it's a Query, go straight to query_tree_walker to make sure that
331          * sublevels_up doesn't get incremented prematurely.
332          */
333         if (node && IsA(node, Query))
334         {
335                 Query      *qry = (Query *) node;
336
337                 /*
338                  * If we are starting at a Query, and sublevels_up is zero, then we
339                  * must also fix rangetable indexes in the Query itself --- namely
340                  * resultRelation and rowMarks entries.  sublevels_up cannot be zero
341                  * when recursing into a subquery, so there's no need to have the same
342                  * logic inside OffsetVarNodes_walker.
343                  */
344                 if (sublevels_up == 0)
345                 {
346                         ListCell   *l;
347
348                         if (qry->resultRelation)
349                                 qry->resultRelation += offset;
350                         foreach(l, qry->rowMarks)
351                         {
352                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
353
354                                 rc->rti += offset;
355                         }
356                 }
357                 query_tree_walker(qry, OffsetVarNodes_walker,
358                                                   (void *) &context, 0);
359         }
360         else
361                 OffsetVarNodes_walker(node, &context);
362 }
363
364 static Relids
365 offset_relid_set(Relids relids, int offset)
366 {
367         Relids          result = NULL;
368         Relids          tmprelids;
369         int                     rtindex;
370
371         tmprelids = bms_copy(relids);
372         while ((rtindex = bms_first_member(tmprelids)) >= 0)
373                 result = bms_add_member(result, rtindex + offset);
374         bms_free(tmprelids);
375         return result;
376 }
377
378 /*
379  * ChangeVarNodes - adjust Var nodes for a specific change of RT index
380  *
381  * Find all Var nodes in the given tree belonging to a specific relation
382  * (identified by sublevels_up and rt_index), and change their varno fields
383  * to 'new_index'.      The varnoold fields are changed too.  Also, adjust other
384  * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
385  *
386  * NOTE: although this has the form of a walker, we cheat and modify the
387  * nodes in-place.      The given expression tree should have been copied
388  * earlier to ensure that no unwanted side-effects occur!
389  */
390
391 typedef struct
392 {
393         int                     rt_index;
394         int                     new_index;
395         int                     sublevels_up;
396 } ChangeVarNodes_context;
397
398 static bool
399 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
400 {
401         if (node == NULL)
402                 return false;
403         if (IsA(node, Var))
404         {
405                 Var                *var = (Var *) node;
406
407                 if (var->varlevelsup == context->sublevels_up &&
408                         var->varno == context->rt_index)
409                 {
410                         var->varno = context->new_index;
411                         var->varnoold = context->new_index;
412                 }
413                 return false;
414         }
415         if (IsA(node, CurrentOfExpr))
416         {
417                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
418
419                 if (context->sublevels_up == 0 &&
420                         cexpr->cvarno == context->rt_index)
421                         cexpr->cvarno = context->new_index;
422                 return false;
423         }
424         if (IsA(node, RangeTblRef))
425         {
426                 RangeTblRef *rtr = (RangeTblRef *) node;
427
428                 if (context->sublevels_up == 0 &&
429                         rtr->rtindex == context->rt_index)
430                         rtr->rtindex = context->new_index;
431                 /* the subquery itself is visited separately */
432                 return false;
433         }
434         if (IsA(node, JoinExpr))
435         {
436                 JoinExpr   *j = (JoinExpr *) node;
437
438                 if (context->sublevels_up == 0 &&
439                         j->rtindex == context->rt_index)
440                         j->rtindex = context->new_index;
441                 /* fall through to examine children */
442         }
443         if (IsA(node, FlattenedSubLink))
444         {
445                 FlattenedSubLink *fslink = (FlattenedSubLink *) node;
446
447                 if (context->sublevels_up == 0)
448                 {
449                         fslink->lefthand = adjust_relid_set(fslink->lefthand,
450                                                                                                 context->rt_index,
451                                                                                                 context->new_index);
452                         fslink->righthand = adjust_relid_set(fslink->righthand,
453                                                                                                  context->rt_index,
454                                                                                                  context->new_index);
455                 }
456                 /* fall through to examine children */
457         }
458         if (IsA(node, PlaceHolderVar))
459         {
460                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
461
462                 if (phv->phlevelsup == context->sublevels_up)
463                 {
464                         phv->phrels = adjust_relid_set(phv->phrels,
465                                                                                    context->rt_index,
466                                                                                    context->new_index);
467                 }
468                 /* fall through to examine children */
469         }
470         if (IsA(node, AppendRelInfo))
471         {
472                 AppendRelInfo *appinfo = (AppendRelInfo *) node;
473
474                 if (context->sublevels_up == 0)
475                 {
476                         if (appinfo->parent_relid == context->rt_index)
477                                 appinfo->parent_relid = context->new_index;
478                         if (appinfo->child_relid == context->rt_index)
479                                 appinfo->child_relid = context->new_index;
480                 }
481                 /* fall through to examine children */
482         }
483         /* Shouldn't need to handle other planner auxiliary nodes here */
484         Assert(!IsA(node, SpecialJoinInfo));
485         Assert(!IsA(node, PlaceHolderInfo));
486
487         if (IsA(node, Query))
488         {
489                 /* Recurse into subselects */
490                 bool            result;
491
492                 context->sublevels_up++;
493                 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
494                                                                    (void *) context, 0);
495                 context->sublevels_up--;
496                 return result;
497         }
498         return expression_tree_walker(node, ChangeVarNodes_walker,
499                                                                   (void *) context);
500 }
501
502 void
503 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
504 {
505         ChangeVarNodes_context context;
506
507         context.rt_index = rt_index;
508         context.new_index = new_index;
509         context.sublevels_up = sublevels_up;
510
511         /*
512          * Must be prepared to start with a Query or a bare expression tree; if
513          * it's a Query, go straight to query_tree_walker to make sure that
514          * sublevels_up doesn't get incremented prematurely.
515          */
516         if (node && IsA(node, Query))
517         {
518                 Query      *qry = (Query *) node;
519
520                 /*
521                  * If we are starting at a Query, and sublevels_up is zero, then we
522                  * must also fix rangetable indexes in the Query itself --- namely
523                  * resultRelation and rowMarks entries.  sublevels_up cannot be zero
524                  * when recursing into a subquery, so there's no need to have the same
525                  * logic inside ChangeVarNodes_walker.
526                  */
527                 if (sublevels_up == 0)
528                 {
529                         ListCell   *l;
530
531                         if (qry->resultRelation == rt_index)
532                                 qry->resultRelation = new_index;
533                         foreach(l, qry->rowMarks)
534                         {
535                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
536
537                                 if (rc->rti == rt_index)
538                                         rc->rti = new_index;
539                         }
540                 }
541                 query_tree_walker(qry, ChangeVarNodes_walker,
542                                                   (void *) &context, 0);
543         }
544         else
545                 ChangeVarNodes_walker(node, &context);
546 }
547
548 /*
549  * Substitute newrelid for oldrelid in a Relid set
550  */
551 static Relids
552 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
553 {
554         if (bms_is_member(oldrelid, relids))
555         {
556                 /* Ensure we have a modifiable copy */
557                 relids = bms_copy(relids);
558                 /* Remove old, add new */
559                 relids = bms_del_member(relids, oldrelid);
560                 relids = bms_add_member(relids, newrelid);
561         }
562         return relids;
563 }
564
565 /*
566  * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
567  *
568  * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
569  * and add delta_sublevels_up to their varlevelsup value.  This is needed when
570  * an expression that's correct for some nesting level is inserted into a
571  * subquery.  Ordinarily the initial call has min_sublevels_up == 0 so that
572  * all Vars are affected.  The point of min_sublevels_up is that we can
573  * increment it when we recurse into a sublink, so that local variables in
574  * that sublink are not affected, only outer references to vars that belong
575  * to the expression's original query level or parents thereof.
576  *
577  * Likewise for other nodes containing levelsup fields, such as Aggref.
578  *
579  * NOTE: although this has the form of a walker, we cheat and modify the
580  * Var nodes in-place.  The given expression tree should have been copied
581  * earlier to ensure that no unwanted side-effects occur!
582  */
583
584 typedef struct
585 {
586         int                     delta_sublevels_up;
587         int                     min_sublevels_up;
588 } IncrementVarSublevelsUp_context;
589
590 static bool
591 IncrementVarSublevelsUp_walker(Node *node,
592                                                            IncrementVarSublevelsUp_context *context)
593 {
594         if (node == NULL)
595                 return false;
596         if (IsA(node, Var))
597         {
598                 Var                *var = (Var *) node;
599
600                 if (var->varlevelsup >= context->min_sublevels_up)
601                         var->varlevelsup += context->delta_sublevels_up;
602                 return false;                   /* done here */
603         }
604         if (IsA(node, CurrentOfExpr))
605         {
606                 /* this should not happen */
607                 if (context->min_sublevels_up == 0)
608                         elog(ERROR, "cannot push down CurrentOfExpr");
609                 return false;
610         }
611         if (IsA(node, Aggref))
612         {
613                 Aggref     *agg = (Aggref *) node;
614
615                 if (agg->agglevelsup >= context->min_sublevels_up)
616                         agg->agglevelsup += context->delta_sublevels_up;
617                 /* fall through to recurse into argument */
618         }
619         if (IsA(node, PlaceHolderVar))
620         {
621                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
622
623                 if (phv->phlevelsup >= context->min_sublevels_up)
624                         phv->phlevelsup += context->delta_sublevels_up;
625                 /* fall through to recurse into argument */
626         }
627         if (IsA(node, RangeTblEntry))
628         {
629                 RangeTblEntry *rte = (RangeTblEntry *) node;
630
631                 if (rte->rtekind == RTE_CTE)
632                 {
633                         if (rte->ctelevelsup >= context->min_sublevels_up)
634                                 rte->ctelevelsup += context->delta_sublevels_up;
635                 }
636                 return false;                   /* allow range_table_walker to continue */
637         }
638         if (IsA(node, Query))
639         {
640                 /* Recurse into subselects */
641                 bool            result;
642
643                 context->min_sublevels_up++;
644                 result = query_tree_walker((Query *) node,
645                                                                    IncrementVarSublevelsUp_walker,
646                                                                    (void *) context,
647                                                                    QTW_EXAMINE_RTES);
648                 context->min_sublevels_up--;
649                 return result;
650         }
651         return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
652                                                                   (void *) context);
653 }
654
655 void
656 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
657                                                 int min_sublevels_up)
658 {
659         IncrementVarSublevelsUp_context context;
660
661         context.delta_sublevels_up = delta_sublevels_up;
662         context.min_sublevels_up = min_sublevels_up;
663
664         /*
665          * Must be prepared to start with a Query or a bare expression tree; if
666          * it's a Query, we don't want to increment sublevels_up.
667          */
668         query_or_expression_tree_walker(node,
669                                                                         IncrementVarSublevelsUp_walker,
670                                                                         (void *) &context,
671                                                                         QTW_EXAMINE_RTES);
672 }
673
674 /*
675  * IncrementVarSublevelsUp_rtable -
676  *      Same as IncrementVarSublevelsUp, but to be invoked on a range table.
677  */
678 void
679 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
680                                                            int min_sublevels_up)
681 {
682         IncrementVarSublevelsUp_context context;
683
684         context.delta_sublevels_up = delta_sublevels_up;
685         context.min_sublevels_up = min_sublevels_up;
686
687         range_table_walker(rtable,
688                                            IncrementVarSublevelsUp_walker,
689                                            (void *) &context,
690                                            QTW_EXAMINE_RTES);
691 }
692
693
694 /*
695  * rangeTableEntry_used - detect whether an RTE is referenced somewhere
696  *      in var nodes or join or setOp trees of a query or expression.
697  */
698
699 typedef struct
700 {
701         int                     rt_index;
702         int                     sublevels_up;
703 } rangeTableEntry_used_context;
704
705 static bool
706 rangeTableEntry_used_walker(Node *node,
707                                                         rangeTableEntry_used_context *context)
708 {
709         if (node == NULL)
710                 return false;
711         if (IsA(node, Var))
712         {
713                 Var                *var = (Var *) node;
714
715                 if (var->varlevelsup == context->sublevels_up &&
716                         var->varno == context->rt_index)
717                         return true;
718                 return false;
719         }
720         if (IsA(node, CurrentOfExpr))
721         {
722                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
723
724                 if (context->sublevels_up == 0 &&
725                         cexpr->cvarno == context->rt_index)
726                         return true;
727                 return false;
728         }
729         if (IsA(node, RangeTblRef))
730         {
731                 RangeTblRef *rtr = (RangeTblRef *) node;
732
733                 if (rtr->rtindex == context->rt_index &&
734                         context->sublevels_up == 0)
735                         return true;
736                 /* the subquery itself is visited separately */
737                 return false;
738         }
739         if (IsA(node, JoinExpr))
740         {
741                 JoinExpr   *j = (JoinExpr *) node;
742
743                 if (j->rtindex == context->rt_index &&
744                         context->sublevels_up == 0)
745                         return true;
746                 /* fall through to examine children */
747         }
748         /* Shouldn't need to handle planner auxiliary nodes here */
749         Assert(!IsA(node, FlattenedSubLink));
750         Assert(!IsA(node, PlaceHolderVar));
751         Assert(!IsA(node, SpecialJoinInfo));
752         Assert(!IsA(node, AppendRelInfo));
753         Assert(!IsA(node, PlaceHolderInfo));
754
755         if (IsA(node, Query))
756         {
757                 /* Recurse into subselects */
758                 bool            result;
759
760                 context->sublevels_up++;
761                 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
762                                                                    (void *) context, 0);
763                 context->sublevels_up--;
764                 return result;
765         }
766         return expression_tree_walker(node, rangeTableEntry_used_walker,
767                                                                   (void *) context);
768 }
769
770 bool
771 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
772 {
773         rangeTableEntry_used_context context;
774
775         context.rt_index = rt_index;
776         context.sublevels_up = sublevels_up;
777
778         /*
779          * Must be prepared to start with a Query or a bare expression tree; if
780          * it's a Query, we don't want to increment sublevels_up.
781          */
782         return query_or_expression_tree_walker(node,
783                                                                                    rangeTableEntry_used_walker,
784                                                                                    (void *) &context,
785                                                                                    0);
786 }
787
788
789 /*
790  * attribute_used -
791  *      Check if a specific attribute number of a RTE is used
792  *      somewhere in the query or expression.
793  */
794
795 typedef struct
796 {
797         int                     rt_index;
798         int                     attno;
799         int                     sublevels_up;
800 } attribute_used_context;
801
802 static bool
803 attribute_used_walker(Node *node,
804                                           attribute_used_context *context)
805 {
806         if (node == NULL)
807                 return false;
808         if (IsA(node, Var))
809         {
810                 Var                *var = (Var *) node;
811
812                 if (var->varlevelsup == context->sublevels_up &&
813                         var->varno == context->rt_index &&
814                         var->varattno == context->attno)
815                         return true;
816                 return false;
817         }
818         if (IsA(node, Query))
819         {
820                 /* Recurse into subselects */
821                 bool            result;
822
823                 context->sublevels_up++;
824                 result = query_tree_walker((Query *) node, attribute_used_walker,
825                                                                    (void *) context, 0);
826                 context->sublevels_up--;
827                 return result;
828         }
829         return expression_tree_walker(node, attribute_used_walker,
830                                                                   (void *) context);
831 }
832
833 bool
834 attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
835 {
836         attribute_used_context context;
837
838         context.rt_index = rt_index;
839         context.attno = attno;
840         context.sublevels_up = sublevels_up;
841
842         /*
843          * Must be prepared to start with a Query or a bare expression tree; if
844          * it's a Query, we don't want to increment sublevels_up.
845          */
846         return query_or_expression_tree_walker(node,
847                                                                                    attribute_used_walker,
848                                                                                    (void *) &context,
849                                                                                    0);
850 }
851
852
853 /*
854  * If the given Query is an INSERT ... SELECT construct, extract and
855  * return the sub-Query node that represents the SELECT part.  Otherwise
856  * return the given Query.
857  *
858  * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
859  * of the link to the SELECT subquery inside parsetree, or NULL if not an
860  * INSERT ... SELECT.
861  *
862  * This is a hack needed because transformations on INSERT ... SELECTs that
863  * appear in rule actions should be applied to the source SELECT, not to the
864  * INSERT part.  Perhaps this can be cleaned up with redesigned querytrees.
865  */
866 Query *
867 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
868 {
869         Query      *selectquery;
870         RangeTblEntry *selectrte;
871         RangeTblRef *rtr;
872
873         if (subquery_ptr)
874                 *subquery_ptr = NULL;
875
876         if (parsetree == NULL)
877                 return parsetree;
878         if (parsetree->commandType != CMD_INSERT)
879                 return parsetree;
880
881         /*
882          * Currently, this is ONLY applied to rule-action queries, and so we
883          * expect to find the *OLD* and *NEW* placeholder entries in the given
884          * query.  If they're not there, it must be an INSERT/SELECT in which
885          * they've been pushed down to the SELECT.
886          */
887         if (list_length(parsetree->rtable) >= 2 &&
888                 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
889                            "*OLD*") == 0 &&
890                 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
891                            "*NEW*") == 0)
892                 return parsetree;
893         Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
894         if (list_length(parsetree->jointree->fromlist) != 1)
895                 elog(ERROR, "expected to find SELECT subquery");
896         rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
897         Assert(IsA(rtr, RangeTblRef));
898         selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
899         selectquery = selectrte->subquery;
900         if (!(selectquery && IsA(selectquery, Query) &&
901                   selectquery->commandType == CMD_SELECT))
902                 elog(ERROR, "expected to find SELECT subquery");
903         if (list_length(selectquery->rtable) >= 2 &&
904                 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
905                            "*OLD*") == 0 &&
906                 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
907                            "*NEW*") == 0)
908         {
909                 if (subquery_ptr)
910                         *subquery_ptr = &(selectrte->subquery);
911                 return selectquery;
912         }
913         elog(ERROR, "could not find rule placeholders");
914         return NULL;                            /* not reached */
915 }
916
917
918 /*
919  * Add the given qualifier condition to the query's WHERE clause
920  */
921 void
922 AddQual(Query *parsetree, Node *qual)
923 {
924         Node       *copy;
925
926         if (qual == NULL)
927                 return;
928
929         if (parsetree->commandType == CMD_UTILITY)
930         {
931                 /*
932                  * There's noplace to put the qual on a utility statement.
933                  *
934                  * If it's a NOTIFY, silently ignore the qual; this means that the
935                  * NOTIFY will execute, whether or not there are any qualifying rows.
936                  * While clearly wrong, this is much more useful than refusing to
937                  * execute the rule at all, and extra NOTIFY events are harmless for
938                  * typical uses of NOTIFY.
939                  *
940                  * If it isn't a NOTIFY, error out, since unconditional execution of
941                  * other utility stmts is unlikely to be wanted.  (This case is not
942                  * currently allowed anyway, but keep the test for safety.)
943                  */
944                 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
945                         return;
946                 else
947                         ereport(ERROR,
948                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
949                           errmsg("conditional utility statements are not implemented")));
950         }
951
952         if (parsetree->setOperations != NULL)
953         {
954                 /*
955                  * There's noplace to put the qual on a setop statement, either. (This
956                  * could be fixed, but right now the planner simply ignores any qual
957                  * condition on a setop query.)
958                  */
959                 ereport(ERROR,
960                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
961                                  errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
962         }
963
964         /* INTERSECT want's the original, but we need to copy - Jan */
965         copy = copyObject(qual);
966
967         parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
968                                                                                            copy);
969
970         /*
971          * We had better not have stuck an aggregate into the WHERE clause.
972          */
973         Assert(!checkExprHasAggs(copy));
974
975         /*
976          * Make sure query is marked correctly if added qual has sublinks. Need
977          * not search qual when query is already marked.
978          */
979         if (!parsetree->hasSubLinks)
980                 parsetree->hasSubLinks = checkExprHasSubLink(copy);
981 }
982
983
984 /*
985  * Invert the given clause and add it to the WHERE qualifications of the
986  * given querytree.  Inversion means "x IS NOT TRUE", not just "NOT x",
987  * else we will do the wrong thing when x evaluates to NULL.
988  */
989 void
990 AddInvertedQual(Query *parsetree, Node *qual)
991 {
992         BooleanTest *invqual;
993
994         if (qual == NULL)
995                 return;
996
997         /* Need not copy input qual, because AddQual will... */
998         invqual = makeNode(BooleanTest);
999         invqual->arg = (Expr *) qual;
1000         invqual->booltesttype = IS_NOT_TRUE;
1001
1002         AddQual(parsetree, (Node *) invqual);
1003 }
1004
1005
1006 /*
1007  * ResolveNew - replace Vars with corresponding items from a targetlist
1008  *
1009  * Vars matching target_varno and sublevels_up are replaced by the
1010  * entry with matching resno from targetlist, if there is one.
1011  * If not, we either change the unmatched Var's varno to update_varno
1012  * (when event == CMD_UPDATE) or replace it with a constant NULL.
1013  *
1014  * The caller must also provide target_rte, the RTE describing the target
1015  * relation.  This is needed to handle whole-row Vars referencing the target.
1016  * We expand such Vars into RowExpr constructs.
1017  *
1018  * Note: the business with inserted_sublink is needed to update hasSubLinks
1019  * in subqueries when the replacement adds a subquery inside a subquery.
1020  * Messy, isn't it?  We do not need to do similar pushups for hasAggs,
1021  * because it isn't possible for this transformation to insert a level-zero
1022  * aggregate reference into a subquery --- it could only insert outer aggs.
1023  */
1024
1025 typedef struct
1026 {
1027         int                     target_varno;
1028         int                     sublevels_up;
1029         RangeTblEntry *target_rte;
1030         List       *targetlist;
1031         int                     event;
1032         int                     update_varno;
1033         bool            inserted_sublink;
1034 } ResolveNew_context;
1035
1036 static Node *
1037 resolve_one_var(Var *var, ResolveNew_context *context)
1038 {
1039         TargetEntry *tle;
1040
1041         tle = get_tle_by_resno(context->targetlist, var->varattno);
1042
1043         if (tle == NULL)
1044         {
1045                 /* Failed to find column in insert/update tlist */
1046                 if (context->event == CMD_UPDATE)
1047                 {
1048                         /* For update, just change unmatched var's varno */
1049                         var = (Var *) copyObject(var);
1050                         var->varno = context->update_varno;
1051                         var->varnoold = context->update_varno;
1052                         return (Node *) var;
1053                 }
1054                 else
1055                 {
1056                         /* Otherwise replace unmatched var with a null */
1057                         /* need coerce_to_domain in case of NOT NULL domain constraint */
1058                         return coerce_to_domain((Node *) makeNullConst(var->vartype,
1059                                                                                                                    var->vartypmod),
1060                                                                         InvalidOid, -1,
1061                                                                         var->vartype,
1062                                                                         COERCE_IMPLICIT_CAST,
1063                                                                         -1,
1064                                                                         false,
1065                                                                         false);
1066                 }
1067         }
1068         else
1069         {
1070                 /* Make a copy of the tlist item to return */
1071                 Node       *n = copyObject(tle->expr);
1072
1073                 /* Adjust varlevelsup if tlist item is from higher query */
1074                 if (var->varlevelsup > 0)
1075                         IncrementVarSublevelsUp(n, var->varlevelsup, 0);
1076                 /* Report it if we are adding a sublink to query */
1077                 if (!context->inserted_sublink)
1078                         context->inserted_sublink = checkExprHasSubLink(n);
1079                 return n;
1080         }
1081 }
1082
1083 static Node *
1084 ResolveNew_mutator(Node *node, ResolveNew_context *context)
1085 {
1086         if (node == NULL)
1087                 return NULL;
1088         if (IsA(node, Var))
1089         {
1090                 Var                *var = (Var *) node;
1091                 int                     this_varno = (int) var->varno;
1092                 int                     this_varlevelsup = (int) var->varlevelsup;
1093
1094                 if (this_varno == context->target_varno &&
1095                         this_varlevelsup == context->sublevels_up)
1096                 {
1097                         if (var->varattno == InvalidAttrNumber)
1098                         {
1099                                 /* Must expand whole-tuple reference into RowExpr */
1100                                 RowExpr    *rowexpr;
1101                                 List       *colnames;
1102                                 List       *fields;
1103
1104                                 /*
1105                                  * If generating an expansion for a var of a named rowtype
1106                                  * (ie, this is a plain relation RTE), then we must include
1107                                  * dummy items for dropped columns.  If the var is RECORD (ie,
1108                                  * this is a JOIN), then omit dropped columns.  Either way,
1109                                  * attach column names to the RowExpr for use of ruleutils.c.
1110                                  */
1111                                 expandRTE(context->target_rte,
1112                                                   this_varno, this_varlevelsup, var->location,
1113                                                   (var->vartype != RECORDOID),
1114                                                   &colnames, &fields);
1115                                 /* Adjust the generated per-field Vars... */
1116                                 fields = (List *) ResolveNew_mutator((Node *) fields,
1117                                                                                                          context);
1118                                 rowexpr = makeNode(RowExpr);
1119                                 rowexpr->args = fields;
1120                                 rowexpr->row_typeid = var->vartype;
1121                                 rowexpr->row_format = COERCE_IMPLICIT_CAST;
1122                                 rowexpr->colnames = colnames;
1123                                 rowexpr->location = -1;
1124
1125                                 return (Node *) rowexpr;
1126                         }
1127
1128                         /* Normal case for scalar variable */
1129                         return resolve_one_var(var, context);
1130                 }
1131                 /* otherwise fall through to copy the var normally */
1132         }
1133         else if (IsA(node, CurrentOfExpr))
1134         {
1135                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
1136                 int                     this_varno = (int) cexpr->cvarno;
1137
1138                 if (this_varno == context->target_varno &&
1139                         context->sublevels_up == 0)
1140                 {
1141                         /*
1142                          * We get here if a WHERE CURRENT OF expression turns out to apply
1143                          * to a view.  Someday we might be able to translate the
1144                          * expression to apply to an underlying table of the view, but
1145                          * right now it's not implemented.
1146                          */
1147                         ereport(ERROR,
1148                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1149                                    errmsg("WHERE CURRENT OF on a view is not implemented")));
1150                 }
1151                 /* otherwise fall through to copy the expr normally */
1152         }
1153         else if (IsA(node, Query))
1154         {
1155                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1156                 Query      *newnode;
1157                 bool            save_inserted_sublink;
1158
1159                 context->sublevels_up++;
1160                 save_inserted_sublink = context->inserted_sublink;
1161                 context->inserted_sublink = false;
1162                 newnode = query_tree_mutator((Query *) node,
1163                                                                          ResolveNew_mutator,
1164                                                                          (void *) context,
1165                                                                          0);
1166                 newnode->hasSubLinks |= context->inserted_sublink;
1167                 context->inserted_sublink = save_inserted_sublink;
1168                 context->sublevels_up--;
1169                 return (Node *) newnode;
1170         }
1171         return expression_tree_mutator(node, ResolveNew_mutator,
1172                                                                    (void *) context);
1173 }
1174
1175 Node *
1176 ResolveNew(Node *node, int target_varno, int sublevels_up,
1177                    RangeTblEntry *target_rte,
1178                    List *targetlist, int event, int update_varno)
1179 {
1180         Node       *result;
1181         ResolveNew_context context;
1182
1183         context.target_varno = target_varno;
1184         context.sublevels_up = sublevels_up;
1185         context.target_rte = target_rte;
1186         context.targetlist = targetlist;
1187         context.event = event;
1188         context.update_varno = update_varno;
1189         context.inserted_sublink = false;
1190
1191         /*
1192          * Must be prepared to start with a Query or a bare expression tree; if
1193          * it's a Query, we don't want to increment sublevels_up.
1194          */
1195         result = query_or_expression_tree_mutator(node,
1196                                                                                           ResolveNew_mutator,
1197                                                                                           (void *) &context,
1198                                                                                           0);
1199
1200         if (context.inserted_sublink)
1201         {
1202                 if (IsA(result, Query))
1203                         ((Query *) result)->hasSubLinks = true;
1204
1205                 /*
1206                  * Note: if we're called on a non-Query node then it's the caller's
1207                  * responsibility to update hasSubLinks in the ancestor Query. This is
1208                  * pretty fragile and perhaps should be rethought ...
1209                  */
1210         }
1211
1212         return result;
1213 }