]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
Add a concept of "placeholder" variables to the planner. These are variables
[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.116 2008/10/21 20:42:53 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         if (IsA(node, PlaceHolderInfo))
302         {
303                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
304
305                 if (context->sublevels_up == 0)
306                 {
307                         phinfo->ph_eval_at = offset_relid_set(phinfo->ph_eval_at,
308                                                                                                   context->offset);
309                         phinfo->ph_needed = offset_relid_set(phinfo->ph_needed,
310                                                                                                  context->offset);
311                 }
312                 /* fall through to examine children */
313         }
314         if (IsA(node, Query))
315         {
316                 /* Recurse into subselects */
317                 bool            result;
318
319                 context->sublevels_up++;
320                 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
321                                                                    (void *) context, 0);
322                 context->sublevels_up--;
323                 return result;
324         }
325         return expression_tree_walker(node, OffsetVarNodes_walker,
326                                                                   (void *) context);
327 }
328
329 void
330 OffsetVarNodes(Node *node, int offset, int sublevels_up)
331 {
332         OffsetVarNodes_context context;
333
334         context.offset = offset;
335         context.sublevels_up = sublevels_up;
336
337         /*
338          * Must be prepared to start with a Query or a bare expression tree; if
339          * it's a Query, go straight to query_tree_walker to make sure that
340          * sublevels_up doesn't get incremented prematurely.
341          */
342         if (node && IsA(node, Query))
343         {
344                 Query      *qry = (Query *) node;
345
346                 /*
347                  * If we are starting at a Query, and sublevels_up is zero, then we
348                  * must also fix rangetable indexes in the Query itself --- namely
349                  * resultRelation and rowMarks entries.  sublevels_up cannot be zero
350                  * when recursing into a subquery, so there's no need to have the same
351                  * logic inside OffsetVarNodes_walker.
352                  */
353                 if (sublevels_up == 0)
354                 {
355                         ListCell   *l;
356
357                         if (qry->resultRelation)
358                                 qry->resultRelation += offset;
359                         foreach(l, qry->rowMarks)
360                         {
361                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
362
363                                 rc->rti += offset;
364                         }
365                 }
366                 query_tree_walker(qry, OffsetVarNodes_walker,
367                                                   (void *) &context, 0);
368         }
369         else
370                 OffsetVarNodes_walker(node, &context);
371 }
372
373 static Relids
374 offset_relid_set(Relids relids, int offset)
375 {
376         Relids          result = NULL;
377         Relids          tmprelids;
378         int                     rtindex;
379
380         tmprelids = bms_copy(relids);
381         while ((rtindex = bms_first_member(tmprelids)) >= 0)
382                 result = bms_add_member(result, rtindex + offset);
383         bms_free(tmprelids);
384         return result;
385 }
386
387 /*
388  * ChangeVarNodes - adjust Var nodes for a specific change of RT index
389  *
390  * Find all Var nodes in the given tree belonging to a specific relation
391  * (identified by sublevels_up and rt_index), and change their varno fields
392  * to 'new_index'.      The varnoold fields are changed too.  Also, adjust other
393  * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
394  *
395  * NOTE: although this has the form of a walker, we cheat and modify the
396  * nodes in-place.      The given expression tree should have been copied
397  * earlier to ensure that no unwanted side-effects occur!
398  */
399
400 typedef struct
401 {
402         int                     rt_index;
403         int                     new_index;
404         int                     sublevels_up;
405 } ChangeVarNodes_context;
406
407 static bool
408 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
409 {
410         if (node == NULL)
411                 return false;
412         if (IsA(node, Var))
413         {
414                 Var                *var = (Var *) node;
415
416                 if (var->varlevelsup == context->sublevels_up &&
417                         var->varno == context->rt_index)
418                 {
419                         var->varno = context->new_index;
420                         var->varnoold = context->new_index;
421                 }
422                 return false;
423         }
424         if (IsA(node, CurrentOfExpr))
425         {
426                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
427
428                 if (context->sublevels_up == 0 &&
429                         cexpr->cvarno == context->rt_index)
430                         cexpr->cvarno = context->new_index;
431                 return false;
432         }
433         if (IsA(node, RangeTblRef))
434         {
435                 RangeTblRef *rtr = (RangeTblRef *) node;
436
437                 if (context->sublevels_up == 0 &&
438                         rtr->rtindex == context->rt_index)
439                         rtr->rtindex = context->new_index;
440                 /* the subquery itself is visited separately */
441                 return false;
442         }
443         if (IsA(node, JoinExpr))
444         {
445                 JoinExpr   *j = (JoinExpr *) node;
446
447                 if (context->sublevels_up == 0 &&
448                         j->rtindex == context->rt_index)
449                         j->rtindex = context->new_index;
450                 /* fall through to examine children */
451         }
452         if (IsA(node, FlattenedSubLink))
453         {
454                 FlattenedSubLink *fslink = (FlattenedSubLink *) node;
455
456                 if (context->sublevels_up == 0)
457                 {
458                         fslink->lefthand = adjust_relid_set(fslink->lefthand,
459                                                                                                 context->rt_index,
460                                                                                                 context->new_index);
461                         fslink->righthand = adjust_relid_set(fslink->righthand,
462                                                                                                  context->rt_index,
463                                                                                                  context->new_index);
464                 }
465                 /* fall through to examine children */
466         }
467         if (IsA(node, PlaceHolderVar))
468         {
469                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
470
471                 if (phv->phlevelsup == context->sublevels_up)
472                 {
473                         phv->phrels = adjust_relid_set(phv->phrels,
474                                                                                    context->rt_index,
475                                                                                    context->new_index);
476                 }
477                 /* fall through to examine children */
478         }
479         if (IsA(node, AppendRelInfo))
480         {
481                 AppendRelInfo *appinfo = (AppendRelInfo *) node;
482
483                 if (context->sublevels_up == 0)
484                 {
485                         if (appinfo->parent_relid == context->rt_index)
486                                 appinfo->parent_relid = context->new_index;
487                         if (appinfo->child_relid == context->rt_index)
488                                 appinfo->child_relid = context->new_index;
489                 }
490                 /* fall through to examine children */
491         }
492         if (IsA(node, PlaceHolderInfo))
493         {
494                 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
495
496                 if (context->sublevels_up == 0)
497                 {
498                         phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
499                                                                                                   context->rt_index,
500                                                                                                   context->new_index);
501                         phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
502                                                                                                  context->rt_index,
503                                                                                                  context->new_index);
504                 }
505                 /* fall through to examine children */
506         }
507         if (IsA(node, Query))
508         {
509                 /* Recurse into subselects */
510                 bool            result;
511
512                 context->sublevels_up++;
513                 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
514                                                                    (void *) context, 0);
515                 context->sublevels_up--;
516                 return result;
517         }
518         return expression_tree_walker(node, ChangeVarNodes_walker,
519                                                                   (void *) context);
520 }
521
522 void
523 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
524 {
525         ChangeVarNodes_context context;
526
527         context.rt_index = rt_index;
528         context.new_index = new_index;
529         context.sublevels_up = sublevels_up;
530
531         /*
532          * Must be prepared to start with a Query or a bare expression tree; if
533          * it's a Query, go straight to query_tree_walker to make sure that
534          * sublevels_up doesn't get incremented prematurely.
535          */
536         if (node && IsA(node, Query))
537         {
538                 Query      *qry = (Query *) node;
539
540                 /*
541                  * If we are starting at a Query, and sublevels_up is zero, then we
542                  * must also fix rangetable indexes in the Query itself --- namely
543                  * resultRelation and rowMarks entries.  sublevels_up cannot be zero
544                  * when recursing into a subquery, so there's no need to have the same
545                  * logic inside ChangeVarNodes_walker.
546                  */
547                 if (sublevels_up == 0)
548                 {
549                         ListCell   *l;
550
551                         if (qry->resultRelation == rt_index)
552                                 qry->resultRelation = new_index;
553                         foreach(l, qry->rowMarks)
554                         {
555                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
556
557                                 if (rc->rti == rt_index)
558                                         rc->rti = new_index;
559                         }
560                 }
561                 query_tree_walker(qry, ChangeVarNodes_walker,
562                                                   (void *) &context, 0);
563         }
564         else
565                 ChangeVarNodes_walker(node, &context);
566 }
567
568 /*
569  * Substitute newrelid for oldrelid in a Relid set
570  */
571 static Relids
572 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
573 {
574         if (bms_is_member(oldrelid, relids))
575         {
576                 /* Ensure we have a modifiable copy */
577                 relids = bms_copy(relids);
578                 /* Remove old, add new */
579                 relids = bms_del_member(relids, oldrelid);
580                 relids = bms_add_member(relids, newrelid);
581         }
582         return relids;
583 }
584
585 /*
586  * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
587  *
588  * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
589  * and add delta_sublevels_up to their varlevelsup value.  This is needed when
590  * an expression that's correct for some nesting level is inserted into a
591  * subquery.  Ordinarily the initial call has min_sublevels_up == 0 so that
592  * all Vars are affected.  The point of min_sublevels_up is that we can
593  * increment it when we recurse into a sublink, so that local variables in
594  * that sublink are not affected, only outer references to vars that belong
595  * to the expression's original query level or parents thereof.
596  *
597  * Likewise for other nodes containing levelsup fields, such as Aggref.
598  *
599  * NOTE: although this has the form of a walker, we cheat and modify the
600  * Var nodes in-place.  The given expression tree should have been copied
601  * earlier to ensure that no unwanted side-effects occur!
602  */
603
604 typedef struct
605 {
606         int                     delta_sublevels_up;
607         int                     min_sublevels_up;
608 } IncrementVarSublevelsUp_context;
609
610 static bool
611 IncrementVarSublevelsUp_walker(Node *node,
612                                                            IncrementVarSublevelsUp_context *context)
613 {
614         if (node == NULL)
615                 return false;
616         if (IsA(node, Var))
617         {
618                 Var                *var = (Var *) node;
619
620                 if (var->varlevelsup >= context->min_sublevels_up)
621                         var->varlevelsup += context->delta_sublevels_up;
622                 return false;                   /* done here */
623         }
624         if (IsA(node, CurrentOfExpr))
625         {
626                 /* this should not happen */
627                 if (context->min_sublevels_up == 0)
628                         elog(ERROR, "cannot push down CurrentOfExpr");
629                 return false;
630         }
631         if (IsA(node, Aggref))
632         {
633                 Aggref     *agg = (Aggref *) node;
634
635                 if (agg->agglevelsup >= context->min_sublevels_up)
636                         agg->agglevelsup += context->delta_sublevels_up;
637                 /* fall through to recurse into argument */
638         }
639         if (IsA(node, PlaceHolderVar))
640         {
641                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
642
643                 if (phv->phlevelsup >= context->min_sublevels_up)
644                         phv->phlevelsup += context->delta_sublevels_up;
645                 /* fall through to recurse into argument */
646         }
647         if (IsA(node, RangeTblEntry))
648         {
649                 RangeTblEntry *rte = (RangeTblEntry *) node;
650
651                 if (rte->rtekind == RTE_CTE)
652                 {
653                         if (rte->ctelevelsup >= context->min_sublevels_up)
654                                 rte->ctelevelsup += context->delta_sublevels_up;
655                 }
656                 return false;                   /* allow range_table_walker to continue */
657         }
658         if (IsA(node, Query))
659         {
660                 /* Recurse into subselects */
661                 bool            result;
662
663                 context->min_sublevels_up++;
664                 result = query_tree_walker((Query *) node,
665                                                                    IncrementVarSublevelsUp_walker,
666                                                                    (void *) context,
667                                                                    QTW_EXAMINE_RTES);
668                 context->min_sublevels_up--;
669                 return result;
670         }
671         return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
672                                                                   (void *) context);
673 }
674
675 void
676 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
677                                                 int min_sublevels_up)
678 {
679         IncrementVarSublevelsUp_context context;
680
681         context.delta_sublevels_up = delta_sublevels_up;
682         context.min_sublevels_up = min_sublevels_up;
683
684         /*
685          * Must be prepared to start with a Query or a bare expression tree; if
686          * it's a Query, we don't want to increment sublevels_up.
687          */
688         query_or_expression_tree_walker(node,
689                                                                         IncrementVarSublevelsUp_walker,
690                                                                         (void *) &context,
691                                                                         QTW_EXAMINE_RTES);
692 }
693
694 /*
695  * IncrementVarSublevelsUp_rtable -
696  *      Same as IncrementVarSublevelsUp, but to be invoked on a range table.
697  */
698 void
699 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
700                                                            int min_sublevels_up)
701 {
702         IncrementVarSublevelsUp_context context;
703
704         context.delta_sublevels_up = delta_sublevels_up;
705         context.min_sublevels_up = min_sublevels_up;
706
707         range_table_walker(rtable,
708                                            IncrementVarSublevelsUp_walker,
709                                            (void *) &context,
710                                            QTW_EXAMINE_RTES);
711 }
712
713
714 /*
715  * rangeTableEntry_used - detect whether an RTE is referenced somewhere
716  *      in var nodes or join or setOp trees of a query or expression.
717  */
718
719 typedef struct
720 {
721         int                     rt_index;
722         int                     sublevels_up;
723 } rangeTableEntry_used_context;
724
725 static bool
726 rangeTableEntry_used_walker(Node *node,
727                                                         rangeTableEntry_used_context *context)
728 {
729         if (node == NULL)
730                 return false;
731         if (IsA(node, Var))
732         {
733                 Var                *var = (Var *) node;
734
735                 if (var->varlevelsup == context->sublevels_up &&
736                         var->varno == context->rt_index)
737                         return true;
738                 return false;
739         }
740         if (IsA(node, CurrentOfExpr))
741         {
742                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
743
744                 if (context->sublevels_up == 0 &&
745                         cexpr->cvarno == context->rt_index)
746                         return true;
747                 return false;
748         }
749         if (IsA(node, RangeTblRef))
750         {
751                 RangeTblRef *rtr = (RangeTblRef *) node;
752
753                 if (rtr->rtindex == context->rt_index &&
754                         context->sublevels_up == 0)
755                         return true;
756                 /* the subquery itself is visited separately */
757                 return false;
758         }
759         if (IsA(node, JoinExpr))
760         {
761                 JoinExpr   *j = (JoinExpr *) node;
762
763                 if (j->rtindex == context->rt_index &&
764                         context->sublevels_up == 0)
765                         return true;
766                 /* fall through to examine children */
767         }
768         /* Shouldn't need to handle planner auxiliary nodes here */
769         Assert(!IsA(node, FlattenedSubLink));
770         Assert(!IsA(node, PlaceHolderVar));
771         Assert(!IsA(node, SpecialJoinInfo));
772         Assert(!IsA(node, AppendRelInfo));
773         Assert(!IsA(node, PlaceHolderInfo));
774
775         if (IsA(node, Query))
776         {
777                 /* Recurse into subselects */
778                 bool            result;
779
780                 context->sublevels_up++;
781                 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
782                                                                    (void *) context, 0);
783                 context->sublevels_up--;
784                 return result;
785         }
786         return expression_tree_walker(node, rangeTableEntry_used_walker,
787                                                                   (void *) context);
788 }
789
790 bool
791 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
792 {
793         rangeTableEntry_used_context context;
794
795         context.rt_index = rt_index;
796         context.sublevels_up = sublevels_up;
797
798         /*
799          * Must be prepared to start with a Query or a bare expression tree; if
800          * it's a Query, we don't want to increment sublevels_up.
801          */
802         return query_or_expression_tree_walker(node,
803                                                                                    rangeTableEntry_used_walker,
804                                                                                    (void *) &context,
805                                                                                    0);
806 }
807
808
809 /*
810  * attribute_used -
811  *      Check if a specific attribute number of a RTE is used
812  *      somewhere in the query or expression.
813  */
814
815 typedef struct
816 {
817         int                     rt_index;
818         int                     attno;
819         int                     sublevels_up;
820 } attribute_used_context;
821
822 static bool
823 attribute_used_walker(Node *node,
824                                           attribute_used_context *context)
825 {
826         if (node == NULL)
827                 return false;
828         if (IsA(node, Var))
829         {
830                 Var                *var = (Var *) node;
831
832                 if (var->varlevelsup == context->sublevels_up &&
833                         var->varno == context->rt_index &&
834                         var->varattno == context->attno)
835                         return true;
836                 return false;
837         }
838         if (IsA(node, Query))
839         {
840                 /* Recurse into subselects */
841                 bool            result;
842
843                 context->sublevels_up++;
844                 result = query_tree_walker((Query *) node, attribute_used_walker,
845                                                                    (void *) context, 0);
846                 context->sublevels_up--;
847                 return result;
848         }
849         return expression_tree_walker(node, attribute_used_walker,
850                                                                   (void *) context);
851 }
852
853 bool
854 attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
855 {
856         attribute_used_context context;
857
858         context.rt_index = rt_index;
859         context.attno = attno;
860         context.sublevels_up = sublevels_up;
861
862         /*
863          * Must be prepared to start with a Query or a bare expression tree; if
864          * it's a Query, we don't want to increment sublevels_up.
865          */
866         return query_or_expression_tree_walker(node,
867                                                                                    attribute_used_walker,
868                                                                                    (void *) &context,
869                                                                                    0);
870 }
871
872
873 /*
874  * If the given Query is an INSERT ... SELECT construct, extract and
875  * return the sub-Query node that represents the SELECT part.  Otherwise
876  * return the given Query.
877  *
878  * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
879  * of the link to the SELECT subquery inside parsetree, or NULL if not an
880  * INSERT ... SELECT.
881  *
882  * This is a hack needed because transformations on INSERT ... SELECTs that
883  * appear in rule actions should be applied to the source SELECT, not to the
884  * INSERT part.  Perhaps this can be cleaned up with redesigned querytrees.
885  */
886 Query *
887 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
888 {
889         Query      *selectquery;
890         RangeTblEntry *selectrte;
891         RangeTblRef *rtr;
892
893         if (subquery_ptr)
894                 *subquery_ptr = NULL;
895
896         if (parsetree == NULL)
897                 return parsetree;
898         if (parsetree->commandType != CMD_INSERT)
899                 return parsetree;
900
901         /*
902          * Currently, this is ONLY applied to rule-action queries, and so we
903          * expect to find the *OLD* and *NEW* placeholder entries in the given
904          * query.  If they're not there, it must be an INSERT/SELECT in which
905          * they've been pushed down to the SELECT.
906          */
907         if (list_length(parsetree->rtable) >= 2 &&
908                 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
909                            "*OLD*") == 0 &&
910                 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
911                            "*NEW*") == 0)
912                 return parsetree;
913         Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
914         if (list_length(parsetree->jointree->fromlist) != 1)
915                 elog(ERROR, "expected to find SELECT subquery");
916         rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
917         Assert(IsA(rtr, RangeTblRef));
918         selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
919         selectquery = selectrte->subquery;
920         if (!(selectquery && IsA(selectquery, Query) &&
921                   selectquery->commandType == CMD_SELECT))
922                 elog(ERROR, "expected to find SELECT subquery");
923         if (list_length(selectquery->rtable) >= 2 &&
924                 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
925                            "*OLD*") == 0 &&
926                 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
927                            "*NEW*") == 0)
928         {
929                 if (subquery_ptr)
930                         *subquery_ptr = &(selectrte->subquery);
931                 return selectquery;
932         }
933         elog(ERROR, "could not find rule placeholders");
934         return NULL;                            /* not reached */
935 }
936
937
938 /*
939  * Add the given qualifier condition to the query's WHERE clause
940  */
941 void
942 AddQual(Query *parsetree, Node *qual)
943 {
944         Node       *copy;
945
946         if (qual == NULL)
947                 return;
948
949         if (parsetree->commandType == CMD_UTILITY)
950         {
951                 /*
952                  * There's noplace to put the qual on a utility statement.
953                  *
954                  * If it's a NOTIFY, silently ignore the qual; this means that the
955                  * NOTIFY will execute, whether or not there are any qualifying rows.
956                  * While clearly wrong, this is much more useful than refusing to
957                  * execute the rule at all, and extra NOTIFY events are harmless for
958                  * typical uses of NOTIFY.
959                  *
960                  * If it isn't a NOTIFY, error out, since unconditional execution of
961                  * other utility stmts is unlikely to be wanted.  (This case is not
962                  * currently allowed anyway, but keep the test for safety.)
963                  */
964                 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
965                         return;
966                 else
967                         ereport(ERROR,
968                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
969                           errmsg("conditional utility statements are not implemented")));
970         }
971
972         if (parsetree->setOperations != NULL)
973         {
974                 /*
975                  * There's noplace to put the qual on a setop statement, either. (This
976                  * could be fixed, but right now the planner simply ignores any qual
977                  * condition on a setop query.)
978                  */
979                 ereport(ERROR,
980                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
981                                  errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
982         }
983
984         /* INTERSECT want's the original, but we need to copy - Jan */
985         copy = copyObject(qual);
986
987         parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
988                                                                                            copy);
989
990         /*
991          * We had better not have stuck an aggregate into the WHERE clause.
992          */
993         Assert(!checkExprHasAggs(copy));
994
995         /*
996          * Make sure query is marked correctly if added qual has sublinks. Need
997          * not search qual when query is already marked.
998          */
999         if (!parsetree->hasSubLinks)
1000                 parsetree->hasSubLinks = checkExprHasSubLink(copy);
1001 }
1002
1003
1004 /*
1005  * Invert the given clause and add it to the WHERE qualifications of the
1006  * given querytree.  Inversion means "x IS NOT TRUE", not just "NOT x",
1007  * else we will do the wrong thing when x evaluates to NULL.
1008  */
1009 void
1010 AddInvertedQual(Query *parsetree, Node *qual)
1011 {
1012         BooleanTest *invqual;
1013
1014         if (qual == NULL)
1015                 return;
1016
1017         /* Need not copy input qual, because AddQual will... */
1018         invqual = makeNode(BooleanTest);
1019         invqual->arg = (Expr *) qual;
1020         invqual->booltesttype = IS_NOT_TRUE;
1021
1022         AddQual(parsetree, (Node *) invqual);
1023 }
1024
1025
1026 /*
1027  * ResolveNew - replace Vars with corresponding items from a targetlist
1028  *
1029  * Vars matching target_varno and sublevels_up are replaced by the
1030  * entry with matching resno from targetlist, if there is one.
1031  * If not, we either change the unmatched Var's varno to update_varno
1032  * (when event == CMD_UPDATE) or replace it with a constant NULL.
1033  *
1034  * The caller must also provide target_rte, the RTE describing the target
1035  * relation.  This is needed to handle whole-row Vars referencing the target.
1036  * We expand such Vars into RowExpr constructs.
1037  *
1038  * Note: the business with inserted_sublink is needed to update hasSubLinks
1039  * in subqueries when the replacement adds a subquery inside a subquery.
1040  * Messy, isn't it?  We do not need to do similar pushups for hasAggs,
1041  * because it isn't possible for this transformation to insert a level-zero
1042  * aggregate reference into a subquery --- it could only insert outer aggs.
1043  */
1044
1045 typedef struct
1046 {
1047         int                     target_varno;
1048         int                     sublevels_up;
1049         RangeTblEntry *target_rte;
1050         List       *targetlist;
1051         int                     event;
1052         int                     update_varno;
1053         bool            inserted_sublink;
1054 } ResolveNew_context;
1055
1056 static Node *
1057 resolve_one_var(Var *var, ResolveNew_context *context)
1058 {
1059         TargetEntry *tle;
1060
1061         tle = get_tle_by_resno(context->targetlist, var->varattno);
1062
1063         if (tle == NULL)
1064         {
1065                 /* Failed to find column in insert/update tlist */
1066                 if (context->event == CMD_UPDATE)
1067                 {
1068                         /* For update, just change unmatched var's varno */
1069                         var = (Var *) copyObject(var);
1070                         var->varno = context->update_varno;
1071                         var->varnoold = context->update_varno;
1072                         return (Node *) var;
1073                 }
1074                 else
1075                 {
1076                         /* Otherwise replace unmatched var with a null */
1077                         /* need coerce_to_domain in case of NOT NULL domain constraint */
1078                         return coerce_to_domain((Node *) makeNullConst(var->vartype,
1079                                                                                                                    var->vartypmod),
1080                                                                         InvalidOid, -1,
1081                                                                         var->vartype,
1082                                                                         COERCE_IMPLICIT_CAST,
1083                                                                         -1,
1084                                                                         false,
1085                                                                         false);
1086                 }
1087         }
1088         else
1089         {
1090                 /* Make a copy of the tlist item to return */
1091                 Node       *n = copyObject(tle->expr);
1092
1093                 /* Adjust varlevelsup if tlist item is from higher query */
1094                 if (var->varlevelsup > 0)
1095                         IncrementVarSublevelsUp(n, var->varlevelsup, 0);
1096                 /* Report it if we are adding a sublink to query */
1097                 if (!context->inserted_sublink)
1098                         context->inserted_sublink = checkExprHasSubLink(n);
1099                 return n;
1100         }
1101 }
1102
1103 static Node *
1104 ResolveNew_mutator(Node *node, ResolveNew_context *context)
1105 {
1106         if (node == NULL)
1107                 return NULL;
1108         if (IsA(node, Var))
1109         {
1110                 Var                *var = (Var *) node;
1111                 int                     this_varno = (int) var->varno;
1112                 int                     this_varlevelsup = (int) var->varlevelsup;
1113
1114                 if (this_varno == context->target_varno &&
1115                         this_varlevelsup == context->sublevels_up)
1116                 {
1117                         if (var->varattno == InvalidAttrNumber)
1118                         {
1119                                 /* Must expand whole-tuple reference into RowExpr */
1120                                 RowExpr    *rowexpr;
1121                                 List       *colnames;
1122                                 List       *fields;
1123
1124                                 /*
1125                                  * If generating an expansion for a var of a named rowtype
1126                                  * (ie, this is a plain relation RTE), then we must include
1127                                  * dummy items for dropped columns.  If the var is RECORD (ie,
1128                                  * this is a JOIN), then omit dropped columns.  Either way,
1129                                  * attach column names to the RowExpr for use of ruleutils.c.
1130                                  */
1131                                 expandRTE(context->target_rte,
1132                                                   this_varno, this_varlevelsup, var->location,
1133                                                   (var->vartype != RECORDOID),
1134                                                   &colnames, &fields);
1135                                 /* Adjust the generated per-field Vars... */
1136                                 fields = (List *) ResolveNew_mutator((Node *) fields,
1137                                                                                                          context);
1138                                 rowexpr = makeNode(RowExpr);
1139                                 rowexpr->args = fields;
1140                                 rowexpr->row_typeid = var->vartype;
1141                                 rowexpr->row_format = COERCE_IMPLICIT_CAST;
1142                                 rowexpr->colnames = colnames;
1143                                 rowexpr->location = -1;
1144
1145                                 return (Node *) rowexpr;
1146                         }
1147
1148                         /* Normal case for scalar variable */
1149                         return resolve_one_var(var, context);
1150                 }
1151                 /* otherwise fall through to copy the var normally */
1152         }
1153         else if (IsA(node, CurrentOfExpr))
1154         {
1155                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
1156                 int                     this_varno = (int) cexpr->cvarno;
1157
1158                 if (this_varno == context->target_varno &&
1159                         context->sublevels_up == 0)
1160                 {
1161                         /*
1162                          * We get here if a WHERE CURRENT OF expression turns out to apply
1163                          * to a view.  Someday we might be able to translate the
1164                          * expression to apply to an underlying table of the view, but
1165                          * right now it's not implemented.
1166                          */
1167                         ereport(ERROR,
1168                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1169                                    errmsg("WHERE CURRENT OF on a view is not implemented")));
1170                 }
1171                 /* otherwise fall through to copy the expr normally */
1172         }
1173         else if (IsA(node, Query))
1174         {
1175                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1176                 Query      *newnode;
1177                 bool            save_inserted_sublink;
1178
1179                 context->sublevels_up++;
1180                 save_inserted_sublink = context->inserted_sublink;
1181                 context->inserted_sublink = false;
1182                 newnode = query_tree_mutator((Query *) node,
1183                                                                          ResolveNew_mutator,
1184                                                                          (void *) context,
1185                                                                          0);
1186                 newnode->hasSubLinks |= context->inserted_sublink;
1187                 context->inserted_sublink = save_inserted_sublink;
1188                 context->sublevels_up--;
1189                 return (Node *) newnode;
1190         }
1191         return expression_tree_mutator(node, ResolveNew_mutator,
1192                                                                    (void *) context);
1193 }
1194
1195 Node *
1196 ResolveNew(Node *node, int target_varno, int sublevels_up,
1197                    RangeTblEntry *target_rte,
1198                    List *targetlist, int event, int update_varno)
1199 {
1200         Node       *result;
1201         ResolveNew_context context;
1202
1203         context.target_varno = target_varno;
1204         context.sublevels_up = sublevels_up;
1205         context.target_rte = target_rte;
1206         context.targetlist = targetlist;
1207         context.event = event;
1208         context.update_varno = update_varno;
1209         context.inserted_sublink = false;
1210
1211         /*
1212          * Must be prepared to start with a Query or a bare expression tree; if
1213          * it's a Query, we don't want to increment sublevels_up.
1214          */
1215         result = query_or_expression_tree_mutator(node,
1216                                                                                           ResolveNew_mutator,
1217                                                                                           (void *) &context,
1218                                                                                           0);
1219
1220         if (context.inserted_sublink)
1221         {
1222                 if (IsA(result, Query))
1223                         ((Query *) result)->hasSubLinks = true;
1224
1225                 /*
1226                  * Note: if we're called on a non-Query node then it's the caller's
1227                  * responsibility to update hasSubLinks in the ancestor Query. This is
1228                  * pretty fragile and perhaps should be rethought ...
1229                  */
1230         }
1231
1232         return result;
1233 }