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