1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
10 * $PostgreSQL: pgsql/src/backend/rewrite/rewriteManip.c,v 1.116 2008/10/21 20:42:53 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "catalog/pg_type.h"
17 #include "nodes/makefuncs.h"
18 #include "nodes/nodeFuncs.h"
19 #include "optimizer/clauses.h"
20 #include "parser/parse_coerce.h"
21 #include "parser/parse_relation.h"
22 #include "parser/parsetree.h"
23 #include "rewrite/rewriteManip.h"
29 } contain_aggs_of_level_context;
35 } locate_agg_of_level_context;
37 static bool contain_aggs_of_level_walker(Node *node,
38 contain_aggs_of_level_context *context);
39 static bool locate_agg_of_level_walker(Node *node,
40 locate_agg_of_level_context *context);
41 static bool checkExprHasSubLink_walker(Node *node, void *context);
42 static Relids offset_relid_set(Relids relids, int offset);
43 static Relids adjust_relid_set(Relids relids, int oldrelid, int newrelid);
48 * Check if an expression contains an aggregate function call of the
49 * current query level.
52 checkExprHasAggs(Node *node)
54 return contain_aggs_of_level(node, 0);
58 * contain_aggs_of_level -
59 * Check if an expression contains an aggregate function call of a
60 * specified query level.
62 * The objective of this routine is to detect whether there are aggregates
63 * belonging to the given query level. Aggregates belonging to subqueries
64 * or outer queries do NOT cause a true result. We must recurse into
65 * subqueries to detect outer-reference aggregates that logically belong to
66 * the specified query level.
69 contain_aggs_of_level(Node *node, int levelsup)
71 contain_aggs_of_level_context context;
73 context.sublevels_up = levelsup;
76 * Must be prepared to start with a Query or a bare expression tree; if
77 * it's a Query, we don't want to increment sublevels_up.
79 return query_or_expression_tree_walker(node,
80 contain_aggs_of_level_walker,
86 contain_aggs_of_level_walker(Node *node,
87 contain_aggs_of_level_context *context)
91 if (IsA(node, Aggref))
93 if (((Aggref *) node)->agglevelsup == context->sublevels_up)
94 return true; /* abort the tree traversal and return true */
95 /* else fall through to examine argument */
99 /* Recurse into subselects */
102 context->sublevels_up++;
103 result = query_tree_walker((Query *) node,
104 contain_aggs_of_level_walker,
105 (void *) context, 0);
106 context->sublevels_up--;
109 return expression_tree_walker(node, contain_aggs_of_level_walker,
114 * locate_agg_of_level -
115 * Find the parse location of any aggregate of the specified query level.
117 * Returns -1 if no such agg is in the querytree, or if they all have
118 * unknown parse location. (The former case is probably caller error,
119 * but we don't bother to distinguish it from the latter case.)
121 * Note: it might seem appropriate to merge this functionality into
122 * contain_aggs_of_level, but that would complicate that function's API.
123 * Currently, the only uses of this function are for error reporting,
124 * and so shaving cycles probably isn't very important.
127 locate_agg_of_level(Node *node, int levelsup)
129 locate_agg_of_level_context context;
131 context.agg_location = -1; /* in case we find nothing */
132 context.sublevels_up = levelsup;
135 * Must be prepared to start with a Query or a bare expression tree; if
136 * it's a Query, we don't want to increment sublevels_up.
138 (void) query_or_expression_tree_walker(node,
139 locate_agg_of_level_walker,
143 return context.agg_location;
147 locate_agg_of_level_walker(Node *node,
148 locate_agg_of_level_context *context)
152 if (IsA(node, Aggref))
154 if (((Aggref *) node)->agglevelsup == context->sublevels_up &&
155 ((Aggref *) node)->location >= 0)
157 context->agg_location = ((Aggref *) node)->location;
158 return true; /* abort the tree traversal and return true */
160 /* else fall through to examine argument */
162 if (IsA(node, Query))
164 /* Recurse into subselects */
167 context->sublevels_up++;
168 result = query_tree_walker((Query *) node,
169 locate_agg_of_level_walker,
170 (void *) context, 0);
171 context->sublevels_up--;
174 return expression_tree_walker(node, locate_agg_of_level_walker,
179 * checkExprHasSubLink -
180 * Check if an expression contains a SubLink.
183 checkExprHasSubLink(Node *node)
186 * If a Query is passed, examine it --- but we should not recurse into
187 * sub-Queries that are in its rangetable or CTE list.
189 return query_or_expression_tree_walker(node,
190 checkExprHasSubLink_walker,
192 QTW_IGNORE_RC_SUBQUERIES);
196 checkExprHasSubLink_walker(Node *node, void *context)
200 if (IsA(node, SubLink))
201 return true; /* abort the tree traversal and return true */
202 return expression_tree_walker(node, checkExprHasSubLink_walker, context);
207 * OffsetVarNodes - adjust Vars when appending one query's RT to another
209 * Find all Var nodes in the given tree with varlevelsup == sublevels_up,
210 * and increment their varno fields (rangetable indexes) by 'offset'.
211 * The varnoold fields are adjusted similarly. Also, adjust other nodes
212 * that contain rangetable indexes, such as RangeTblRef and JoinExpr.
214 * NOTE: although this has the form of a walker, we cheat and modify the
215 * nodes in-place. The given expression tree should have been copied
216 * earlier to ensure that no unwanted side-effects occur!
223 } OffsetVarNodes_context;
226 OffsetVarNodes_walker(Node *node, OffsetVarNodes_context *context)
232 Var *var = (Var *) node;
234 if (var->varlevelsup == context->sublevels_up)
236 var->varno += context->offset;
237 var->varnoold += context->offset;
241 if (IsA(node, CurrentOfExpr))
243 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
245 if (context->sublevels_up == 0)
246 cexpr->cvarno += context->offset;
249 if (IsA(node, RangeTblRef))
251 RangeTblRef *rtr = (RangeTblRef *) node;
253 if (context->sublevels_up == 0)
254 rtr->rtindex += context->offset;
255 /* the subquery itself is visited separately */
258 if (IsA(node, JoinExpr))
260 JoinExpr *j = (JoinExpr *) node;
262 if (context->sublevels_up == 0)
263 j->rtindex += context->offset;
264 /* fall through to examine children */
266 if (IsA(node, FlattenedSubLink))
268 FlattenedSubLink *fslink = (FlattenedSubLink *) node;
270 if (context->sublevels_up == 0)
272 fslink->lefthand = offset_relid_set(fslink->lefthand,
274 fslink->righthand = offset_relid_set(fslink->righthand,
277 /* fall through to examine children */
279 if (IsA(node, PlaceHolderVar))
281 PlaceHolderVar *phv = (PlaceHolderVar *) node;
283 if (phv->phlevelsup == context->sublevels_up)
285 phv->phrels = offset_relid_set(phv->phrels,
288 /* fall through to examine children */
290 if (IsA(node, AppendRelInfo))
292 AppendRelInfo *appinfo = (AppendRelInfo *) node;
294 if (context->sublevels_up == 0)
296 appinfo->parent_relid += context->offset;
297 appinfo->child_relid += context->offset;
299 /* fall through to examine children */
301 if (IsA(node, PlaceHolderInfo))
303 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
305 if (context->sublevels_up == 0)
307 phinfo->ph_eval_at = offset_relid_set(phinfo->ph_eval_at,
309 phinfo->ph_needed = offset_relid_set(phinfo->ph_needed,
312 /* fall through to examine children */
314 if (IsA(node, Query))
316 /* Recurse into subselects */
319 context->sublevels_up++;
320 result = query_tree_walker((Query *) node, OffsetVarNodes_walker,
321 (void *) context, 0);
322 context->sublevels_up--;
325 return expression_tree_walker(node, OffsetVarNodes_walker,
330 OffsetVarNodes(Node *node, int offset, int sublevels_up)
332 OffsetVarNodes_context context;
334 context.offset = offset;
335 context.sublevels_up = sublevels_up;
338 * Must be prepared to start with a Query or a bare expression tree; if
339 * it's a Query, go straight to query_tree_walker to make sure that
340 * sublevels_up doesn't get incremented prematurely.
342 if (node && IsA(node, Query))
344 Query *qry = (Query *) node;
347 * If we are starting at a Query, and sublevels_up is zero, then we
348 * must also fix rangetable indexes in the Query itself --- namely
349 * resultRelation and rowMarks entries. sublevels_up cannot be zero
350 * when recursing into a subquery, so there's no need to have the same
351 * logic inside OffsetVarNodes_walker.
353 if (sublevels_up == 0)
357 if (qry->resultRelation)
358 qry->resultRelation += offset;
359 foreach(l, qry->rowMarks)
361 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
366 query_tree_walker(qry, OffsetVarNodes_walker,
367 (void *) &context, 0);
370 OffsetVarNodes_walker(node, &context);
374 offset_relid_set(Relids relids, int offset)
376 Relids result = NULL;
380 tmprelids = bms_copy(relids);
381 while ((rtindex = bms_first_member(tmprelids)) >= 0)
382 result = bms_add_member(result, rtindex + offset);
388 * ChangeVarNodes - adjust Var nodes for a specific change of RT index
390 * Find all Var nodes in the given tree belonging to a specific relation
391 * (identified by sublevels_up and rt_index), and change their varno fields
392 * to 'new_index'. The varnoold fields are changed too. Also, adjust other
393 * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
395 * NOTE: although this has the form of a walker, we cheat and modify the
396 * nodes in-place. The given expression tree should have been copied
397 * earlier to ensure that no unwanted side-effects occur!
405 } ChangeVarNodes_context;
408 ChangeVarNodes_walker(Node *node, ChangeVarNodes_context *context)
414 Var *var = (Var *) node;
416 if (var->varlevelsup == context->sublevels_up &&
417 var->varno == context->rt_index)
419 var->varno = context->new_index;
420 var->varnoold = context->new_index;
424 if (IsA(node, CurrentOfExpr))
426 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
428 if (context->sublevels_up == 0 &&
429 cexpr->cvarno == context->rt_index)
430 cexpr->cvarno = context->new_index;
433 if (IsA(node, RangeTblRef))
435 RangeTblRef *rtr = (RangeTblRef *) node;
437 if (context->sublevels_up == 0 &&
438 rtr->rtindex == context->rt_index)
439 rtr->rtindex = context->new_index;
440 /* the subquery itself is visited separately */
443 if (IsA(node, JoinExpr))
445 JoinExpr *j = (JoinExpr *) node;
447 if (context->sublevels_up == 0 &&
448 j->rtindex == context->rt_index)
449 j->rtindex = context->new_index;
450 /* fall through to examine children */
452 if (IsA(node, FlattenedSubLink))
454 FlattenedSubLink *fslink = (FlattenedSubLink *) node;
456 if (context->sublevels_up == 0)
458 fslink->lefthand = adjust_relid_set(fslink->lefthand,
461 fslink->righthand = adjust_relid_set(fslink->righthand,
465 /* fall through to examine children */
467 if (IsA(node, PlaceHolderVar))
469 PlaceHolderVar *phv = (PlaceHolderVar *) node;
471 if (phv->phlevelsup == context->sublevels_up)
473 phv->phrels = adjust_relid_set(phv->phrels,
477 /* fall through to examine children */
479 if (IsA(node, AppendRelInfo))
481 AppendRelInfo *appinfo = (AppendRelInfo *) node;
483 if (context->sublevels_up == 0)
485 if (appinfo->parent_relid == context->rt_index)
486 appinfo->parent_relid = context->new_index;
487 if (appinfo->child_relid == context->rt_index)
488 appinfo->child_relid = context->new_index;
490 /* fall through to examine children */
492 if (IsA(node, PlaceHolderInfo))
494 PlaceHolderInfo *phinfo = (PlaceHolderInfo *) node;
496 if (context->sublevels_up == 0)
498 phinfo->ph_eval_at = adjust_relid_set(phinfo->ph_eval_at,
501 phinfo->ph_needed = adjust_relid_set(phinfo->ph_needed,
505 /* fall through to examine children */
507 if (IsA(node, Query))
509 /* Recurse into subselects */
512 context->sublevels_up++;
513 result = query_tree_walker((Query *) node, ChangeVarNodes_walker,
514 (void *) context, 0);
515 context->sublevels_up--;
518 return expression_tree_walker(node, ChangeVarNodes_walker,
523 ChangeVarNodes(Node *node, int rt_index, int new_index, int sublevels_up)
525 ChangeVarNodes_context context;
527 context.rt_index = rt_index;
528 context.new_index = new_index;
529 context.sublevels_up = sublevels_up;
532 * Must be prepared to start with a Query or a bare expression tree; if
533 * it's a Query, go straight to query_tree_walker to make sure that
534 * sublevels_up doesn't get incremented prematurely.
536 if (node && IsA(node, Query))
538 Query *qry = (Query *) node;
541 * If we are starting at a Query, and sublevels_up is zero, then we
542 * must also fix rangetable indexes in the Query itself --- namely
543 * resultRelation and rowMarks entries. sublevels_up cannot be zero
544 * when recursing into a subquery, so there's no need to have the same
545 * logic inside ChangeVarNodes_walker.
547 if (sublevels_up == 0)
551 if (qry->resultRelation == rt_index)
552 qry->resultRelation = new_index;
553 foreach(l, qry->rowMarks)
555 RowMarkClause *rc = (RowMarkClause *) lfirst(l);
557 if (rc->rti == rt_index)
561 query_tree_walker(qry, ChangeVarNodes_walker,
562 (void *) &context, 0);
565 ChangeVarNodes_walker(node, &context);
569 * Substitute newrelid for oldrelid in a Relid set
572 adjust_relid_set(Relids relids, int oldrelid, int newrelid)
574 if (bms_is_member(oldrelid, relids))
576 /* Ensure we have a modifiable copy */
577 relids = bms_copy(relids);
578 /* Remove old, add new */
579 relids = bms_del_member(relids, oldrelid);
580 relids = bms_add_member(relids, newrelid);
586 * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
588 * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
589 * and add delta_sublevels_up to their varlevelsup value. This is needed when
590 * an expression that's correct for some nesting level is inserted into a
591 * subquery. Ordinarily the initial call has min_sublevels_up == 0 so that
592 * all Vars are affected. The point of min_sublevels_up is that we can
593 * increment it when we recurse into a sublink, so that local variables in
594 * that sublink are not affected, only outer references to vars that belong
595 * to the expression's original query level or parents thereof.
597 * Likewise for other nodes containing levelsup fields, such as Aggref.
599 * NOTE: although this has the form of a walker, we cheat and modify the
600 * Var nodes in-place. The given expression tree should have been copied
601 * earlier to ensure that no unwanted side-effects occur!
606 int delta_sublevels_up;
607 int min_sublevels_up;
608 } IncrementVarSublevelsUp_context;
611 IncrementVarSublevelsUp_walker(Node *node,
612 IncrementVarSublevelsUp_context *context)
618 Var *var = (Var *) node;
620 if (var->varlevelsup >= context->min_sublevels_up)
621 var->varlevelsup += context->delta_sublevels_up;
622 return false; /* done here */
624 if (IsA(node, CurrentOfExpr))
626 /* this should not happen */
627 if (context->min_sublevels_up == 0)
628 elog(ERROR, "cannot push down CurrentOfExpr");
631 if (IsA(node, Aggref))
633 Aggref *agg = (Aggref *) node;
635 if (agg->agglevelsup >= context->min_sublevels_up)
636 agg->agglevelsup += context->delta_sublevels_up;
637 /* fall through to recurse into argument */
639 if (IsA(node, PlaceHolderVar))
641 PlaceHolderVar *phv = (PlaceHolderVar *) node;
643 if (phv->phlevelsup >= context->min_sublevels_up)
644 phv->phlevelsup += context->delta_sublevels_up;
645 /* fall through to recurse into argument */
647 if (IsA(node, RangeTblEntry))
649 RangeTblEntry *rte = (RangeTblEntry *) node;
651 if (rte->rtekind == RTE_CTE)
653 if (rte->ctelevelsup >= context->min_sublevels_up)
654 rte->ctelevelsup += context->delta_sublevels_up;
656 return false; /* allow range_table_walker to continue */
658 if (IsA(node, Query))
660 /* Recurse into subselects */
663 context->min_sublevels_up++;
664 result = query_tree_walker((Query *) node,
665 IncrementVarSublevelsUp_walker,
668 context->min_sublevels_up--;
671 return expression_tree_walker(node, IncrementVarSublevelsUp_walker,
676 IncrementVarSublevelsUp(Node *node, int delta_sublevels_up,
677 int min_sublevels_up)
679 IncrementVarSublevelsUp_context context;
681 context.delta_sublevels_up = delta_sublevels_up;
682 context.min_sublevels_up = min_sublevels_up;
685 * Must be prepared to start with a Query or a bare expression tree; if
686 * it's a Query, we don't want to increment sublevels_up.
688 query_or_expression_tree_walker(node,
689 IncrementVarSublevelsUp_walker,
695 * IncrementVarSublevelsUp_rtable -
696 * Same as IncrementVarSublevelsUp, but to be invoked on a range table.
699 IncrementVarSublevelsUp_rtable(List *rtable, int delta_sublevels_up,
700 int min_sublevels_up)
702 IncrementVarSublevelsUp_context context;
704 context.delta_sublevels_up = delta_sublevels_up;
705 context.min_sublevels_up = min_sublevels_up;
707 range_table_walker(rtable,
708 IncrementVarSublevelsUp_walker,
715 * rangeTableEntry_used - detect whether an RTE is referenced somewhere
716 * in var nodes or join or setOp trees of a query or expression.
723 } rangeTableEntry_used_context;
726 rangeTableEntry_used_walker(Node *node,
727 rangeTableEntry_used_context *context)
733 Var *var = (Var *) node;
735 if (var->varlevelsup == context->sublevels_up &&
736 var->varno == context->rt_index)
740 if (IsA(node, CurrentOfExpr))
742 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
744 if (context->sublevels_up == 0 &&
745 cexpr->cvarno == context->rt_index)
749 if (IsA(node, RangeTblRef))
751 RangeTblRef *rtr = (RangeTblRef *) node;
753 if (rtr->rtindex == context->rt_index &&
754 context->sublevels_up == 0)
756 /* the subquery itself is visited separately */
759 if (IsA(node, JoinExpr))
761 JoinExpr *j = (JoinExpr *) node;
763 if (j->rtindex == context->rt_index &&
764 context->sublevels_up == 0)
766 /* fall through to examine children */
768 /* Shouldn't need to handle planner auxiliary nodes here */
769 Assert(!IsA(node, FlattenedSubLink));
770 Assert(!IsA(node, PlaceHolderVar));
771 Assert(!IsA(node, SpecialJoinInfo));
772 Assert(!IsA(node, AppendRelInfo));
773 Assert(!IsA(node, PlaceHolderInfo));
775 if (IsA(node, Query))
777 /* Recurse into subselects */
780 context->sublevels_up++;
781 result = query_tree_walker((Query *) node, rangeTableEntry_used_walker,
782 (void *) context, 0);
783 context->sublevels_up--;
786 return expression_tree_walker(node, rangeTableEntry_used_walker,
791 rangeTableEntry_used(Node *node, int rt_index, int sublevels_up)
793 rangeTableEntry_used_context context;
795 context.rt_index = rt_index;
796 context.sublevels_up = sublevels_up;
799 * Must be prepared to start with a Query or a bare expression tree; if
800 * it's a Query, we don't want to increment sublevels_up.
802 return query_or_expression_tree_walker(node,
803 rangeTableEntry_used_walker,
811 * Check if a specific attribute number of a RTE is used
812 * somewhere in the query or expression.
820 } attribute_used_context;
823 attribute_used_walker(Node *node,
824 attribute_used_context *context)
830 Var *var = (Var *) node;
832 if (var->varlevelsup == context->sublevels_up &&
833 var->varno == context->rt_index &&
834 var->varattno == context->attno)
838 if (IsA(node, Query))
840 /* Recurse into subselects */
843 context->sublevels_up++;
844 result = query_tree_walker((Query *) node, attribute_used_walker,
845 (void *) context, 0);
846 context->sublevels_up--;
849 return expression_tree_walker(node, attribute_used_walker,
854 attribute_used(Node *node, int rt_index, int attno, int sublevels_up)
856 attribute_used_context context;
858 context.rt_index = rt_index;
859 context.attno = attno;
860 context.sublevels_up = sublevels_up;
863 * Must be prepared to start with a Query or a bare expression tree; if
864 * it's a Query, we don't want to increment sublevels_up.
866 return query_or_expression_tree_walker(node,
867 attribute_used_walker,
874 * If the given Query is an INSERT ... SELECT construct, extract and
875 * return the sub-Query node that represents the SELECT part. Otherwise
876 * return the given Query.
878 * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
879 * of the link to the SELECT subquery inside parsetree, or NULL if not an
882 * This is a hack needed because transformations on INSERT ... SELECTs that
883 * appear in rule actions should be applied to the source SELECT, not to the
884 * INSERT part. Perhaps this can be cleaned up with redesigned querytrees.
887 getInsertSelectQuery(Query *parsetree, Query ***subquery_ptr)
890 RangeTblEntry *selectrte;
894 *subquery_ptr = NULL;
896 if (parsetree == NULL)
898 if (parsetree->commandType != CMD_INSERT)
902 * Currently, this is ONLY applied to rule-action queries, and so we
903 * expect to find the *OLD* and *NEW* placeholder entries in the given
904 * query. If they're not there, it must be an INSERT/SELECT in which
905 * they've been pushed down to the SELECT.
907 if (list_length(parsetree->rtable) >= 2 &&
908 strcmp(rt_fetch(PRS2_OLD_VARNO, parsetree->rtable)->eref->aliasname,
910 strcmp(rt_fetch(PRS2_NEW_VARNO, parsetree->rtable)->eref->aliasname,
913 Assert(parsetree->jointree && IsA(parsetree->jointree, FromExpr));
914 if (list_length(parsetree->jointree->fromlist) != 1)
915 elog(ERROR, "expected to find SELECT subquery");
916 rtr = (RangeTblRef *) linitial(parsetree->jointree->fromlist);
917 Assert(IsA(rtr, RangeTblRef));
918 selectrte = rt_fetch(rtr->rtindex, parsetree->rtable);
919 selectquery = selectrte->subquery;
920 if (!(selectquery && IsA(selectquery, Query) &&
921 selectquery->commandType == CMD_SELECT))
922 elog(ERROR, "expected to find SELECT subquery");
923 if (list_length(selectquery->rtable) >= 2 &&
924 strcmp(rt_fetch(PRS2_OLD_VARNO, selectquery->rtable)->eref->aliasname,
926 strcmp(rt_fetch(PRS2_NEW_VARNO, selectquery->rtable)->eref->aliasname,
930 *subquery_ptr = &(selectrte->subquery);
933 elog(ERROR, "could not find rule placeholders");
934 return NULL; /* not reached */
939 * Add the given qualifier condition to the query's WHERE clause
942 AddQual(Query *parsetree, Node *qual)
949 if (parsetree->commandType == CMD_UTILITY)
952 * There's noplace to put the qual on a utility statement.
954 * If it's a NOTIFY, silently ignore the qual; this means that the
955 * NOTIFY will execute, whether or not there are any qualifying rows.
956 * While clearly wrong, this is much more useful than refusing to
957 * execute the rule at all, and extra NOTIFY events are harmless for
958 * typical uses of NOTIFY.
960 * If it isn't a NOTIFY, error out, since unconditional execution of
961 * other utility stmts is unlikely to be wanted. (This case is not
962 * currently allowed anyway, but keep the test for safety.)
964 if (parsetree->utilityStmt && IsA(parsetree->utilityStmt, NotifyStmt))
968 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
969 errmsg("conditional utility statements are not implemented")));
972 if (parsetree->setOperations != NULL)
975 * There's noplace to put the qual on a setop statement, either. (This
976 * could be fixed, but right now the planner simply ignores any qual
977 * condition on a setop query.)
980 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
981 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
984 /* INTERSECT want's the original, but we need to copy - Jan */
985 copy = copyObject(qual);
987 parsetree->jointree->quals = make_and_qual(parsetree->jointree->quals,
991 * We had better not have stuck an aggregate into the WHERE clause.
993 Assert(!checkExprHasAggs(copy));
996 * Make sure query is marked correctly if added qual has sublinks. Need
997 * not search qual when query is already marked.
999 if (!parsetree->hasSubLinks)
1000 parsetree->hasSubLinks = checkExprHasSubLink(copy);
1005 * Invert the given clause and add it to the WHERE qualifications of the
1006 * given querytree. Inversion means "x IS NOT TRUE", not just "NOT x",
1007 * else we will do the wrong thing when x evaluates to NULL.
1010 AddInvertedQual(Query *parsetree, Node *qual)
1012 BooleanTest *invqual;
1017 /* Need not copy input qual, because AddQual will... */
1018 invqual = makeNode(BooleanTest);
1019 invqual->arg = (Expr *) qual;
1020 invqual->booltesttype = IS_NOT_TRUE;
1022 AddQual(parsetree, (Node *) invqual);
1027 * ResolveNew - replace Vars with corresponding items from a targetlist
1029 * Vars matching target_varno and sublevels_up are replaced by the
1030 * entry with matching resno from targetlist, if there is one.
1031 * If not, we either change the unmatched Var's varno to update_varno
1032 * (when event == CMD_UPDATE) or replace it with a constant NULL.
1034 * The caller must also provide target_rte, the RTE describing the target
1035 * relation. This is needed to handle whole-row Vars referencing the target.
1036 * We expand such Vars into RowExpr constructs.
1038 * Note: the business with inserted_sublink is needed to update hasSubLinks
1039 * in subqueries when the replacement adds a subquery inside a subquery.
1040 * Messy, isn't it? We do not need to do similar pushups for hasAggs,
1041 * because it isn't possible for this transformation to insert a level-zero
1042 * aggregate reference into a subquery --- it could only insert outer aggs.
1049 RangeTblEntry *target_rte;
1053 bool inserted_sublink;
1054 } ResolveNew_context;
1057 resolve_one_var(Var *var, ResolveNew_context *context)
1061 tle = get_tle_by_resno(context->targetlist, var->varattno);
1065 /* Failed to find column in insert/update tlist */
1066 if (context->event == CMD_UPDATE)
1068 /* For update, just change unmatched var's varno */
1069 var = (Var *) copyObject(var);
1070 var->varno = context->update_varno;
1071 var->varnoold = context->update_varno;
1072 return (Node *) var;
1076 /* Otherwise replace unmatched var with a null */
1077 /* need coerce_to_domain in case of NOT NULL domain constraint */
1078 return coerce_to_domain((Node *) makeNullConst(var->vartype,
1082 COERCE_IMPLICIT_CAST,
1090 /* Make a copy of the tlist item to return */
1091 Node *n = copyObject(tle->expr);
1093 /* Adjust varlevelsup if tlist item is from higher query */
1094 if (var->varlevelsup > 0)
1095 IncrementVarSublevelsUp(n, var->varlevelsup, 0);
1096 /* Report it if we are adding a sublink to query */
1097 if (!context->inserted_sublink)
1098 context->inserted_sublink = checkExprHasSubLink(n);
1104 ResolveNew_mutator(Node *node, ResolveNew_context *context)
1110 Var *var = (Var *) node;
1111 int this_varno = (int) var->varno;
1112 int this_varlevelsup = (int) var->varlevelsup;
1114 if (this_varno == context->target_varno &&
1115 this_varlevelsup == context->sublevels_up)
1117 if (var->varattno == InvalidAttrNumber)
1119 /* Must expand whole-tuple reference into RowExpr */
1125 * If generating an expansion for a var of a named rowtype
1126 * (ie, this is a plain relation RTE), then we must include
1127 * dummy items for dropped columns. If the var is RECORD (ie,
1128 * this is a JOIN), then omit dropped columns. Either way,
1129 * attach column names to the RowExpr for use of ruleutils.c.
1131 expandRTE(context->target_rte,
1132 this_varno, this_varlevelsup, var->location,
1133 (var->vartype != RECORDOID),
1134 &colnames, &fields);
1135 /* Adjust the generated per-field Vars... */
1136 fields = (List *) ResolveNew_mutator((Node *) fields,
1138 rowexpr = makeNode(RowExpr);
1139 rowexpr->args = fields;
1140 rowexpr->row_typeid = var->vartype;
1141 rowexpr->row_format = COERCE_IMPLICIT_CAST;
1142 rowexpr->colnames = colnames;
1143 rowexpr->location = -1;
1145 return (Node *) rowexpr;
1148 /* Normal case for scalar variable */
1149 return resolve_one_var(var, context);
1151 /* otherwise fall through to copy the var normally */
1153 else if (IsA(node, CurrentOfExpr))
1155 CurrentOfExpr *cexpr = (CurrentOfExpr *) node;
1156 int this_varno = (int) cexpr->cvarno;
1158 if (this_varno == context->target_varno &&
1159 context->sublevels_up == 0)
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.
1168 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1169 errmsg("WHERE CURRENT OF on a view is not implemented")));
1171 /* otherwise fall through to copy the expr normally */
1173 else if (IsA(node, Query))
1175 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1177 bool save_inserted_sublink;
1179 context->sublevels_up++;
1180 save_inserted_sublink = context->inserted_sublink;
1181 context->inserted_sublink = false;
1182 newnode = query_tree_mutator((Query *) node,
1186 newnode->hasSubLinks |= context->inserted_sublink;
1187 context->inserted_sublink = save_inserted_sublink;
1188 context->sublevels_up--;
1189 return (Node *) newnode;
1191 return expression_tree_mutator(node, ResolveNew_mutator,
1196 ResolveNew(Node *node, int target_varno, int sublevels_up,
1197 RangeTblEntry *target_rte,
1198 List *targetlist, int event, int update_varno)
1201 ResolveNew_context context;
1203 context.target_varno = target_varno;
1204 context.sublevels_up = sublevels_up;
1205 context.target_rte = target_rte;
1206 context.targetlist = targetlist;
1207 context.event = event;
1208 context.update_varno = update_varno;
1209 context.inserted_sublink = false;
1212 * Must be prepared to start with a Query or a bare expression tree; if
1213 * it's a Query, we don't want to increment sublevels_up.
1215 result = query_or_expression_tree_mutator(node,
1220 if (context.inserted_sublink)
1222 if (IsA(result, Query))
1223 ((Query *) result)->hasSubLinks = true;
1226 * Note: if we're called on a non-Query node then it's the caller's
1227 * responsibility to update hasSubLinks in the ancestor Query. This is
1228 * pretty fragile and perhaps should be rethought ...