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