]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteManip.c
Refactor planner's header files.
[postgresql] / src / backend / rewrite / rewriteManip.c
1 /*-------------------------------------------------------------------------
2  *
3  * rewriteManip.c
4  *
5  * Portions Copyright (c) 1996-2019, 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 "nodes/relation.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, PlaceHolderInfo));
406         Assert(!IsA(node, MinMaxAggInfo));
407
408         if (IsA(node, Query))
409         {
410                 /* Recurse into subselects */
411                 bool            result;
412
413                 context->sublevels_up++;
414                 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
415                                                                    (void *) context, 0);
416                 context->sublevels_up--;
417                 return result;
418         }
419         return expression_tree_walker(node, OffsetVarNodes_walker,
420                                                                   (void *) context);
421 }
422
423 void
424 OffsetVarNodes(Node *node, int offset, int sublevels_up)
425 {
426         OffsetVarNodes_context context;
427
428         context.offset = offset;
429         context.sublevels_up = sublevels_up;
430
431         /*
432          * Must be prepared to start with a Query or a bare expression tree; if
433          * it's a Query, go straight to query_tree_walker to make sure that
434          * sublevels_up doesn't get incremented prematurely.
435          */
436         if (node && IsA(node, Query))
437         {
438                 Query      *qry = (Query *) node;
439
440                 /*
441                  * If we are starting at a Query, and sublevels_up is zero, then we
442                  * must also fix rangetable indexes in the Query itself --- namely
443                  * resultRelation, exclRelIndex and rowMarks entries.  sublevels_up
444                  * cannot be zero when recursing into a subquery, so there's no need
445                  * to have the same logic inside OffsetVarNodes_walker.
446                  */
447                 if (sublevels_up == 0)
448                 {
449                         ListCell   *l;
450
451                         if (qry->resultRelation)
452                                 qry->resultRelation += offset;
453
454                         if (qry->onConflict && qry->onConflict->exclRelIndex)
455                                 qry->onConflict->exclRelIndex += offset;
456
457                         foreach(l, qry->rowMarks)
458                         {
459                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
460
461                                 rc->rti += offset;
462                         }
463                 }
464                 query_tree_walker(qry, OffsetVarNodes_walker,
465                                                   (void *) &context, 0);
466         }
467         else
468                 OffsetVarNodes_walker(node, &context);
469 }
470
471 static Relids
472 offset_relid_set(Relids relids, int offset)
473 {
474         Relids          result = NULL;
475         int                     rtindex;
476
477         rtindex = -1;
478         while ((rtindex = bms_next_member(relids, rtindex)) >= 0)
479                 result = bms_add_member(result, rtindex + offset);
480         return result;
481 }
482
483 /*
484  * ChangeVarNodes - adjust Var nodes for a specific change of RT index
485  *
486  * Find all Var nodes in the given tree belonging to a specific relation
487  * (identified by sublevels_up and rt_index), and change their varno fields
488  * to 'new_index'.  The varnoold fields are changed too.  Also, adjust other
489  * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
490  *
491  * NOTE: although this has the form of a walker, we cheat and modify the
492  * nodes in-place.  The given expression tree should have been copied
493  * earlier to ensure that no unwanted side-effects occur!
494  */
495
496 typedef struct
497 {
498         int                     rt_index;
499         int                     new_index;
500         int                     sublevels_up;
501 } ChangeVarNodes_context;
502
503 static bool
504 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
505 {
506         if (node == NULL)
507                 return false;
508         if (IsA(node, Var))
509         {
510                 Var                *var = (Var *) node;
511
512                 if (var->varlevelsup == context->sublevels_up &&
513                         var->varno == context->rt_index)
514                 {
515                         var->varno = context->new_index;
516                         var->varnoold = context->new_index;
517                 }
518                 return false;
519         }
520         if (IsA(node, CurrentOfExpr))
521         {
522                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
523
524                 if (context->sublevels_up == 0 &&
525                         cexpr->cvarno == context->rt_index)
526                         cexpr->cvarno = context->new_index;
527                 return false;
528         }
529         if (IsA(node, RangeTblRef))
530         {
531                 RangeTblRef *rtr = (RangeTblRef *) node;
532
533                 if (context->sublevels_up == 0 &&
534                         rtr->rtindex == context->rt_index)
535                         rtr->rtindex = context->new_index;
536                 /* the subquery itself is visited separately */
537                 return false;
538         }
539         if (IsA(node, JoinExpr))
540         {
541                 JoinExpr   *j = (JoinExpr *) node;
542
543                 if (context->sublevels_up == 0 &&
544                         j->rtindex == context->rt_index)
545                         j->rtindex = context->new_index;
546                 /* fall through to examine children */
547         }
548         if (IsA(node, PlaceHolderVar))
549         {
550                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
551
552                 if (phv->phlevelsup == context->sublevels_up)
553                 {
554                         phv->phrels = adjust_relid_set(phv->phrels,
555                                                                                    context->rt_index,
556                                                                                    context->new_index);
557                 }
558                 /* fall through to examine children */
559         }
560         if (IsA(node, PlanRowMark))
561         {
562                 PlanRowMark *rowmark = (PlanRowMark *) node;
563
564                 if (context->sublevels_up == 0)
565                 {
566                         if (rowmark->rti == context->rt_index)
567                                 rowmark->rti = context->new_index;
568                         if (rowmark->prti == context->rt_index)
569                                 rowmark->prti = context->new_index;
570                 }
571                 return false;
572         }
573         if (IsA(node, AppendRelInfo))
574         {
575                 AppendRelInfo *appinfo = (AppendRelInfo *) node;
576
577                 if (context->sublevels_up == 0)
578                 {
579                         if (appinfo->parent_relid == context->rt_index)
580                                 appinfo->parent_relid = context->new_index;
581                         if (appinfo->child_relid == context->rt_index)
582                                 appinfo->child_relid = context->new_index;
583                 }
584                 /* fall through to examine children */
585         }
586         /* Shouldn't need to handle other planner auxiliary nodes here */
587         Assert(!IsA(node, SpecialJoinInfo));
588         Assert(!IsA(node, PlaceHolderInfo));
589         Assert(!IsA(node, MinMaxAggInfo));
590
591         if (IsA(node, Query))
592         {
593                 /* Recurse into subselects */
594                 bool            result;
595
596                 context->sublevels_up++;
597                 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
598                                                                    (void *) context, 0);
599                 context->sublevels_up--;
600                 return result;
601         }
602         return expression_tree_walker(node, ChangeVarNodes_walker,
603                                                                   (void *) context);
604 }
605
606 void
607 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
608 {
609         ChangeVarNodes_context context;
610
611         context.rt_index = rt_index;
612         context.new_index = new_index;
613         context.sublevels_up = sublevels_up;
614
615         /*
616          * Must be prepared to start with a Query or a bare expression tree; if
617          * it's a Query, go straight to query_tree_walker to make sure that
618          * sublevels_up doesn't get incremented prematurely.
619          */
620         if (node && IsA(node, Query))
621         {
622                 Query      *qry = (Query *) node;
623
624                 /*
625                  * If we are starting at a Query, and sublevels_up is zero, then we
626                  * must also fix rangetable indexes in the Query itself --- namely
627                  * resultRelation and rowMarks entries.  sublevels_up cannot be zero
628                  * when recursing into a subquery, so there's no need to have the same
629                  * logic inside ChangeVarNodes_walker.
630                  */
631                 if (sublevels_up == 0)
632                 {
633                         ListCell   *l;
634
635                         if (qry->resultRelation == rt_index)
636                                 qry->resultRelation = new_index;
637
638                         /* this is unlikely to ever be used, but ... */
639                         if (qry->onConflict && qry->onConflict->exclRelIndex == rt_index)
640                                 qry->onConflict->exclRelIndex = new_index;
641
642                         foreach(l, qry->rowMarks)
643                         {
644                                 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
645
646                                 if (rc->rti == rt_index)
647                                         rc->rti = new_index;
648                         }
649                 }
650                 query_tree_walker(qry, ChangeVarNodes_walker,
651                                                   (void *) &context, 0);
652         }
653         else
654                 ChangeVarNodes_walker(node, &context);
655 }
656
657 /*
658  * Substitute newrelid for oldrelid in a Relid set
659  */
660 static Relids
661 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
662 {
663         if (bms_is_member(oldrelid, relids))
664         {
665                 /* Ensure we have a modifiable copy */
666                 relids = bms_copy(relids);
667                 /* Remove old, add new */
668                 relids = bms_del_member(relids, oldrelid);
669                 relids = bms_add_member(relids, newrelid);
670         }
671         return relids;
672 }
673
674 /*
675  * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
676  *
677  * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
678  * and add delta_sublevels_up to their varlevelsup value.  This is needed when
679  * an expression that's correct for some nesting level is inserted into a
680  * subquery.  Ordinarily the initial call has min_sublevels_up == 0 so that
681  * all Vars are affected.  The point of min_sublevels_up is that we can
682  * increment it when we recurse into a sublink, so that local variables in
683  * that sublink are not affected, only outer references to vars that belong
684  * to the expression's original query level or parents thereof.
685  *
686  * Likewise for other nodes containing levelsup fields, such as Aggref.
687  *
688  * NOTE: although this has the form of a walker, we cheat and modify the
689  * Var nodes in-place.  The given expression tree should have been copied
690  * earlier to ensure that no unwanted side-effects occur!
691  */
692
693 typedef struct
694 {
695         int                     delta_sublevels_up;
696         int                     min_sublevels_up;
697 } IncrementVarSublevelsUp_context;
698
699 static bool
700 IncrementVarSublevelsUp_walker(Node *node,
701                                                            IncrementVarSublevelsUp_context *context)
702 {
703         if (node == NULL)
704                 return false;
705         if (IsA(node, Var))
706         {
707                 Var                *var = (Var *) node;
708
709                 if (var->varlevelsup >= context->min_sublevels_up)
710                         var->varlevelsup += context->delta_sublevels_up;
711                 return false;                   /* done here */
712         }
713         if (IsA(node, CurrentOfExpr))
714         {
715                 /* this should not happen */
716                 if (context->min_sublevels_up == 0)
717                         elog(ERROR, "cannot push down CurrentOfExpr");
718                 return false;
719         }
720         if (IsA(node, Aggref))
721         {
722                 Aggref     *agg = (Aggref *) node;
723
724                 if (agg->agglevelsup >= context->min_sublevels_up)
725                         agg->agglevelsup += context->delta_sublevels_up;
726                 /* fall through to recurse into argument */
727         }
728         if (IsA(node, GroupingFunc))
729         {
730                 GroupingFunc *grp = (GroupingFunc *) node;
731
732                 if (grp->agglevelsup >= context->min_sublevels_up)
733                         grp->agglevelsup += context->delta_sublevels_up;
734                 /* fall through to recurse into argument */
735         }
736         if (IsA(node, PlaceHolderVar))
737         {
738                 PlaceHolderVar *phv = (PlaceHolderVar *) node;
739
740                 if (phv->phlevelsup >= context->min_sublevels_up)
741                         phv->phlevelsup += context->delta_sublevels_up;
742                 /* fall through to recurse into argument */
743         }
744         if (IsA(node, RangeTblEntry))
745         {
746                 RangeTblEntry *rte = (RangeTblEntry *) node;
747
748                 if (rte->rtekind == RTE_CTE)
749                 {
750                         if (rte->ctelevelsup >= context->min_sublevels_up)
751                                 rte->ctelevelsup += context->delta_sublevels_up;
752                 }
753                 return false;                   /* allow range_table_walker to continue */
754         }
755         if (IsA(node, Query))
756         {
757                 /* Recurse into subselects */
758                 bool            result;
759
760                 context->min_sublevels_up++;
761                 result = query_tree_walker((Query *) node,
762                                                                    IncrementVarSublevelsUp_walker,
763                                                                    (void *) context,
764                                                                    QTW_EXAMINE_RTES_BEFORE);
765                 context->min_sublevels_up--;
766                 return result;
767         }
768         return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
769                                                                   (void *) context);
770 }
771
772 void
773 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
774                                                 int min_sublevels_up)
775 {
776         IncrementVarSublevelsUp_context context;
777
778         context.delta_sublevels_up = delta_sublevels_up;
779         context.min_sublevels_up = min_sublevels_up;
780
781         /*
782          * Must be prepared to start with a Query or a bare expression tree; if
783          * it's a Query, we don't want to increment sublevels_up.
784          */
785         query_or_expression_tree_walker(node,
786                                                                         IncrementVarSublevelsUp_walker,
787                                                                         (void *) &context,
788                                                                         QTW_EXAMINE_RTES_BEFORE);
789 }
790
791 /*
792  * IncrementVarSublevelsUp_rtable -
793  *      Same as IncrementVarSublevelsUp, but to be invoked on a range table.
794  */
795 void
796 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
797                                                            int min_sublevels_up)
798 {
799         IncrementVarSublevelsUp_context context;
800
801         context.delta_sublevels_up = delta_sublevels_up;
802         context.min_sublevels_up = min_sublevels_up;
803
804         range_table_walker(rtable,
805                                            IncrementVarSublevelsUp_walker,
806                                            (void *) &context,
807                                            QTW_EXAMINE_RTES_BEFORE);
808 }
809
810
811 /*
812  * rangeTableEntry_used - detect whether an RTE is referenced somewhere
813  *      in var nodes or join or setOp trees of a query or expression.
814  */
815
816 typedef struct
817 {
818         int                     rt_index;
819         int                     sublevels_up;
820 } rangeTableEntry_used_context;
821
822 static bool
823 rangeTableEntry_used_walker(Node *node,
824                                                         rangeTableEntry_used_context *context)
825 {
826         if (node == NULL)
827                 return false;
828         if (IsA(node, Var))
829         {
830                 Var                *var = (Var *) node;
831
832                 if (var->varlevelsup == context->sublevels_up &&
833                         var->varno == context->rt_index)
834                         return true;
835                 return false;
836         }
837         if (IsA(node, CurrentOfExpr))
838         {
839                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
840
841                 if (context->sublevels_up == 0 &&
842                         cexpr->cvarno == context->rt_index)
843                         return true;
844                 return false;
845         }
846         if (IsA(node, RangeTblRef))
847         {
848                 RangeTblRef *rtr = (RangeTblRef *) node;
849
850                 if (rtr->rtindex == context->rt_index &&
851                         context->sublevels_up == 0)
852                         return true;
853                 /* the subquery itself is visited separately */
854                 return false;
855         }
856         if (IsA(node, JoinExpr))
857         {
858                 JoinExpr   *j = (JoinExpr *) node;
859
860                 if (j->rtindex == context->rt_index &&
861                         context->sublevels_up == 0)
862                         return true;
863                 /* fall through to examine children */
864         }
865         /* Shouldn't need to handle planner auxiliary nodes here */
866         Assert(!IsA(node, PlaceHolderVar));
867         Assert(!IsA(node, PlanRowMark));
868         Assert(!IsA(node, SpecialJoinInfo));
869         Assert(!IsA(node, AppendRelInfo));
870         Assert(!IsA(node, PlaceHolderInfo));
871         Assert(!IsA(node, MinMaxAggInfo));
872
873         if (IsA(node, Query))
874         {
875                 /* Recurse into subselects */
876                 bool            result;
877
878                 context->sublevels_up++;
879                 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
880                                                                    (void *) context, 0);
881                 context->sublevels_up--;
882                 return result;
883         }
884         return expression_tree_walker(node, rangeTableEntry_used_walker,
885                                                                   (void *) context);
886 }
887
888 bool
889 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
890 {
891         rangeTableEntry_used_context context;
892
893         context.rt_index = rt_index;
894         context.sublevels_up = sublevels_up;
895
896         /*
897          * Must be prepared to start with a Query or a bare expression tree; if
898          * it's a Query, we don't want to increment sublevels_up.
899          */
900         return query_or_expression_tree_walker(node,
901                                                                                    rangeTableEntry_used_walker,
902                                                                                    (void *) &context,
903                                                                                    0);
904 }
905
906
907 /*
908  * If the given Query is an INSERT ... SELECT construct, extract and
909  * return the sub-Query node that represents the SELECT part.  Otherwise
910  * return the given Query.
911  *
912  * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
913  * of the link to the SELECT subquery inside parsetree, or NULL if not an
914  * INSERT ... SELECT.
915  *
916  * This is a hack needed because transformations on INSERT ... SELECTs that
917  * appear in rule actions should be applied to the source SELECT, not to the
918  * INSERT part.  Perhaps this can be cleaned up with redesigned querytrees.
919  */
920 Query *
921 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
922 {
923         Query      *selectquery;
924         RangeTblEntry *selectrte;
925         RangeTblRef *rtr;
926
927         if (subquery_ptr)
928                 *subquery_ptr = NULL;
929
930         if (parsetree == NULL)
931                 return parsetree;
932         if (parsetree->commandType != CMD_INSERT)
933                 return parsetree;
934
935         /*
936          * Currently, this is ONLY applied to rule-action queries, and so we
937          * expect to find the OLD and NEW placeholder entries in the given query.
938          * If they're not there, it must be an INSERT/SELECT in which they've been
939          * pushed down to the SELECT.
940          */
941         if (list_length(parsetree->rtable) >= 2 &&
942                 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
943                            "old") == 0 &&
944                 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
945                            "new") == 0)
946                 return parsetree;
947         Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
948         if (list_length(parsetree->jointree->fromlist) != 1)
949                 elog(ERROR, "expected to find SELECT subquery");
950         rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
951         Assert(IsA(rtr, RangeTblRef));
952         selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
953         selectquery = selectrte->subquery;
954         if (!(selectquery && IsA(selectquery, Query) &&
955                   selectquery->commandType == CMD_SELECT))
956                 elog(ERROR, "expected to find SELECT subquery");
957         if (list_length(selectquery->rtable) >= 2 &&
958                 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
959                            "old") == 0 &&
960                 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
961                            "new") == 0)
962         {
963                 if (subquery_ptr)
964                         *subquery_ptr = &(selectrte->subquery);
965                 return selectquery;
966         }
967         elog(ERROR, "could not find rule placeholders");
968         return NULL;                            /* not reached */
969 }
970
971
972 /*
973  * Add the given qualifier condition to the query's WHERE clause
974  */
975 void
976 AddQual(Query *parsetree, Node *qual)
977 {
978         Node       *copy;
979
980         if (qual == NULL)
981                 return;
982
983         if (parsetree->commandType == CMD_UTILITY)
984         {
985                 /*
986                  * There's noplace to put the qual on a utility statement.
987                  *
988                  * If it's a NOTIFY, silently ignore the qual; this means that the
989                  * NOTIFY will execute, whether or not there are any qualifying rows.
990                  * While clearly wrong, this is much more useful than refusing to
991                  * execute the rule at all, and extra NOTIFY events are harmless for
992                  * typical uses of NOTIFY.
993                  *
994                  * If it isn't a NOTIFY, error out, since unconditional execution of
995                  * other utility stmts is unlikely to be wanted.  (This case is not
996                  * currently allowed anyway, but keep the test for safety.)
997                  */
998                 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
999                         return;
1000                 else
1001                         ereport(ERROR,
1002                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1003                                          errmsg("conditional utility statements are not implemented")));
1004         }
1005
1006         if (parsetree->setOperations != NULL)
1007         {
1008                 /*
1009                  * There's noplace to put the qual on a setop statement, either. (This
1010                  * could be fixed, but right now the planner simply ignores any qual
1011                  * condition on a setop query.)
1012                  */
1013                 ereport(ERROR,
1014                                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1015                                  errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
1016         }
1017
1018         /* INTERSECT want's the original, but we need to copy - Jan */
1019         copy = copyObject(qual);
1020
1021         parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
1022                                                                                            copy);
1023
1024         /*
1025          * We had better not have stuck an aggregate into the WHERE clause.
1026          */
1027         Assert(!contain_aggs_of_level(copy, 0));
1028
1029         /*
1030          * Make sure query is marked correctly if added qual has sublinks. Need
1031          * not search qual when query is already marked.
1032          */
1033         if (!parsetree->hasSubLinks)
1034                 parsetree->hasSubLinks = checkExprHasSubLink(copy);
1035 }
1036
1037
1038 /*
1039  * Invert the given clause and add it to the WHERE qualifications of the
1040  * given querytree.  Inversion means "x IS NOT TRUE", not just "NOT x",
1041  * else we will do the wrong thing when x evaluates to NULL.
1042  */
1043 void
1044 AddInvertedQual(Query *parsetree, Node *qual)
1045 {
1046         BooleanTest *invqual;
1047
1048         if (qual == NULL)
1049                 return;
1050
1051         /* Need not copy input qual, because AddQual will... */
1052         invqual = makeNode(BooleanTest);
1053         invqual->arg = (Expr *) qual;
1054         invqual->booltesttype = IS_NOT_TRUE;
1055         invqual->location = -1;
1056
1057         AddQual(parsetree, (Node *) invqual);
1058 }
1059
1060
1061 /*
1062  * replace_rte_variables() finds all Vars in an expression tree
1063  * that reference a particular RTE, and replaces them with substitute
1064  * expressions obtained from a caller-supplied callback function.
1065  *
1066  * When invoking replace_rte_variables on a portion of a Query, pass the
1067  * address of the containing Query's hasSubLinks field as outer_hasSubLinks.
1068  * Otherwise, pass NULL, but inserting a SubLink into a non-Query expression
1069  * will then cause an error.
1070  *
1071  * Note: the business with inserted_sublink is needed to update hasSubLinks
1072  * in subqueries when the replacement adds a subquery inside a subquery.
1073  * Messy, isn't it?  We do not need to do similar pushups for hasAggs,
1074  * because it isn't possible for this transformation to insert a level-zero
1075  * aggregate reference into a subquery --- it could only insert outer aggs.
1076  * Likewise for hasWindowFuncs.
1077  *
1078  * Note: usually, we'd not expose the mutator function or context struct
1079  * for a function like this.  We do so because callbacks often find it
1080  * convenient to recurse directly to the mutator on sub-expressions of
1081  * what they will return.
1082  */
1083 Node *
1084 replace_rte_variables(Node *node, int target_varno, int sublevels_up,
1085                                           replace_rte_variables_callback callback,
1086                                           void *callback_arg,
1087                                           bool *outer_hasSubLinks)
1088 {
1089         Node       *result;
1090         replace_rte_variables_context context;
1091
1092         context.callback = callback;
1093         context.callback_arg = callback_arg;
1094         context.target_varno = target_varno;
1095         context.sublevels_up = sublevels_up;
1096
1097         /*
1098          * We try to initialize inserted_sublink to true if there is no need to
1099          * detect new sublinks because the query already has some.
1100          */
1101         if (node && IsA(node, Query))
1102                 context.inserted_sublink = ((Query *) node)->hasSubLinks;
1103         else if (outer_hasSubLinks)
1104                 context.inserted_sublink = *outer_hasSubLinks;
1105         else
1106                 context.inserted_sublink = false;
1107
1108         /*
1109          * Must be prepared to start with a Query or a bare expression tree; if
1110          * it's a Query, we don't want to increment sublevels_up.
1111          */
1112         result = query_or_expression_tree_mutator(node,
1113                                                                                           replace_rte_variables_mutator,
1114                                                                                           (void *) &context,
1115                                                                                           0);
1116
1117         if (context.inserted_sublink)
1118         {
1119                 if (result && IsA(result, Query))
1120                         ((Query *) result)->hasSubLinks = true;
1121                 else if (outer_hasSubLinks)
1122                         *outer_hasSubLinks = true;
1123                 else
1124                         elog(ERROR, "replace_rte_variables inserted a SubLink, but has noplace to record it");
1125         }
1126
1127         return result;
1128 }
1129
1130 Node *
1131 replace_rte_variables_mutator(Node *node,
1132                                                           replace_rte_variables_context *context)
1133 {
1134         if (node == NULL)
1135                 return NULL;
1136         if (IsA(node, Var))
1137         {
1138                 Var                *var = (Var *) node;
1139
1140                 if (var->varno == context->target_varno &&
1141                         var->varlevelsup == context->sublevels_up)
1142                 {
1143                         /* Found a matching variable, make the substitution */
1144                         Node       *newnode;
1145
1146                         newnode = context->callback(var, context);
1147                         /* Detect if we are adding a sublink to query */
1148                         if (!context->inserted_sublink)
1149                                 context->inserted_sublink = checkExprHasSubLink(newnode);
1150                         return newnode;
1151                 }
1152                 /* otherwise fall through to copy the var normally */
1153         }
1154         else if (IsA(node, CurrentOfExpr))
1155         {
1156                 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
1157
1158                 if (cexpr->cvarno == context->target_varno &&
1159                         context->sublevels_up == 0)
1160                 {
1161                         /*
1162                          * We get here if a WHERE CURRENT OF expression turns out to apply
1163                          * to a view.  Someday we might be able to translate the
1164                          * expression to apply to an underlying table of the view, but
1165                          * right now it's not implemented.
1166                          */
1167                         ereport(ERROR,
1168                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1169                                          errmsg("WHERE CURRENT OF on a view is not implemented")));
1170                 }
1171                 /* otherwise fall through to copy the expr normally */
1172         }
1173         else if (IsA(node, Query))
1174         {
1175                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1176                 Query      *newnode;
1177                 bool            save_inserted_sublink;
1178
1179                 context->sublevels_up++;
1180                 save_inserted_sublink = context->inserted_sublink;
1181                 context->inserted_sublink = ((Query *) node)->hasSubLinks;
1182                 newnode = query_tree_mutator((Query *) node,
1183                                                                          replace_rte_variables_mutator,
1184                                                                          (void *) context,
1185                                                                          0);
1186                 newnode->hasSubLinks |= context->inserted_sublink;
1187                 context->inserted_sublink = save_inserted_sublink;
1188                 context->sublevels_up--;
1189                 return (Node *) newnode;
1190         }
1191         return expression_tree_mutator(node, replace_rte_variables_mutator,
1192                                                                    (void *) context);
1193 }
1194
1195
1196 /*
1197  * map_variable_attnos() finds all user-column Vars in an expression tree
1198  * that reference a particular RTE, and adjusts their varattnos according
1199  * to the given mapping array (varattno n is replaced by attno_map[n-1]).
1200  * Vars for system columns are not modified.
1201  *
1202  * A zero in the mapping array represents a dropped column, which should not
1203  * appear in the expression.
1204  *
1205  * If the expression tree contains a whole-row Var for the target RTE,
1206  * *found_whole_row is set to true.  In addition, if to_rowtype is
1207  * not InvalidOid, we replace the Var with a Var of that vartype, inserting
1208  * a ConvertRowtypeExpr to map back to the rowtype expected by the expression.
1209  * (Therefore, to_rowtype had better be a child rowtype of the rowtype of the
1210  * RTE we're changing references to.)  Callers that don't provide to_rowtype
1211  * should report an error if *found_row_type is true; we don't do that here
1212  * because we don't know exactly what wording for the error message would
1213  * be most appropriate.  The caller will be aware of the context.
1214  *
1215  * This could be built using replace_rte_variables and a callback function,
1216  * but since we don't ever need to insert sublinks, replace_rte_variables is
1217  * overly complicated.
1218  */
1219
1220 typedef struct
1221 {
1222         int                     target_varno;   /* RTE index to search for */
1223         int                     sublevels_up;   /* (current) nesting depth */
1224         const AttrNumber *attno_map;    /* map array for user attnos */
1225         int                     map_length;             /* number of entries in attno_map[] */
1226         Oid                     to_rowtype;             /* change whole-row Vars to this type */
1227         bool       *found_whole_row;    /* output flag */
1228 } map_variable_attnos_context;
1229
1230 static Node *
1231 map_variable_attnos_mutator(Node *node,
1232                                                         map_variable_attnos_context *context)
1233 {
1234         if (node == NULL)
1235                 return NULL;
1236         if (IsA(node, Var))
1237         {
1238                 Var                *var = (Var *) node;
1239
1240                 if (var->varno == context->target_varno &&
1241                         var->varlevelsup == context->sublevels_up)
1242                 {
1243                         /* Found a matching variable, make the substitution */
1244                         Var                *newvar = (Var *) palloc(sizeof(Var));
1245                         int                     attno = var->varattno;
1246
1247                         *newvar = *var;         /* initially copy all fields of the Var */
1248
1249                         if (attno > 0)
1250                         {
1251                                 /* user-defined column, replace attno */
1252                                 if (attno > context->map_length ||
1253                                         context->attno_map[attno - 1] == 0)
1254                                         elog(ERROR, "unexpected varattno %d in expression to be mapped",
1255                                                  attno);
1256                                 newvar->varattno = newvar->varoattno = context->attno_map[attno - 1];
1257                         }
1258                         else if (attno == 0)
1259                         {
1260                                 /* whole-row variable, warn caller */
1261                                 *(context->found_whole_row) = true;
1262
1263                                 /* If the caller expects us to convert the Var, do so. */
1264                                 if (OidIsValid(context->to_rowtype) &&
1265                                         context->to_rowtype != var->vartype)
1266                                 {
1267                                         ConvertRowtypeExpr *r;
1268
1269                                         /* This certainly won't work for a RECORD variable. */
1270                                         Assert(var->vartype != RECORDOID);
1271
1272                                         /* Var itself is changed to the requested type. */
1273                                         newvar->vartype = context->to_rowtype;
1274
1275                                         /*
1276                                          * Add a conversion node on top to convert back to the
1277                                          * original type expected by the expression.
1278                                          */
1279                                         r = makeNode(ConvertRowtypeExpr);
1280                                         r->arg = (Expr *) newvar;
1281                                         r->resulttype = var->vartype;
1282                                         r->convertformat = COERCE_IMPLICIT_CAST;
1283                                         r->location = -1;
1284
1285                                         return (Node *) r;
1286                                 }
1287                         }
1288                         return (Node *) newvar;
1289                 }
1290                 /* otherwise fall through to copy the var normally */
1291         }
1292         else if (IsA(node, ConvertRowtypeExpr))
1293         {
1294                 ConvertRowtypeExpr *r = (ConvertRowtypeExpr *) node;
1295                 Var                *var = (Var *) r->arg;
1296
1297                 /*
1298                  * If this is coercing a whole-row Var that we need to convert, then
1299                  * just convert the Var without adding an extra ConvertRowtypeExpr.
1300                  * Effectively we're simplifying var::parenttype::grandparenttype into
1301                  * just var::grandparenttype.  This avoids building stacks of CREs if
1302                  * this function is applied repeatedly.
1303                  */
1304                 if (IsA(var, Var) &&
1305                         var->varno == context->target_varno &&
1306                         var->varlevelsup == context->sublevels_up &&
1307                         var->varattno == 0 &&
1308                         OidIsValid(context->to_rowtype) &&
1309                         context->to_rowtype != var->vartype)
1310                 {
1311                         ConvertRowtypeExpr *newnode;
1312                         Var                *newvar = (Var *) palloc(sizeof(Var));
1313
1314                         /* whole-row variable, warn caller */
1315                         *(context->found_whole_row) = true;
1316
1317                         *newvar = *var;         /* initially copy all fields of the Var */
1318
1319                         /* This certainly won't work for a RECORD variable. */
1320                         Assert(var->vartype != RECORDOID);
1321
1322                         /* Var itself is changed to the requested type. */
1323                         newvar->vartype = context->to_rowtype;
1324
1325                         newnode = (ConvertRowtypeExpr *) palloc(sizeof(ConvertRowtypeExpr));
1326                         *newnode = *r;          /* initially copy all fields of the CRE */
1327                         newnode->arg = (Expr *) newvar;
1328
1329                         return (Node *) newnode;
1330                 }
1331                 /* otherwise fall through to process the expression normally */
1332         }
1333         else if (IsA(node, Query))
1334         {
1335                 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1336                 Query      *newnode;
1337
1338                 context->sublevels_up++;
1339                 newnode = query_tree_mutator((Query *) node,
1340                                                                          map_variable_attnos_mutator,
1341                                                                          (void *) context,
1342                                                                          0);
1343                 context->sublevels_up--;
1344                 return (Node *) newnode;
1345         }
1346         return expression_tree_mutator(node, map_variable_attnos_mutator,
1347                                                                    (void *) context);
1348 }
1349
1350 Node *
1351 map_variable_attnos(Node *node,
1352                                         int target_varno, int sublevels_up,
1353                                         const AttrNumber *attno_map, int map_length,
1354                                         Oid to_rowtype, bool *found_whole_row)
1355 {
1356         map_variable_attnos_context context;
1357
1358         context.target_varno = target_varno;
1359         context.sublevels_up = sublevels_up;
1360         context.attno_map = attno_map;
1361         context.map_length = map_length;
1362         context.to_rowtype = to_rowtype;
1363         context.found_whole_row = found_whole_row;
1364
1365         *found_whole_row = false;
1366
1367         /*
1368          * Must be prepared to start with a Query or a bare expression tree; if
1369          * it's a Query, we don't want to increment sublevels_up.
1370          */
1371         return query_or_expression_tree_mutator(node,
1372                                                                                         map_variable_attnos_mutator,
1373                                                                                         (void *) &context,
1374                                                                                         0);
1375 }
1376
1377
1378 /*
1379  * ReplaceVarsFromTargetList - replace Vars with items from a targetlist
1380  *
1381  * Vars matching target_varno and sublevels_up are replaced by the
1382  * entry with matching resno from targetlist, if there is one.
1383  *
1384  * If there is no matching resno for such a Var, the action depends on the
1385  * nomatch_option:
1386  *      REPLACEVARS_REPORT_ERROR: throw an error
1387  *      REPLACEVARS_CHANGE_VARNO: change Var's varno to nomatch_varno
1388  *      REPLACEVARS_SUBSTITUTE_NULL: replace Var with a NULL Const of same type
1389  *
1390  * The caller must also provide target_rte, the RTE describing the target
1391  * relation.  This is needed to handle whole-row Vars referencing the target.
1392  * We expand such Vars into RowExpr constructs.
1393  *
1394  * outer_hasSubLinks works the same as for replace_rte_variables().
1395  */
1396
1397 typedef struct
1398 {
1399         RangeTblEntry *target_rte;
1400         List       *targetlist;
1401         ReplaceVarsNoMatchOption nomatch_option;
1402         int                     nomatch_varno;
1403 } ReplaceVarsFromTargetList_context;
1404
1405 static Node *
1406 ReplaceVarsFromTargetList_callback(Var *var,
1407                                                                    replace_rte_variables_context *context)
1408 {
1409         ReplaceVarsFromTargetList_context *rcon = (ReplaceVarsFromTargetList_context *) context->callback_arg;
1410         TargetEntry *tle;
1411
1412         if (var->varattno == InvalidAttrNumber)
1413         {
1414                 /* Must expand whole-tuple reference into RowExpr */
1415                 RowExpr    *rowexpr;
1416                 List       *colnames;
1417                 List       *fields;
1418
1419                 /*
1420                  * If generating an expansion for a var of a named rowtype (ie, this
1421                  * is a plain relation RTE), then we must include dummy items for
1422                  * dropped columns.  If the var is RECORD (ie, this is a JOIN), then
1423                  * omit dropped columns.  Either way, attach column names to the
1424                  * RowExpr for use of ruleutils.c.
1425                  */
1426                 expandRTE(rcon->target_rte,
1427                                   var->varno, var->varlevelsup, var->location,
1428                                   (var->vartype != RECORDOID),
1429                                   &colnames, &fields);
1430                 /* Adjust the generated per-field Vars... */
1431                 fields = (List *) replace_rte_variables_mutator((Node *) fields,
1432                                                                                                                 context);
1433                 rowexpr = makeNode(RowExpr);
1434                 rowexpr->args = fields;
1435                 rowexpr->row_typeid = var->vartype;
1436                 rowexpr->row_format = COERCE_IMPLICIT_CAST;
1437                 rowexpr->colnames = colnames;
1438                 rowexpr->location = var->location;
1439
1440                 return (Node *) rowexpr;
1441         }
1442
1443         /* Normal case referencing one targetlist element */
1444         tle = get_tle_by_resno(rcon->targetlist, var->varattno);
1445
1446         if (tle == NULL || tle->resjunk)
1447         {
1448                 /* Failed to find column in targetlist */
1449                 switch (rcon->nomatch_option)
1450                 {
1451                         case REPLACEVARS_REPORT_ERROR:
1452                                 /* fall through, throw error below */
1453                                 break;
1454
1455                         case REPLACEVARS_CHANGE_VARNO:
1456                                 var = (Var *) copyObject(var);
1457                                 var->varno = rcon->nomatch_varno;
1458                                 var->varnoold = rcon->nomatch_varno;
1459                                 return (Node *) var;
1460
1461                         case REPLACEVARS_SUBSTITUTE_NULL:
1462
1463                                 /*
1464                                  * If Var is of domain type, we should add a CoerceToDomain
1465                                  * node, in case there is a NOT NULL domain constraint.
1466                                  */
1467                                 return coerce_to_domain((Node *) makeNullConst(var->vartype,
1468                                                                                                                            var->vartypmod,
1469                                                                                                                            var->varcollid),
1470                                                                                 InvalidOid, -1,
1471                                                                                 var->vartype,
1472                                                                                 COERCION_IMPLICIT,
1473                                                                                 COERCE_IMPLICIT_CAST,
1474                                                                                 -1,
1475                                                                                 false);
1476                 }
1477                 elog(ERROR, "could not find replacement targetlist entry for attno %d",
1478                          var->varattno);
1479                 return NULL;                    /* keep compiler quiet */
1480         }
1481         else
1482         {
1483                 /* Make a copy of the tlist item to return */
1484                 Expr       *newnode = copyObject(tle->expr);
1485
1486                 /* Must adjust varlevelsup if tlist item is from higher query */
1487                 if (var->varlevelsup > 0)
1488                         IncrementVarSublevelsUp((Node *) newnode, var->varlevelsup, 0);
1489
1490                 /*
1491                  * Check to see if the tlist item contains a PARAM_MULTIEXPR Param,
1492                  * and throw error if so.  This case could only happen when expanding
1493                  * an ON UPDATE rule's NEW variable and the referenced tlist item in
1494                  * the original UPDATE command is part of a multiple assignment. There
1495                  * seems no practical way to handle such cases without multiple
1496                  * evaluation of the multiple assignment's sub-select, which would
1497                  * create semantic oddities that users of rules would probably prefer
1498                  * not to cope with.  So treat it as an unimplemented feature.
1499                  */
1500                 if (contains_multiexpr_param((Node *) newnode, NULL))
1501                         ereport(ERROR,
1502                                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1503                                          errmsg("NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command")));
1504
1505                 return (Node *) newnode;
1506         }
1507 }
1508
1509 Node *
1510 ReplaceVarsFromTargetList(Node *node,
1511                                                   int target_varno, int sublevels_up,
1512                                                   RangeTblEntry *target_rte,
1513                                                   List *targetlist,
1514                                                   ReplaceVarsNoMatchOption nomatch_option,
1515                                                   int nomatch_varno,
1516                                                   bool *outer_hasSubLinks)
1517 {
1518         ReplaceVarsFromTargetList_context context;
1519
1520         context.target_rte = target_rte;
1521         context.targetlist = targetlist;
1522         context.nomatch_option = nomatch_option;
1523         context.nomatch_varno = nomatch_varno;
1524
1525         return replace_rte_variables(node, target_varno, sublevels_up,
1526                                                                  ReplaceVarsFromTargetList_callback,
1527                                                                  (void *) &context,
1528                                                                  outer_hasSubLinks);
1529 }