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