1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
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 /* Shouldn't need to handle other planner auxiliary nodes here */
302 Assert(!IsA(node
, SpecialJoinInfo
));
303 Assert(!IsA(node
, PlaceHolderInfo
));
305 if (IsA(node
, Query
))
307 /* Recurse into subselects */
310 context
->sublevels_up
++;
311 result
= query_tree_walker((Query
*) node
, OffsetVarNodes_walker
,
312 (void *) context
, 0);
313 context
->sublevels_up
--;
316 return expression_tree_walker(node
, OffsetVarNodes_walker
,
321 OffsetVarNodes(Node
*node
, int offset
, int sublevels_up
)
323 OffsetVarNodes_context context
;
325 context
.offset
= offset
;
326 context
.sublevels_up
= sublevels_up
;
329 * Must be prepared to start with a Query or a bare expression tree; if
330 * it's a Query, go straight to query_tree_walker to make sure that
331 * sublevels_up doesn't get incremented prematurely.
333 if (node
&& IsA(node
, Query
))
335 Query
*qry
= (Query
*) node
;
338 * If we are starting at a Query, and sublevels_up is zero, then we
339 * must also fix rangetable indexes in the Query itself --- namely
340 * resultRelation and rowMarks entries. sublevels_up cannot be zero
341 * when recursing into a subquery, so there's no need to have the same
342 * logic inside OffsetVarNodes_walker.
344 if (sublevels_up
== 0)
348 if (qry
->resultRelation
)
349 qry
->resultRelation
+= offset
;
350 foreach(l
, qry
->rowMarks
)
352 RowMarkClause
*rc
= (RowMarkClause
*) lfirst(l
);
357 query_tree_walker(qry
, OffsetVarNodes_walker
,
358 (void *) &context
, 0);
361 OffsetVarNodes_walker(node
, &context
);
365 offset_relid_set(Relids relids
, int offset
)
367 Relids result
= NULL
;
371 tmprelids
= bms_copy(relids
);
372 while ((rtindex
= bms_first_member(tmprelids
)) >= 0)
373 result
= bms_add_member(result
, rtindex
+ offset
);
379 * ChangeVarNodes - adjust Var nodes for a specific change of RT index
381 * Find all Var nodes in the given tree belonging to a specific relation
382 * (identified by sublevels_up and rt_index), and change their varno fields
383 * to 'new_index'. The varnoold fields are changed too. Also, adjust other
384 * nodes that contain rangetable indexes, such as RangeTblRef and JoinExpr.
386 * NOTE: although this has the form of a walker, we cheat and modify the
387 * nodes in-place. The given expression tree should have been copied
388 * earlier to ensure that no unwanted side-effects occur!
396 } ChangeVarNodes_context
;
399 ChangeVarNodes_walker(Node
*node
, ChangeVarNodes_context
*context
)
405 Var
*var
= (Var
*) node
;
407 if (var
->varlevelsup
== context
->sublevels_up
&&
408 var
->varno
== context
->rt_index
)
410 var
->varno
= context
->new_index
;
411 var
->varnoold
= context
->new_index
;
415 if (IsA(node
, CurrentOfExpr
))
417 CurrentOfExpr
*cexpr
= (CurrentOfExpr
*) node
;
419 if (context
->sublevels_up
== 0 &&
420 cexpr
->cvarno
== context
->rt_index
)
421 cexpr
->cvarno
= context
->new_index
;
424 if (IsA(node
, RangeTblRef
))
426 RangeTblRef
*rtr
= (RangeTblRef
*) node
;
428 if (context
->sublevels_up
== 0 &&
429 rtr
->rtindex
== context
->rt_index
)
430 rtr
->rtindex
= context
->new_index
;
431 /* the subquery itself is visited separately */
434 if (IsA(node
, JoinExpr
))
436 JoinExpr
*j
= (JoinExpr
*) node
;
438 if (context
->sublevels_up
== 0 &&
439 j
->rtindex
== context
->rt_index
)
440 j
->rtindex
= context
->new_index
;
441 /* fall through to examine children */
443 if (IsA(node
, FlattenedSubLink
))
445 FlattenedSubLink
*fslink
= (FlattenedSubLink
*) node
;
447 if (context
->sublevels_up
== 0)
449 fslink
->lefthand
= adjust_relid_set(fslink
->lefthand
,
452 fslink
->righthand
= adjust_relid_set(fslink
->righthand
,
456 /* fall through to examine children */
458 if (IsA(node
, PlaceHolderVar
))
460 PlaceHolderVar
*phv
= (PlaceHolderVar
*) node
;
462 if (phv
->phlevelsup
== context
->sublevels_up
)
464 phv
->phrels
= adjust_relid_set(phv
->phrels
,
468 /* fall through to examine children */
470 if (IsA(node
, AppendRelInfo
))
472 AppendRelInfo
*appinfo
= (AppendRelInfo
*) node
;
474 if (context
->sublevels_up
== 0)
476 if (appinfo
->parent_relid
== context
->rt_index
)
477 appinfo
->parent_relid
= context
->new_index
;
478 if (appinfo
->child_relid
== context
->rt_index
)
479 appinfo
->child_relid
= context
->new_index
;
481 /* fall through to examine children */
483 /* Shouldn't need to handle other planner auxiliary nodes here */
484 Assert(!IsA(node
, SpecialJoinInfo
));
485 Assert(!IsA(node
, PlaceHolderInfo
));
487 if (IsA(node
, Query
))
489 /* Recurse into subselects */
492 context
->sublevels_up
++;
493 result
= query_tree_walker((Query
*) node
, ChangeVarNodes_walker
,
494 (void *) context
, 0);
495 context
->sublevels_up
--;
498 return expression_tree_walker(node
, ChangeVarNodes_walker
,
503 ChangeVarNodes(Node
*node
, int rt_index
, int new_index
, int sublevels_up
)
505 ChangeVarNodes_context context
;
507 context
.rt_index
= rt_index
;
508 context
.new_index
= new_index
;
509 context
.sublevels_up
= sublevels_up
;
512 * Must be prepared to start with a Query or a bare expression tree; if
513 * it's a Query, go straight to query_tree_walker to make sure that
514 * sublevels_up doesn't get incremented prematurely.
516 if (node
&& IsA(node
, Query
))
518 Query
*qry
= (Query
*) node
;
521 * If we are starting at a Query, and sublevels_up is zero, then we
522 * must also fix rangetable indexes in the Query itself --- namely
523 * resultRelation and rowMarks entries. sublevels_up cannot be zero
524 * when recursing into a subquery, so there's no need to have the same
525 * logic inside ChangeVarNodes_walker.
527 if (sublevels_up
== 0)
531 if (qry
->resultRelation
== rt_index
)
532 qry
->resultRelation
= new_index
;
533 foreach(l
, qry
->rowMarks
)
535 RowMarkClause
*rc
= (RowMarkClause
*) lfirst(l
);
537 if (rc
->rti
== rt_index
)
541 query_tree_walker(qry
, ChangeVarNodes_walker
,
542 (void *) &context
, 0);
545 ChangeVarNodes_walker(node
, &context
);
549 * Substitute newrelid for oldrelid in a Relid set
552 adjust_relid_set(Relids relids
, int oldrelid
, int newrelid
)
554 if (bms_is_member(oldrelid
, relids
))
556 /* Ensure we have a modifiable copy */
557 relids
= bms_copy(relids
);
558 /* Remove old, add new */
559 relids
= bms_del_member(relids
, oldrelid
);
560 relids
= bms_add_member(relids
, newrelid
);
566 * IncrementVarSublevelsUp - adjust Var nodes when pushing them down in tree
568 * Find all Var nodes in the given tree having varlevelsup >= min_sublevels_up,
569 * and add delta_sublevels_up to their varlevelsup value. This is needed when
570 * an expression that's correct for some nesting level is inserted into a
571 * subquery. Ordinarily the initial call has min_sublevels_up == 0 so that
572 * all Vars are affected. The point of min_sublevels_up is that we can
573 * increment it when we recurse into a sublink, so that local variables in
574 * that sublink are not affected, only outer references to vars that belong
575 * to the expression's original query level or parents thereof.
577 * Likewise for other nodes containing levelsup fields, such as Aggref.
579 * NOTE: although this has the form of a walker, we cheat and modify the
580 * Var nodes in-place. The given expression tree should have been copied
581 * earlier to ensure that no unwanted side-effects occur!
586 int delta_sublevels_up
;
587 int min_sublevels_up
;
588 } IncrementVarSublevelsUp_context
;
591 IncrementVarSublevelsUp_walker(Node
*node
,
592 IncrementVarSublevelsUp_context
*context
)
598 Var
*var
= (Var
*) node
;
600 if (var
->varlevelsup
>= context
->min_sublevels_up
)
601 var
->varlevelsup
+= context
->delta_sublevels_up
;
602 return false; /* done here */
604 if (IsA(node
, CurrentOfExpr
))
606 /* this should not happen */
607 if (context
->min_sublevels_up
== 0)
608 elog(ERROR
, "cannot push down CurrentOfExpr");
611 if (IsA(node
, Aggref
))
613 Aggref
*agg
= (Aggref
*) node
;
615 if (agg
->agglevelsup
>= context
->min_sublevels_up
)
616 agg
->agglevelsup
+= context
->delta_sublevels_up
;
617 /* fall through to recurse into argument */
619 if (IsA(node
, PlaceHolderVar
))
621 PlaceHolderVar
*phv
= (PlaceHolderVar
*) node
;
623 if (phv
->phlevelsup
>= context
->min_sublevels_up
)
624 phv
->phlevelsup
+= context
->delta_sublevels_up
;
625 /* fall through to recurse into argument */
627 if (IsA(node
, RangeTblEntry
))
629 RangeTblEntry
*rte
= (RangeTblEntry
*) node
;
631 if (rte
->rtekind
== RTE_CTE
)
633 if (rte
->ctelevelsup
>= context
->min_sublevels_up
)
634 rte
->ctelevelsup
+= context
->delta_sublevels_up
;
636 return false; /* allow range_table_walker to continue */
638 if (IsA(node
, Query
))
640 /* Recurse into subselects */
643 context
->min_sublevels_up
++;
644 result
= query_tree_walker((Query
*) node
,
645 IncrementVarSublevelsUp_walker
,
648 context
->min_sublevels_up
--;
651 return expression_tree_walker(node
, IncrementVarSublevelsUp_walker
,
656 IncrementVarSublevelsUp(Node
*node
, int delta_sublevels_up
,
657 int min_sublevels_up
)
659 IncrementVarSublevelsUp_context context
;
661 context
.delta_sublevels_up
= delta_sublevels_up
;
662 context
.min_sublevels_up
= min_sublevels_up
;
665 * Must be prepared to start with a Query or a bare expression tree; if
666 * it's a Query, we don't want to increment sublevels_up.
668 query_or_expression_tree_walker(node
,
669 IncrementVarSublevelsUp_walker
,
675 * IncrementVarSublevelsUp_rtable -
676 * Same as IncrementVarSublevelsUp, but to be invoked on a range table.
679 IncrementVarSublevelsUp_rtable(List
*rtable
, int delta_sublevels_up
,
680 int min_sublevels_up
)
682 IncrementVarSublevelsUp_context context
;
684 context
.delta_sublevels_up
= delta_sublevels_up
;
685 context
.min_sublevels_up
= min_sublevels_up
;
687 range_table_walker(rtable
,
688 IncrementVarSublevelsUp_walker
,
695 * rangeTableEntry_used - detect whether an RTE is referenced somewhere
696 * in var nodes or join or setOp trees of a query or expression.
703 } rangeTableEntry_used_context
;
706 rangeTableEntry_used_walker(Node
*node
,
707 rangeTableEntry_used_context
*context
)
713 Var
*var
= (Var
*) node
;
715 if (var
->varlevelsup
== context
->sublevels_up
&&
716 var
->varno
== context
->rt_index
)
720 if (IsA(node
, CurrentOfExpr
))
722 CurrentOfExpr
*cexpr
= (CurrentOfExpr
*) node
;
724 if (context
->sublevels_up
== 0 &&
725 cexpr
->cvarno
== context
->rt_index
)
729 if (IsA(node
, RangeTblRef
))
731 RangeTblRef
*rtr
= (RangeTblRef
*) node
;
733 if (rtr
->rtindex
== context
->rt_index
&&
734 context
->sublevels_up
== 0)
736 /* the subquery itself is visited separately */
739 if (IsA(node
, JoinExpr
))
741 JoinExpr
*j
= (JoinExpr
*) node
;
743 if (j
->rtindex
== context
->rt_index
&&
744 context
->sublevels_up
== 0)
746 /* fall through to examine children */
748 /* Shouldn't need to handle planner auxiliary nodes here */
749 Assert(!IsA(node
, FlattenedSubLink
));
750 Assert(!IsA(node
, PlaceHolderVar
));
751 Assert(!IsA(node
, SpecialJoinInfo
));
752 Assert(!IsA(node
, AppendRelInfo
));
753 Assert(!IsA(node
, PlaceHolderInfo
));
755 if (IsA(node
, Query
))
757 /* Recurse into subselects */
760 context
->sublevels_up
++;
761 result
= query_tree_walker((Query
*) node
, rangeTableEntry_used_walker
,
762 (void *) context
, 0);
763 context
->sublevels_up
--;
766 return expression_tree_walker(node
, rangeTableEntry_used_walker
,
771 rangeTableEntry_used(Node
*node
, int rt_index
, int sublevels_up
)
773 rangeTableEntry_used_context context
;
775 context
.rt_index
= rt_index
;
776 context
.sublevels_up
= sublevels_up
;
779 * Must be prepared to start with a Query or a bare expression tree; if
780 * it's a Query, we don't want to increment sublevels_up.
782 return query_or_expression_tree_walker(node
,
783 rangeTableEntry_used_walker
,
791 * Check if a specific attribute number of a RTE is used
792 * somewhere in the query or expression.
800 } attribute_used_context
;
803 attribute_used_walker(Node
*node
,
804 attribute_used_context
*context
)
810 Var
*var
= (Var
*) node
;
812 if (var
->varlevelsup
== context
->sublevels_up
&&
813 var
->varno
== context
->rt_index
&&
814 var
->varattno
== context
->attno
)
818 if (IsA(node
, Query
))
820 /* Recurse into subselects */
823 context
->sublevels_up
++;
824 result
= query_tree_walker((Query
*) node
, attribute_used_walker
,
825 (void *) context
, 0);
826 context
->sublevels_up
--;
829 return expression_tree_walker(node
, attribute_used_walker
,
834 attribute_used(Node
*node
, int rt_index
, int attno
, int sublevels_up
)
836 attribute_used_context context
;
838 context
.rt_index
= rt_index
;
839 context
.attno
= attno
;
840 context
.sublevels_up
= sublevels_up
;
843 * Must be prepared to start with a Query or a bare expression tree; if
844 * it's a Query, we don't want to increment sublevels_up.
846 return query_or_expression_tree_walker(node
,
847 attribute_used_walker
,
854 * If the given Query is an INSERT ... SELECT construct, extract and
855 * return the sub-Query node that represents the SELECT part. Otherwise
856 * return the given Query.
858 * If subquery_ptr is not NULL, then *subquery_ptr is set to the location
859 * of the link to the SELECT subquery inside parsetree, or NULL if not an
862 * This is a hack needed because transformations on INSERT ... SELECTs that
863 * appear in rule actions should be applied to the source SELECT, not to the
864 * INSERT part. Perhaps this can be cleaned up with redesigned querytrees.
867 getInsertSelectQuery(Query
*parsetree
, Query
***subquery_ptr
)
870 RangeTblEntry
*selectrte
;
874 *subquery_ptr
= NULL
;
876 if (parsetree
== NULL
)
878 if (parsetree
->commandType
!= CMD_INSERT
)
882 * Currently, this is ONLY applied to rule-action queries, and so we
883 * expect to find the *OLD* and *NEW* placeholder entries in the given
884 * query. If they're not there, it must be an INSERT/SELECT in which
885 * they've been pushed down to the SELECT.
887 if (list_length(parsetree
->rtable
) >= 2 &&
888 strcmp(rt_fetch(PRS2_OLD_VARNO
, parsetree
->rtable
)->eref
->aliasname
,
890 strcmp(rt_fetch(PRS2_NEW_VARNO
, parsetree
->rtable
)->eref
->aliasname
,
893 Assert(parsetree
->jointree
&& IsA(parsetree
->jointree
, FromExpr
));
894 if (list_length(parsetree
->jointree
->fromlist
) != 1)
895 elog(ERROR
, "expected to find SELECT subquery");
896 rtr
= (RangeTblRef
*) linitial(parsetree
->jointree
->fromlist
);
897 Assert(IsA(rtr
, RangeTblRef
));
898 selectrte
= rt_fetch(rtr
->rtindex
, parsetree
->rtable
);
899 selectquery
= selectrte
->subquery
;
900 if (!(selectquery
&& IsA(selectquery
, Query
) &&
901 selectquery
->commandType
== CMD_SELECT
))
902 elog(ERROR
, "expected to find SELECT subquery");
903 if (list_length(selectquery
->rtable
) >= 2 &&
904 strcmp(rt_fetch(PRS2_OLD_VARNO
, selectquery
->rtable
)->eref
->aliasname
,
906 strcmp(rt_fetch(PRS2_NEW_VARNO
, selectquery
->rtable
)->eref
->aliasname
,
910 *subquery_ptr
= &(selectrte
->subquery
);
913 elog(ERROR
, "could not find rule placeholders");
914 return NULL
; /* not reached */
919 * Add the given qualifier condition to the query's WHERE clause
922 AddQual(Query
*parsetree
, Node
*qual
)
929 if (parsetree
->commandType
== CMD_UTILITY
)
932 * There's noplace to put the qual on a utility statement.
934 * If it's a NOTIFY, silently ignore the qual; this means that the
935 * NOTIFY will execute, whether or not there are any qualifying rows.
936 * While clearly wrong, this is much more useful than refusing to
937 * execute the rule at all, and extra NOTIFY events are harmless for
938 * typical uses of NOTIFY.
940 * If it isn't a NOTIFY, error out, since unconditional execution of
941 * other utility stmts is unlikely to be wanted. (This case is not
942 * currently allowed anyway, but keep the test for safety.)
944 if (parsetree
->utilityStmt
&& IsA(parsetree
->utilityStmt
, NotifyStmt
))
948 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
949 errmsg("conditional utility statements are not implemented")));
952 if (parsetree
->setOperations
!= NULL
)
955 * There's noplace to put the qual on a setop statement, either. (This
956 * could be fixed, but right now the planner simply ignores any qual
957 * condition on a setop query.)
960 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
961 errmsg("conditional UNION/INTERSECT/EXCEPT statements are not implemented")));
964 /* INTERSECT want's the original, but we need to copy - Jan */
965 copy
= copyObject(qual
);
967 parsetree
->jointree
->quals
= make_and_qual(parsetree
->jointree
->quals
,
971 * We had better not have stuck an aggregate into the WHERE clause.
973 Assert(!checkExprHasAggs(copy
));
976 * Make sure query is marked correctly if added qual has sublinks. Need
977 * not search qual when query is already marked.
979 if (!parsetree
->hasSubLinks
)
980 parsetree
->hasSubLinks
= checkExprHasSubLink(copy
);
985 * Invert the given clause and add it to the WHERE qualifications of the
986 * given querytree. Inversion means "x IS NOT TRUE", not just "NOT x",
987 * else we will do the wrong thing when x evaluates to NULL.
990 AddInvertedQual(Query
*parsetree
, Node
*qual
)
992 BooleanTest
*invqual
;
997 /* Need not copy input qual, because AddQual will... */
998 invqual
= makeNode(BooleanTest
);
999 invqual
->arg
= (Expr
*) qual
;
1000 invqual
->booltesttype
= IS_NOT_TRUE
;
1002 AddQual(parsetree
, (Node
*) invqual
);
1007 * ResolveNew - replace Vars with corresponding items from a targetlist
1009 * Vars matching target_varno and sublevels_up are replaced by the
1010 * entry with matching resno from targetlist, if there is one.
1011 * If not, we either change the unmatched Var's varno to update_varno
1012 * (when event == CMD_UPDATE) or replace it with a constant NULL.
1014 * The caller must also provide target_rte, the RTE describing the target
1015 * relation. This is needed to handle whole-row Vars referencing the target.
1016 * We expand such Vars into RowExpr constructs.
1018 * Note: the business with inserted_sublink is needed to update hasSubLinks
1019 * in subqueries when the replacement adds a subquery inside a subquery.
1020 * Messy, isn't it? We do not need to do similar pushups for hasAggs,
1021 * because it isn't possible for this transformation to insert a level-zero
1022 * aggregate reference into a subquery --- it could only insert outer aggs.
1029 RangeTblEntry
*target_rte
;
1033 bool inserted_sublink
;
1034 } ResolveNew_context
;
1037 resolve_one_var(Var
*var
, ResolveNew_context
*context
)
1041 tle
= get_tle_by_resno(context
->targetlist
, var
->varattno
);
1045 /* Failed to find column in insert/update tlist */
1046 if (context
->event
== CMD_UPDATE
)
1048 /* For update, just change unmatched var's varno */
1049 var
= (Var
*) copyObject(var
);
1050 var
->varno
= context
->update_varno
;
1051 var
->varnoold
= context
->update_varno
;
1052 return (Node
*) var
;
1056 /* Otherwise replace unmatched var with a null */
1057 /* need coerce_to_domain in case of NOT NULL domain constraint */
1058 return coerce_to_domain((Node
*) makeNullConst(var
->vartype
,
1062 COERCE_IMPLICIT_CAST
,
1070 /* Make a copy of the tlist item to return */
1071 Node
*n
= copyObject(tle
->expr
);
1073 /* Adjust varlevelsup if tlist item is from higher query */
1074 if (var
->varlevelsup
> 0)
1075 IncrementVarSublevelsUp(n
, var
->varlevelsup
, 0);
1076 /* Report it if we are adding a sublink to query */
1077 if (!context
->inserted_sublink
)
1078 context
->inserted_sublink
= checkExprHasSubLink(n
);
1084 ResolveNew_mutator(Node
*node
, ResolveNew_context
*context
)
1090 Var
*var
= (Var
*) node
;
1091 int this_varno
= (int) var
->varno
;
1092 int this_varlevelsup
= (int) var
->varlevelsup
;
1094 if (this_varno
== context
->target_varno
&&
1095 this_varlevelsup
== context
->sublevels_up
)
1097 if (var
->varattno
== InvalidAttrNumber
)
1099 /* Must expand whole-tuple reference into RowExpr */
1105 * If generating an expansion for a var of a named rowtype
1106 * (ie, this is a plain relation RTE), then we must include
1107 * dummy items for dropped columns. If the var is RECORD (ie,
1108 * this is a JOIN), then omit dropped columns. Either way,
1109 * attach column names to the RowExpr for use of ruleutils.c.
1111 expandRTE(context
->target_rte
,
1112 this_varno
, this_varlevelsup
, var
->location
,
1113 (var
->vartype
!= RECORDOID
),
1114 &colnames
, &fields
);
1115 /* Adjust the generated per-field Vars... */
1116 fields
= (List
*) ResolveNew_mutator((Node
*) fields
,
1118 rowexpr
= makeNode(RowExpr
);
1119 rowexpr
->args
= fields
;
1120 rowexpr
->row_typeid
= var
->vartype
;
1121 rowexpr
->row_format
= COERCE_IMPLICIT_CAST
;
1122 rowexpr
->colnames
= colnames
;
1123 rowexpr
->location
= -1;
1125 return (Node
*) rowexpr
;
1128 /* Normal case for scalar variable */
1129 return resolve_one_var(var
, context
);
1131 /* otherwise fall through to copy the var normally */
1133 else if (IsA(node
, CurrentOfExpr
))
1135 CurrentOfExpr
*cexpr
= (CurrentOfExpr
*) node
;
1136 int this_varno
= (int) cexpr
->cvarno
;
1138 if (this_varno
== context
->target_varno
&&
1139 context
->sublevels_up
== 0)
1142 * We get here if a WHERE CURRENT OF expression turns out to apply
1143 * to a view. Someday we might be able to translate the
1144 * expression to apply to an underlying table of the view, but
1145 * right now it's not implemented.
1148 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED
),
1149 errmsg("WHERE CURRENT OF on a view is not implemented")));
1151 /* otherwise fall through to copy the expr normally */
1153 else if (IsA(node
, Query
))
1155 /* Recurse into RTE subquery or not-yet-planned sublink subquery */
1157 bool save_inserted_sublink
;
1159 context
->sublevels_up
++;
1160 save_inserted_sublink
= context
->inserted_sublink
;
1161 context
->inserted_sublink
= false;
1162 newnode
= query_tree_mutator((Query
*) node
,
1166 newnode
->hasSubLinks
|= context
->inserted_sublink
;
1167 context
->inserted_sublink
= save_inserted_sublink
;
1168 context
->sublevels_up
--;
1169 return (Node
*) newnode
;
1171 return expression_tree_mutator(node
, ResolveNew_mutator
,
1176 ResolveNew(Node
*node
, int target_varno
, int sublevels_up
,
1177 RangeTblEntry
*target_rte
,
1178 List
*targetlist
, int event
, int update_varno
)
1181 ResolveNew_context context
;
1183 context
.target_varno
= target_varno
;
1184 context
.sublevels_up
= sublevels_up
;
1185 context
.target_rte
= target_rte
;
1186 context
.targetlist
= targetlist
;
1187 context
.event
= event
;
1188 context
.update_varno
= update_varno
;
1189 context
.inserted_sublink
= false;
1192 * Must be prepared to start with a Query or a bare expression tree; if
1193 * it's a Query, we don't want to increment sublevels_up.
1195 result
= query_or_expression_tree_mutator(node
,
1200 if (context
.inserted_sublink
)
1202 if (IsA(result
, Query
))
1203 ((Query
*) result
)->hasSubLinks
= true;
1206 * Note: if we're called on a non-Query node then it's the caller's
1207 * responsibility to update hasSubLinks in the ancestor Query. This is
1208 * pretty fragile and perhaps should be rethought ...