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