1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
10 * src/backend/rewrite/rewriteManip.c
12 *-------------------------------------------------------------------------
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"
30 } contain_aggs_of_level_context;
36 } locate_agg_of_level_context;
41 } locate_windowfunc_context;
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);
56 * contain_aggs_of_level -
57 * Check if an expression contains an aggregate function call of a
58 * specified query level.
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.
67 contain_aggs_of_level(Node *node, int levelsup)
69 contain_aggs_of_level_context context;
71 context.sublevels_up = levelsup;
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.
77 return query_or_expression_tree_walker(node,
78 contain_aggs_of_level_walker,
84 contain_aggs_of_level_walker(Node *node,
85 contain_aggs_of_level_context *context)
89 if (IsA(node, Aggref))
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 */
97 /* Recurse into subselects */
100 context->sublevels_up++;
101 result = query_tree_walker((Query *) node,
102 contain_aggs_of_level_walker,
103 (void *) context, 0);
104 context->sublevels_up--;
107 return expression_tree_walker(node, contain_aggs_of_level_walker,
112 * locate_agg_of_level -
113 * Find the parse location of any aggregate of the specified query level.
115 * Returns -1 if no such agg is in the querytree, or if they all have
116 * unknown parse location. (The former case is probably caller error,
117 * but we don't bother to distinguish it from the latter case.)
119 * Note: it might seem appropriate to merge this functionality into
120 * contain_aggs_of_level, but that would complicate that function's API.
121 * Currently, the only uses of this function are for error reporting,
122 * and so shaving cycles probably isn't very important.
125 locate_agg_of_level(Node *node, int levelsup)
127 locate_agg_of_level_context context;
129 context.agg_location = -1; /* in case we find nothing */
130 context.sublevels_up = levelsup;
133 * Must be prepared to start with a Query or a bare expression tree; if
134 * it's a Query, we don't want to increment sublevels_up.
136 (void) query_or_expression_tree_walker(node,
137 locate_agg_of_level_walker,
141 return context.agg_location;
145 locate_agg_of_level_walker(Node *node,
146 locate_agg_of_level_context *context)
150 if (IsA(node, Aggref))
152 if (((Aggref *) node)->agglevelsup == context->sublevels_up &&
153 ((Aggref *) node)->location >= 0)
155 context->agg_location = ((Aggref *) node)->location;
156 return true; /* abort the tree traversal and return true */
158 /* else fall through to examine argument */
160 if (IsA(node, Query))
162 /* Recurse into subselects */
165 context->sublevels_up++;
166 result = query_tree_walker((Query *) node,
167 locate_agg_of_level_walker,
168 (void *) context, 0);
169 context->sublevels_up--;
172 return expression_tree_walker(node, locate_agg_of_level_walker,
177 * contain_windowfuncs -
178 * Check if an expression contains a window function call of the
179 * current query level.
182 contain_windowfuncs(Node *node)
185 * Must be prepared to start with a Query or a bare expression tree; if
186 * it's a Query, we don't want to increment sublevels_up.
188 return query_or_expression_tree_walker(node,
189 contain_windowfuncs_walker,
195 contain_windowfuncs_walker(Node *node, void *context)
199 if (IsA(node, WindowFunc))
200 return true; /* abort the tree traversal and return true */
201 /* Mustn't recurse into subselects */
202 return expression_tree_walker(node, contain_windowfuncs_walker,
207 * locate_windowfunc -
208 * Find the parse location of any windowfunc of the current query level.
210 * Returns -1 if no such windowfunc is in the querytree, or if they all have
211 * unknown parse location. (The former case is probably caller error,
212 * but we don't bother to distinguish it from the latter case.)
214 * Note: it might seem appropriate to merge this functionality into
215 * contain_windowfuncs, but that would complicate that function's API.
216 * Currently, the only uses of this function are for error reporting,
217 * and so shaving cycles probably isn't very important.
220 locate_windowfunc(Node *node)
222 locate_windowfunc_context context;
224 context.win_location = -1; /* in case we find nothing */
227 * Must be prepared to start with a Query or a bare expression tree; if
228 * it's a Query, we don't want to increment sublevels_up.
230 (void) query_or_expression_tree_walker(node,
231 locate_windowfunc_walker,
235 return context.win_location;
239 locate_windowfunc_walker(Node *node, locate_windowfunc_context *context)
243 if (IsA(node, WindowFunc))
245 if (((WindowFunc *) node)->location >= 0)
247 context->win_location = ((WindowFunc *) node)->location;
248 return true; /* abort the tree traversal and return true */
250 /* else fall through to examine argument */
252 /* Mustn't recurse into subselects */
253 return expression_tree_walker(node, locate_windowfunc_walker,
258 * checkExprHasSubLink -
259 * Check if an expression contains a SubLink.
262 checkExprHasSubLink(Node *node)
265 * If a Query is passed, examine it --- but we should not recurse into
266 * sub-Queries that are in its rangetable or CTE list.
268 return query_or_expression_tree_walker(node,
269 checkExprHasSubLink_walker,
271 QTW_IGNORE_RC_SUBQUERIES);
275 checkExprHasSubLink_walker(Node *node, void *context)
279 if (IsA(node, SubLink))
280 return true; /* abort the tree traversal and return true */
281 return expression_tree_walker(node, checkExprHasSubLink_walker, context);
285 * Check for MULTIEXPR Param within expression tree
287 * We intentionally don't descend into SubLinks: only Params at the current
288 * query level are of interest.
291 contains_multiexpr_param(Node *node, void *context)
295 if (IsA(node, Param))
297 if (((Param *) node)->paramkind == PARAM_MULTIEXPR)
298 return true; /* abort the tree traversal and return true */
301 return expression_tree_walker(node, contains_multiexpr_param, context);
306 * OffsetVarNodes - adjust Vars when appending one query's RT to another
308 * Find all Var nodes in the given tree with varlevelsup == sublevels_up,
309 * and increment their varno fields (rangetable indexes) by 'offset'.
310 * The varnoold fields are adjusted similarly. Also, adjust other nodes
311 * that contain rangetable indexes, such as RangeTblRef and JoinExpr.
313 * NOTE: although this has the form of a walker, we cheat and modify the
314 * nodes in-place. The given expression tree should have been copied
315 * earlier to ensure that no unwanted side-effects occur!
322 } OffsetVarNodes_context;
325 OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
331 Var *var = (Var *) node;
333 if (var->varlevelsup == context->sublevels_up)
335 var->varno += context->offset;
336 var->varnoold += context->offset;
340 if (IsA(node, CurrentOfExpr))
342 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
344 if (context->sublevels_up == 0)
345 cexpr->cvarno += context->offset;
348 if (IsA(node, RangeTblRef))
350 RangeTblRef *rtr = (RangeTblRef *) node;
352 if (context->sublevels_up == 0)
353 rtr->rtindex += context->offset;
354 /* the subquery itself is visited separately */
357 if (IsA(node, JoinExpr))
359 JoinExpr *j = (JoinExpr *) node;
361 if (j->rtindex && context->sublevels_up == 0)
362 j->rtindex += context->offset;
363 /* fall through to examine children */
365 if (IsA(node, PlaceHolderVar))
367 PlaceHolderVar *phv = (PlaceHolderVar *) node;
369 if (phv->phlevelsup == context->sublevels_up)
371 phv->phrels = offset_relid_set(phv->phrels,
374 /* fall through to examine children */
376 if (IsA(node, AppendRelInfo))
378 AppendRelInfo *appinfo = (AppendRelInfo *) node;
380 if (context->sublevels_up == 0)
382 appinfo->parent_relid += context->offset;
383 appinfo->child_relid += context->offset;
385 /* fall through to examine children */
387 /* Shouldn't need to handle other planner auxiliary nodes here */
388 Assert(!IsA(node, PlanRowMark));
389 Assert(!IsA(node, SpecialJoinInfo));
390 Assert(!IsA(node, LateralJoinInfo));
391 Assert(!IsA(node, PlaceHolderInfo));
392 Assert(!IsA(node, MinMaxAggInfo));
394 if (IsA(node, Query))
396 /* Recurse into subselects */
399 context->sublevels_up++;
400 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
401 (void *) context, 0);
402 context->sublevels_up--;
405 return expression_tree_walker(node, OffsetVarNodes_walker,
410 OffsetVarNodes(Node *node, int offset, int sublevels_up)
412 OffsetVarNodes_context context;
414 context.offset = offset;
415 context.sublevels_up = sublevels_up;
418 * Must be prepared to start with a Query or a bare expression tree; if
419 * it's a Query, go straight to query_tree_walker to make sure that
420 * sublevels_up doesn't get incremented prematurely.
422 if (node && IsA(node, Query))
424 Query *qry = (Query *) node;
427 * If we are starting at a Query, and sublevels_up is zero, then we
428 * must also fix rangetable indexes in the Query itself --- namely
429 * resultRelation and rowMarks entries. sublevels_up cannot be zero
430 * when recursing into a subquery, so there's no need to have the same
431 * logic inside OffsetVarNodes_walker.
433 if (sublevels_up == 0)
437 if (qry->resultRelation)
438 qry->resultRelation += offset;
439 foreach(l, qry->rowMarks)
441 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
446 query_tree_walker(qry, OffsetVarNodes_walker,
447 (void *) &context, 0);
450 OffsetVarNodes_walker(node, &context);
454 offset_relid_set(Relids relids, int offset)
456 Relids result = NULL;
460 tmprelids = bms_copy(relids);
461 while ((rtindex = bms_first_member(tmprelids)) >= 0)
462 result = bms_add_member(result, rtindex + offset);
468 * ChangeVarNodes - adjust Var nodes for a specific change of RT index
470 * Find all Var nodes in the given tree belonging to a specific relation
471 * (identified by sublevels_up and rt_index), and change their varno fields
472 * to 'new_index'. The varnoold fields are changed too. Also, adjust other
473 * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
475 * NOTE: although this has the form of a walker, we cheat and modify the
476 * nodes in-place. The given expression tree should have been copied
477 * earlier to ensure that no unwanted side-effects occur!
485 } ChangeVarNodes_context;
488 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
494 Var *var = (Var *) node;
496 if (var->varlevelsup == context->sublevels_up &&
497 var->varno == context->rt_index)
499 var->varno = context->new_index;
500 var->varnoold = context->new_index;
504 if (IsA(node, CurrentOfExpr))
506 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
508 if (context->sublevels_up == 0 &&
509 cexpr->cvarno == context->rt_index)
510 cexpr->cvarno = context->new_index;
513 if (IsA(node, RangeTblRef))
515 RangeTblRef *rtr = (RangeTblRef *) node;
517 if (context->sublevels_up == 0 &&
518 rtr->rtindex == context->rt_index)
519 rtr->rtindex = context->new_index;
520 /* the subquery itself is visited separately */
523 if (IsA(node, JoinExpr))
525 JoinExpr *j = (JoinExpr *) node;
527 if (context->sublevels_up == 0 &&
528 j->rtindex == context->rt_index)
529 j->rtindex = context->new_index;
530 /* fall through to examine children */
532 if (IsA(node, PlaceHolderVar))
534 PlaceHolderVar *phv = (PlaceHolderVar *) node;
536 if (phv->phlevelsup == context->sublevels_up)
538 phv->phrels = adjust_relid_set(phv->phrels,
542 /* fall through to examine children */
544 if (IsA(node, PlanRowMark))
546 PlanRowMark *rowmark = (PlanRowMark *) node;
548 if (context->sublevels_up == 0)
550 if (rowmark->rti == context->rt_index)
551 rowmark->rti = context->new_index;
552 if (rowmark->prti == context->rt_index)
553 rowmark->prti = context->new_index;
557 if (IsA(node, AppendRelInfo))
559 AppendRelInfo *appinfo = (AppendRelInfo *) node;
561 if (context->sublevels_up == 0)
563 if (appinfo->parent_relid == context->rt_index)
564 appinfo->parent_relid = context->new_index;
565 if (appinfo->child_relid == context->rt_index)
566 appinfo->child_relid = context->new_index;
568 /* fall through to examine children */
570 /* Shouldn't need to handle other planner auxiliary nodes here */
571 Assert(!IsA(node, SpecialJoinInfo));
572 Assert(!IsA(node, LateralJoinInfo));
573 Assert(!IsA(node, PlaceHolderInfo));
574 Assert(!IsA(node, MinMaxAggInfo));
576 if (IsA(node, Query))
578 /* Recurse into subselects */
581 context->sublevels_up++;
582 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
583 (void *) context, 0);
584 context->sublevels_up--;
587 return expression_tree_walker(node, ChangeVarNodes_walker,
592 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
594 ChangeVarNodes_context context;
596 context.rt_index = rt_index;
597 context.new_index = new_index;
598 context.sublevels_up = sublevels_up;
601 * Must be prepared to start with a Query or a bare expression tree; if
602 * it's a Query, go straight to query_tree_walker to make sure that
603 * sublevels_up doesn't get incremented prematurely.
605 if (node && IsA(node, Query))
607 Query *qry = (Query *) node;
610 * If we are starting at a Query, and sublevels_up is zero, then we
611 * must also fix rangetable indexes in the Query itself --- namely
612 * resultRelation and rowMarks entries. sublevels_up cannot be zero
613 * when recursing into a subquery, so there's no need to have the same
614 * logic inside ChangeVarNodes_walker.
616 if (sublevels_up == 0)
620 if (qry->resultRelation == rt_index)
621 qry->resultRelation = new_index;
622 foreach(l, qry->rowMarks)
624 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
626 if (rc->rti == rt_index)
630 query_tree_walker(qry, ChangeVarNodes_walker,
631 (void *) &context, 0);
634 ChangeVarNodes_walker(node, &context);
638 * Substitute newrelid for oldrelid in a Relid set
641 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
643 if (bms_is_member(oldrelid, relids))
645 /* Ensure we have a modifiable copy */
646 relids = bms_copy(relids);
647 /* Remove old, add new */
648 relids = bms_del_member(relids, oldrelid);
649 relids = bms_add_member(relids, newrelid);
655 * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
657 * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
658 * and add delta_sublevels_up to their varlevelsup value. This is needed when
659 * an expression that's correct for some nesting level is inserted into a
660 * subquery. Ordinarily the initial call has min_sublevels_up == 0 so that
661 * all Vars are affected. The point of min_sublevels_up is that we can
662 * increment it when we recurse into a sublink, so that local variables in
663 * that sublink are not affected, only outer references to vars that belong
664 * to the expression's original query level or parents thereof.
666 * Likewise for other nodes containing levelsup fields, such as Aggref.
668 * NOTE: although this has the form of a walker, we cheat and modify the
669 * Var nodes in-place. The given expression tree should have been copied
670 * earlier to ensure that no unwanted side-effects occur!
675 int delta_sublevels_up;
676 int min_sublevels_up;
677 } IncrementVarSublevelsUp_context;
680 IncrementVarSublevelsUp_walker(Node *node,
681 IncrementVarSublevelsUp_context *context)
687 Var *var = (Var *) node;
689 if (var->varlevelsup >= context->min_sublevels_up)
690 var->varlevelsup += context->delta_sublevels_up;
691 return false; /* done here */
693 if (IsA(node, CurrentOfExpr))
695 /* this should not happen */
696 if (context->min_sublevels_up == 0)
697 elog(ERROR, "cannot push down CurrentOfExpr");
700 if (IsA(node, Aggref))
702 Aggref *agg = (Aggref *) node;
704 if (agg->agglevelsup >= context->min_sublevels_up)
705 agg->agglevelsup += context->delta_sublevels_up;
706 /* fall through to recurse into argument */
708 if (IsA(node, PlaceHolderVar))
710 PlaceHolderVar *phv = (PlaceHolderVar *) node;
712 if (phv->phlevelsup >= context->min_sublevels_up)
713 phv->phlevelsup += context->delta_sublevels_up;
714 /* fall through to recurse into argument */
716 if (IsA(node, RangeTblEntry))
718 RangeTblEntry *rte = (RangeTblEntry *) node;
720 if (rte->rtekind == RTE_CTE)
722 if (rte->ctelevelsup >= context->min_sublevels_up)
723 rte->ctelevelsup += context->delta_sublevels_up;
725 return false; /* allow range_table_walker to continue */
727 if (IsA(node, Query))
729 /* Recurse into subselects */
732 context->min_sublevels_up++;
733 result = query_tree_walker((Query *) node,
734 IncrementVarSublevelsUp_walker,
737 context->min_sublevels_up--;
740 return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
745 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
746 int min_sublevels_up)
748 IncrementVarSublevelsUp_context context;
750 context.delta_sublevels_up = delta_sublevels_up;
751 context.min_sublevels_up = min_sublevels_up;
754 * Must be prepared to start with a Query or a bare expression tree; if
755 * it's a Query, we don't want to increment sublevels_up.
757 query_or_expression_tree_walker(node,
758 IncrementVarSublevelsUp_walker,
764 * IncrementVarSublevelsUp_rtable -
765 * Same as IncrementVarSublevelsUp, but to be invoked on a range table.
768 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
769 int min_sublevels_up)
771 IncrementVarSublevelsUp_context context;
773 context.delta_sublevels_up = delta_sublevels_up;
774 context.min_sublevels_up = min_sublevels_up;
776 range_table_walker(rtable,
777 IncrementVarSublevelsUp_walker,
784 * rangeTableEntry_used - detect whether an RTE is referenced somewhere
785 * in var nodes or join or setOp trees of a query or expression.
792 } rangeTableEntry_used_context;
795 rangeTableEntry_used_walker(Node *node,
796 rangeTableEntry_used_context *context)
802 Var *var = (Var *) node;
804 if (var->varlevelsup == context->sublevels_up &&
805 var->varno == context->rt_index)
809 if (IsA(node, CurrentOfExpr))
811 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
813 if (context->sublevels_up == 0 &&
814 cexpr->cvarno == context->rt_index)
818 if (IsA(node, RangeTblRef))
820 RangeTblRef *rtr = (RangeTblRef *) node;
822 if (rtr->rtindex == context->rt_index &&
823 context->sublevels_up == 0)
825 /* the subquery itself is visited separately */
828 if (IsA(node, JoinExpr))
830 JoinExpr *j = (JoinExpr *) node;
832 if (j->rtindex == context->rt_index &&
833 context->sublevels_up == 0)
835 /* fall through to examine children */
837 /* Shouldn't need to handle planner auxiliary nodes here */
838 Assert(!IsA(node, PlaceHolderVar));
839 Assert(!IsA(node, PlanRowMark));
840 Assert(!IsA(node, SpecialJoinInfo));
841 Assert(!IsA(node, LateralJoinInfo));
842 Assert(!IsA(node, AppendRelInfo));
843 Assert(!IsA(node, PlaceHolderInfo));
844 Assert(!IsA(node, MinMaxAggInfo));
846 if (IsA(node, Query))
848 /* Recurse into subselects */
851 context->sublevels_up++;
852 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
853 (void *) context, 0);
854 context->sublevels_up--;
857 return expression_tree_walker(node, rangeTableEntry_used_walker,
862 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
864 rangeTableEntry_used_context context;
866 context.rt_index = rt_index;
867 context.sublevels_up = sublevels_up;
870 * Must be prepared to start with a Query or a bare expression tree; if
871 * it's a Query, we don't want to increment sublevels_up.
873 return query_or_expression_tree_walker(node,
874 rangeTableEntry_used_walker,
881 * If the given Query is an INSERT ... SELECT construct, extract and
882 * return the sub-Query node that represents the SELECT part. Otherwise
883 * return the given Query.
885 * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
886 * of the link to the SELECT subquery inside parsetree, or NULL if not an
889 * This is a hack needed because transformations on INSERT ... SELECTs that
890 * appear in rule actions should be applied to the source SELECT, not to the
891 * INSERT part. Perhaps this can be cleaned up with redesigned querytrees.
894 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
897 RangeTblEntry *selectrte;
901 *subquery_ptr = NULL;
903 if (parsetree == NULL)
905 if (parsetree->commandType != CMD_INSERT)
909 * Currently, this is ONLY applied to rule-action queries, and so we
910 * expect to find the OLD and NEW placeholder entries in the given query.
911 * If they're not there, it must be an INSERT/SELECT in which they've been
912 * pushed down to the SELECT.
914 if (list_length(parsetree->rtable) >= 2 &&
915 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
917 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
920 Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
921 if (list_length(parsetree->jointree->fromlist) != 1)
922 elog(ERROR, "expected to find SELECT subquery");
923 rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
924 Assert(IsA(rtr, RangeTblRef));
925 selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
926 selectquery = selectrte->subquery;
927 if (!(selectquery && IsA(selectquery, Query) &&
928 selectquery->commandType == CMD_SELECT))
929 elog(ERROR, "expected to find SELECT subquery");
930 if (list_length(selectquery->rtable) >= 2 &&
931 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
933 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
937 *subquery_ptr = &(selectrte->subquery);
940 elog(ERROR, "could not find rule placeholders");
941 return NULL; /* not reached */
946 * Add the given qualifier condition to the query's WHERE clause
949 AddQual(Query *parsetree, Node *qual)
956 if (parsetree->commandType == CMD_UTILITY)
959 * There's noplace to put the qual on a utility statement.
961 * If it's a NOTIFY, silently ignore the qual; this means that the
962 * NOTIFY will execute, whether or not there are any qualifying rows.
963 * While clearly wrong, this is much more useful than refusing to
964 * execute the rule at all, and extra NOTIFY events are harmless for
965 * typical uses of NOTIFY.
967 * If it isn't a NOTIFY, error out, since unconditional execution of
968 * other utility stmts is unlikely to be wanted. (This case is not
969 * currently allowed anyway, but keep the test for safety.)
971 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
975 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
976 errmsg("conditional utility statements are not implemented")));
979 if (parsetree->setOperations != NULL)
982 * There's noplace to put the qual on a setop statement, either. (This
983 * could be fixed, but right now the planner simply ignores any qual
984 * condition on a setop query.)
987 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
988 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
991 /* INTERSECT want's the original, but we need to copy - Jan */
992 copy = copyObject(qual);
994 parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
998 * We had better not have stuck an aggregate into the WHERE clause.
1000 Assert(!contain_aggs_of_level(copy, 0));
1003 * Make sure query is marked correctly if added qual has sublinks. Need
1004 * not search qual when query is already marked.
1006 if (!parsetree->hasSubLinks)
1007 parsetree->hasSubLinks = checkExprHasSubLink(copy);
1012 * Invert the given clause and add it to the WHERE qualifications of the
1013 * given querytree. Inversion means "x IS NOT TRUE", not just "NOT x",
1014 * else we will do the wrong thing when x evaluates to NULL.
1017 AddInvertedQual(Query *parsetree, Node *qual)
1019 BooleanTest *invqual;
1024 /* Need not copy input qual, because AddQual will... */
1025 invqual = makeNode(BooleanTest);
1026 invqual->arg = (Expr *) qual;
1027 invqual->booltesttype = IS_NOT_TRUE;
1029 AddQual(parsetree, (Node *) invqual);
1034 * replace_rte_variables() finds all Vars in an expression tree
1035 * that reference a particular RTE, and replaces them with substitute
1036 * expressions obtained from a caller-supplied callback function.
1038 * When invoking replace_rte_variables on a portion of a Query, pass the
1039 * address of the containing Query's hasSubLinks field as outer_hasSubLinks.
1040 * Otherwise, pass NULL, but inserting a SubLink into a non-Query expression
1041 * will then cause an error.
1043 * Note: the business with inserted_sublink is needed to update hasSubLinks
1044 * in subqueries when the replacement adds a subquery inside a subquery.
1045 * Messy, isn't it? We do not need to do similar pushups for hasAggs,
1046 * because it isn't possible for this transformation to insert a level-zero
1047 * aggregate reference into a subquery --- it could only insert outer aggs.
1048 * Likewise for hasWindowFuncs.
1050 * Note: usually, we'd not expose the mutator function or context struct
1051 * for a function like this. We do so because callbacks often find it
1052 * convenient to recurse directly to the mutator on sub-expressions of
1053 * what they will return.
1056 replace_rte_variables(Node *node, int target_varno, int sublevels_up,
1057 replace_rte_variables_callback callback,
1059 bool *outer_hasSubLinks)
1062 replace_rte_variables_context context;
1064 context.callback = callback;
1065 context.callback_arg = callback_arg;
1066 context.target_varno = target_varno;
1067 context.sublevels_up = sublevels_up;
1070 * We try to initialize inserted_sublink to true if there is no need to
1071 * detect new sublinks because the query already has some.
1073 if (node && IsA(node, Query))
1074 context.inserted_sublink = ((Query *) node)->hasSubLinks;
1075 else if (outer_hasSubLinks)
1076 context.inserted_sublink = *outer_hasSubLinks;
1078 context.inserted_sublink = false;
1081 * Must be prepared to start with a Query or a bare expression tree; if
1082 * it's a Query, we don't want to increment sublevels_up.
1084 result = query_or_expression_tree_mutator(node,
1085 replace_rte_variables_mutator,
1089 if (context.inserted_sublink)
1091 if (result && IsA(result, Query))
1092 ((Query *) result)->hasSubLinks = true;
1093 else if (outer_hasSubLinks)
1094 *outer_hasSubLinks = true;
1096 elog(ERROR, "replace_rte_variables inserted a SubLink, but has noplace to record it");
1103 replace_rte_variables_mutator(Node *node,
1104 replace_rte_variables_context *context)
1110 Var *var = (Var *) node;
1112 if (var->varno == context->target_varno &&
1113 var->varlevelsup == context->sublevels_up)
1115 /* Found a matching variable, make the substitution */
1118 newnode = (*context->callback) (var, context);
1119 /* Detect if we are adding a sublink to query */
1120 if (!context->inserted_sublink)
1121 context->inserted_sublink = checkExprHasSubLink(newnode);
1124 /* otherwise fall through to copy the var normally */
1126 else if (IsA(node, CurrentOfExpr))
1128 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
1130 if (cexpr->cvarno == context->target_varno &&
1131 context->sublevels_up == 0)
1134 * We get here if a WHERE CURRENT OF expression turns out to apply
1135 * to a view. Someday we might be able to translate the
1136 * expression to apply to an underlying table of the view, but
1137 * right now it's not implemented.
1140 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1141 errmsg("WHERE CURRENT OF on a view is not implemented")));
1143 /* otherwise fall through to copy the expr normally */
1145 else if (IsA(node, Query))
1147 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1149 bool save_inserted_sublink;
1151 context->sublevels_up++;
1152 save_inserted_sublink = context->inserted_sublink;
1153 context->inserted_sublink = ((Query *) node)->hasSubLinks;
1154 newnode = query_tree_mutator((Query *) node,
1155 replace_rte_variables_mutator,
1158 newnode->hasSubLinks |= context->inserted_sublink;
1159 context->inserted_sublink = save_inserted_sublink;
1160 context->sublevels_up--;
1161 return (Node *) newnode;
1163 return expression_tree_mutator(node, replace_rte_variables_mutator,
1169 * map_variable_attnos() finds all user-column Vars in an expression tree
1170 * that reference a particular RTE, and adjusts their varattnos according
1171 * to the given mapping array (varattno n is replaced by attno_map[n-1]).
1172 * Vars for system columns are not modified.
1174 * A zero in the mapping array represents a dropped column, which should not
1175 * appear in the expression.
1177 * If the expression tree contains a whole-row Var for the target RTE,
1178 * the Var is not changed but *found_whole_row is returned as TRUE.
1179 * For most callers this is an error condition, but we leave it to the caller
1180 * to report the error so that useful context can be provided. (In some
1181 * usages it would be appropriate to modify the Var's vartype and insert a
1182 * ConvertRowtypeExpr node to map back to the original vartype. We might
1183 * someday extend this function's API to support that. For now, the only
1184 * concession to that future need is that this function is a tree mutator
1185 * not just a walker.)
1187 * This could be built using replace_rte_variables and a callback function,
1188 * but since we don't ever need to insert sublinks, replace_rte_variables is
1189 * overly complicated.
1194 int target_varno; /* RTE index to search for */
1195 int sublevels_up; /* (current) nesting depth */
1196 const AttrNumber *attno_map; /* map array for user attnos */
1197 int map_length; /* number of entries in attno_map[] */
1198 bool *found_whole_row; /* output flag */
1199 } map_variable_attnos_context;
1202 map_variable_attnos_mutator(Node *node,
1203 map_variable_attnos_context *context)
1209 Var *var = (Var *) node;
1211 if (var->varno == context->target_varno &&
1212 var->varlevelsup == context->sublevels_up)
1214 /* Found a matching variable, make the substitution */
1215 Var *newvar = (Var *) palloc(sizeof(Var));
1216 int attno = var->varattno;
1221 /* user-defined column, replace attno */
1222 if (attno > context->map_length ||
1223 context->attno_map[attno - 1] == 0)
1224 elog(ERROR, "unexpected varattno %d in expression to be mapped",
1226 newvar->varattno = newvar->varoattno = context->attno_map[attno - 1];
1228 else if (attno == 0)
1230 /* whole-row variable, warn caller */
1231 *(context->found_whole_row) = true;
1233 return (Node *) newvar;
1235 /* otherwise fall through to copy the var normally */
1237 else if (IsA(node, Query))
1239 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1242 context->sublevels_up++;
1243 newnode = query_tree_mutator((Query *) node,
1244 map_variable_attnos_mutator,
1247 context->sublevels_up--;
1248 return (Node *) newnode;
1250 return expression_tree_mutator(node, map_variable_attnos_mutator,
1255 map_variable_attnos(Node *node,
1256 int target_varno, int sublevels_up,
1257 const AttrNumber *attno_map, int map_length,
1258 bool *found_whole_row)
1260 map_variable_attnos_context context;
1262 context.target_varno = target_varno;
1263 context.sublevels_up = sublevels_up;
1264 context.attno_map = attno_map;
1265 context.map_length = map_length;
1266 context.found_whole_row = found_whole_row;
1268 *found_whole_row = false;
1271 * Must be prepared to start with a Query or a bare expression tree; if
1272 * it's a Query, we don't want to increment sublevels_up.
1274 return query_or_expression_tree_mutator(node,
1275 map_variable_attnos_mutator,
1282 * ReplaceVarsFromTargetList - replace Vars with items from a targetlist
1284 * Vars matching target_varno and sublevels_up are replaced by the
1285 * entry with matching resno from targetlist, if there is one.
1287 * If there is no matching resno for such a Var, the action depends on the
1289 * REPLACEVARS_REPORT_ERROR: throw an error
1290 * REPLACEVARS_CHANGE_VARNO: change Var's varno to nomatch_varno
1291 * REPLACEVARS_SUBSTITUTE_NULL: replace Var with a NULL Const of same type
1293 * The caller must also provide target_rte, the RTE describing the target
1294 * relation. This is needed to handle whole-row Vars referencing the target.
1295 * We expand such Vars into RowExpr constructs.
1297 * outer_hasSubLinks works the same as for replace_rte_variables().
1302 RangeTblEntry *target_rte;
1304 ReplaceVarsNoMatchOption nomatch_option;
1306 } ReplaceVarsFromTargetList_context;
1309 ReplaceVarsFromTargetList_callback(Var *var,
1310 replace_rte_variables_context *context)
1312 ReplaceVarsFromTargetList_context *rcon = (ReplaceVarsFromTargetList_context *) context->callback_arg;
1315 if (var->varattno == InvalidAttrNumber)
1317 /* Must expand whole-tuple reference into RowExpr */
1323 * If generating an expansion for a var of a named rowtype (ie, this
1324 * is a plain relation RTE), then we must include dummy items for
1325 * dropped columns. If the var is RECORD (ie, this is a JOIN), then
1326 * omit dropped columns. Either way, attach column names to the
1327 * RowExpr for use of ruleutils.c.
1329 expandRTE(rcon->target_rte,
1330 var->varno, var->varlevelsup, var->location,
1331 (var->vartype != RECORDOID),
1332 &colnames, &fields);
1333 /* Adjust the generated per-field Vars... */
1334 fields = (List *) replace_rte_variables_mutator((Node *) fields,
1336 rowexpr = makeNode(RowExpr);
1337 rowexpr->args = fields;
1338 rowexpr->row_typeid = var->vartype;
1339 rowexpr->row_format = COERCE_IMPLICIT_CAST;
1340 rowexpr->colnames = colnames;
1341 rowexpr->location = var->location;
1343 return (Node *) rowexpr;
1346 /* Normal case referencing one targetlist element */
1347 tle = get_tle_by_resno(rcon->targetlist, var->varattno);
1349 if (tle == NULL || tle->resjunk)
1351 /* Failed to find column in targetlist */
1352 switch (rcon->nomatch_option)
1354 case REPLACEVARS_REPORT_ERROR:
1355 /* fall through, throw error below */
1358 case REPLACEVARS_CHANGE_VARNO:
1359 var = (Var *) copyObject(var);
1360 var->varno = rcon->nomatch_varno;
1361 var->varnoold = rcon->nomatch_varno;
1362 return (Node *) var;
1364 case REPLACEVARS_SUBSTITUTE_NULL:
1367 * If Var is of domain type, we should add a CoerceToDomain
1368 * node, in case there is a NOT NULL domain constraint.
1370 return coerce_to_domain((Node *) makeNullConst(var->vartype,
1375 COERCE_IMPLICIT_CAST,
1380 elog(ERROR, "could not find replacement targetlist entry for attno %d",
1382 return NULL; /* keep compiler quiet */
1386 /* Make a copy of the tlist item to return */
1387 Node *newnode = copyObject(tle->expr);
1389 /* Must adjust varlevelsup if tlist item is from higher query */
1390 if (var->varlevelsup > 0)
1391 IncrementVarSublevelsUp(newnode, var->varlevelsup, 0);
1394 * Check to see if the tlist item contains a PARAM_MULTIEXPR Param,
1395 * and throw error if so. This case could only happen when expanding
1396 * an ON UPDATE rule's NEW variable and the referenced tlist item in
1397 * the original UPDATE command is part of a multiple assignment. There
1398 * seems no practical way to handle such cases without multiple
1399 * evaluation of the multiple assignment's sub-select, which would
1400 * create semantic oddities that users of rules would probably prefer
1401 * not to cope with. So treat it as an unimplemented feature.
1403 if (contains_multiexpr_param(newnode, NULL))
1405 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1406 errmsg("NEW variables in ON UPDATE rules cannot reference columns that are part of a multiple assignment in the subject UPDATE command")));
1413 ReplaceVarsFromTargetList(Node *node,
1414 int target_varno, int sublevels_up,
1415 RangeTblEntry *target_rte,
1417 ReplaceVarsNoMatchOption nomatch_option,
1419 bool *outer_hasSubLinks)
1421 ReplaceVarsFromTargetList_context context;
1423 context.target_rte = target_rte;
1424 context.targetlist = targetlist;
1425 context.nomatch_option = nomatch_option;
1426 context.nomatch_varno = nomatch_varno;
1428 return replace_rte_variables(node, target_varno, sublevels_up,
1429 ReplaceVarsFromTargetList_callback,