1 /*-------------------------------------------------------------------------
5 * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
6 * Portions Copyright (c) 1994, Regents of the University of California
10 * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteHandler.c,v 1.89 2001/01/27 04:40:59 tgl Exp $
12 *-------------------------------------------------------------------------
16 #include "access/heapam.h"
17 #include "catalog/pg_operator.h"
18 #include "catalog/pg_type.h"
19 #include "miscadmin.h"
20 #include "nodes/makefuncs.h"
21 #include "optimizer/clauses.h"
22 #include "optimizer/prep.h"
23 #include "optimizer/var.h"
24 #include "parser/analyze.h"
25 #include "parser/parse_expr.h"
26 #include "parser/parse_oper.h"
27 #include "parser/parse_target.h"
28 #include "parser/parsetree.h"
29 #include "parser/parse_type.h"
30 #include "rewrite/rewriteManip.h"
31 #include "utils/lsyscache.h"
34 static RewriteInfo *gatherRewriteMeta(Query *parsetree,
40 static List *adjustJoinTreeList(Query *parsetree, bool removert, int rt_index);
41 static void markQueryForUpdate(Query *qry, bool skipOldNew);
42 static List *matchLocks(CmdType event, RuleLock *rulelocks,
43 int varno, Query *parsetree);
44 static Query *fireRIRrules(Query *parsetree);
49 * Gather meta information about parsetree, and rule. Fix rule body
50 * and qualifier so that they can be mixed with the parsetree and
51 * maintain semantic validity
54 gatherRewriteMeta(Query *parsetree,
63 Query **sub_action_ptr;
66 info = (RewriteInfo *) palloc(sizeof(RewriteInfo));
67 info->rt_index = rt_index;
69 info->instead_flag = instead_flag;
70 info->rule_action = (Query *) copyObject(rule_action);
71 info->rule_qual = (Node *) copyObject(rule_qual);
72 if (info->rule_action == NULL)
77 info->nothing = FALSE;
78 info->action = info->rule_action->commandType;
79 info->current_varno = rt_index;
80 rt_length = length(parsetree->rtable);
81 info->new_varno = PRS2_NEW_VARNO + rt_length;
84 * Adjust rule action and qual to offset its varnos, so that we can
85 * merge its rtable into the main parsetree's rtable.
87 * If the rule action is an INSERT...SELECT, the OLD/NEW rtable
88 * entries will be in the SELECT part, and we have to modify that
89 * rather than the top-level INSERT (kluge!).
91 sub_action = getInsertSelectQuery(info->rule_action, &sub_action_ptr);
93 OffsetVarNodes((Node *) sub_action, rt_length, 0);
94 OffsetVarNodes(info->rule_qual, rt_length, 0);
95 /* but references to *OLD* should point at original rt_index */
96 ChangeVarNodes((Node *) sub_action,
97 PRS2_OLD_VARNO + rt_length, rt_index, 0);
98 ChangeVarNodes(info->rule_qual,
99 PRS2_OLD_VARNO + rt_length, rt_index, 0);
102 * We want the main parsetree's rtable to end up as the concatenation
103 * of its original contents plus those of all the relevant rule
104 * actions. Also store same into all the rule_action rtables.
105 * Some of the entries may be unused after we finish rewriting, but
106 * if we tried to clean those out we'd have a much harder job to
107 * adjust RT indexes in the query's Vars. It's OK to have unused
108 * RT entries, since planner will ignore them.
110 * NOTE KLUGY HACK: we assume the parsetree rtable had at least one
111 * entry to begin with (OK enough, else where'd the rule come from?).
112 * Because of this, if multiple rules nconc() their rtable additions
113 * onto parsetree->rtable, they'll all see the same rtable because
114 * they all have the same list head pointer.
116 parsetree->rtable = nconc(parsetree->rtable,
118 sub_action->rtable = parsetree->rtable;
121 * Each rule action's jointree should be the main parsetree's jointree
122 * plus that rule's jointree, but usually *without* the original rtindex
123 * that we're replacing (if present, which it won't be for INSERT).
124 * Note that if the rule action refers to OLD, its jointree will add
125 * a reference to rt_index. If the rule action doesn't refer to OLD,
126 * but either the rule_qual or the user query quals do, then we need to
127 * keep the original rtindex in the jointree to provide data for the
128 * quals. We don't want the original rtindex to be joined twice,
129 * however, so avoid keeping it if the rule action mentions it.
131 if (sub_action->jointree != NULL)
136 keeporig = (! rangeTableEntry_used((Node *) sub_action->jointree,
138 (rangeTableEntry_used(info->rule_qual, rt_index, 0) ||
139 rangeTableEntry_used(parsetree->jointree->quals, rt_index, 0));
140 newjointree = adjustJoinTreeList(parsetree, !keeporig, rt_index);
141 sub_action->jointree->fromlist =
142 nconc(newjointree, sub_action->jointree->fromlist);
146 * We copy the qualifications of the parsetree to the action and vice
147 * versa. So force hasSubLinks if one of them has it. If this is not
148 * right, the flag will get cleared later, but we mustn't risk having
149 * it not set when it needs to be.
151 if (parsetree->hasSubLinks)
152 sub_action->hasSubLinks = TRUE;
153 else if (sub_action->hasSubLinks)
154 parsetree->hasSubLinks = TRUE;
157 * Event Qualification forces copying of parsetree and
158 * splitting into two queries one w/rule_qual, one w/NOT
159 * rule_qual. Also add user query qual onto rule action
161 AddQual(sub_action, info->rule_qual);
163 AddQual(sub_action, parsetree->jointree->quals);
166 * Rewrite new.attribute w/ right hand side of target-list
167 * entry for appropriate field name in insert/update.
169 * KLUGE ALERT: since ResolveNew returns a mutated copy, we can't just
170 * apply it to sub_action; we have to remember to update the sublink
171 * inside info->rule_action, too.
173 if (info->event == CMD_INSERT || info->event == CMD_UPDATE)
175 sub_action = (Query *) ResolveNew((Node *) sub_action,
178 parsetree->targetList,
180 info->current_varno);
182 *sub_action_ptr = sub_action;
184 info->rule_action = sub_action;
191 * Copy the query's jointree list, and optionally attempt to remove any
192 * occurrence of the given rt_index as a top-level join item (we do not look
193 * for it within join items; this is OK because we are only expecting to find
194 * it as an UPDATE or DELETE target relation, which will be at the top level
195 * of the join). Returns modified jointree list --- original list is not
199 adjustJoinTreeList(Query *parsetree, bool removert, int rt_index)
201 List *newjointree = listCopy(parsetree->jointree->fromlist);
206 foreach(jjt, newjointree)
208 RangeTblRef *rtr = lfirst(jjt);
210 if (IsA(rtr, RangeTblRef) && rtr->rtindex == rt_index)
212 newjointree = lremove(rtr, newjointree);
223 * match the list of locks and returns the matching rules
226 matchLocks(CmdType event,
231 List *real_locks = NIL;
235 Assert(rulelocks != NULL); /* we get called iff there is some lock */
236 Assert(parsetree != NULL);
238 if (parsetree->commandType != CMD_SELECT)
240 if (parsetree->resultRelation != varno)
244 nlocks = rulelocks->numLocks;
246 for (i = 0; i < nlocks; i++)
248 RewriteRule *oneLock = rulelocks->rules[i];
250 if (oneLock->event == event)
252 if (parsetree->commandType != CMD_SELECT ||
253 (oneLock->attrno == -1 ?
254 rangeTableEntry_used((Node *) parsetree, varno, 0) :
255 attribute_used((Node *) parsetree,
256 varno, oneLock->attrno, 0)))
257 real_locks = lappend(real_locks, oneLock);
266 ApplyRetrieveRule(Query *parsetree,
277 if (length(rule->actions) != 1)
278 elog(ERROR, "ApplyRetrieveRule: expected just one rule action");
279 if (rule->qual != NULL)
280 elog(ERROR, "ApplyRetrieveRule: can't handle qualified ON SELECT rule");
281 if (! relation_level)
282 elog(ERROR, "ApplyRetrieveRule: can't handle per-attribute ON SELECT rule");
285 * Make a modifiable copy of the view query, and recursively expand
286 * any view references inside it.
288 rule_action = copyObject(lfirst(rule->actions));
290 rule_action = fireRIRrules(rule_action);
293 * VIEWs are really easy --- just plug the view query in as a subselect,
294 * replacing the relation's original RTE.
296 rte = rt_fetch(rt_index, parsetree->rtable);
299 rte->relid = InvalidOid;
300 rte->subquery = rule_action;
301 rte->inh = false; /* must not be set for a subquery */
304 * We move the view's permission check data down to its rangetable.
305 * The checks will actually be done against the *OLD* entry therein.
307 subrte = rt_fetch(PRS2_OLD_VARNO, rule_action->rtable);
308 Assert(subrte->relid == relation->rd_id);
309 subrte->checkForRead = rte->checkForRead;
310 subrte->checkForWrite = rte->checkForWrite;
312 rte->checkForRead = false; /* no permission check on subquery itself */
313 rte->checkForWrite = false;
316 * FOR UPDATE of view?
318 if (intMember(rt_index, parsetree->rowMarks))
321 * Remove the view from the list of rels that will actually be
322 * marked FOR UPDATE by the executor. It will still be access-
323 * checked for write access, though.
325 parsetree->rowMarks = lremovei(rt_index, parsetree->rowMarks);
328 * Set up the view's referenced tables as if FOR UPDATE.
330 markQueryForUpdate(rule_action, true);
337 * Recursively mark all relations used by a view as FOR UPDATE.
339 * This may generate an invalid query, eg if some sub-query uses an
340 * aggregate. We leave it to the planner to detect that.
342 * NB: this must agree with the parser's transformForUpdate() routine.
345 markQueryForUpdate(Query *qry, bool skipOldNew)
350 foreach(l, qry->rtable)
352 RangeTblEntry *rte = (RangeTblEntry *) lfirst(l);
356 /* Ignore OLD and NEW entries if we are at top level of view */
358 (rti == PRS2_OLD_VARNO || rti == PRS2_NEW_VARNO))
363 /* FOR UPDATE of subquery is propagated to subquery's rels */
364 markQueryForUpdate(rte->subquery, false);
368 if (!intMember(rti, qry->rowMarks))
369 qry->rowMarks = lappendi(qry->rowMarks, rti);
370 rte->checkForWrite = true;
378 * Apply fireRIRrules() to each SubLink (subselect in expression) found
381 * NOTE: although this has the form of a walker, we cheat and modify the
382 * SubLink nodes in-place. It is caller's responsibility to ensure that
383 * no unwanted side-effects occur!
385 * This is unlike most of the other routines that recurse into subselects,
386 * because we must take control at the SubLink node in order to replace
387 * the SubLink's subselect link with the possibly-rewritten subquery.
390 fireRIRonSubLink(Node *node, void *context)
394 if (IsA(node, SubLink))
396 SubLink *sub = (SubLink *) node;
398 /* Do what we came for */
399 sub->subselect = (Node *) fireRIRrules((Query *) (sub->subselect));
400 /* Fall through to process lefthand args of SubLink */
403 * Do NOT recurse into Query nodes, because fireRIRrules already
404 * processed subselects of subselects for us.
406 return expression_tree_walker(node, fireRIRonSubLink,
413 * Apply all RIR rules on each rangetable entry in a query
416 fireRIRrules(Query *parsetree)
421 * don't try to convert this into a foreach loop, because rtable list
422 * can get changed each time through...
425 while (rt_index < length(parsetree->rtable))
439 rte = rt_fetch(rt_index, parsetree->rtable);
442 * A subquery RTE can't have associated rules, so there's nothing
443 * to do to this level of the query, but we must recurse into the
444 * subquery to expand any rule references in it.
448 rte->subquery = fireRIRrules(rte->subquery);
453 * If the table is not referenced in the query, then we ignore it.
454 * This prevents infinite expansion loop due to new rtable entries
455 * inserted by expansion of a rule. A table is referenced if it is
456 * part of the join set (a source table), or is referenced by any
457 * Var nodes, or is the result table.
459 relIsUsed = rangeTableEntry_used((Node *) parsetree, rt_index, 0);
461 if (!relIsUsed && rt_index != parsetree->resultRelation)
465 * This may well be the first access to the relation during
466 * the current statement (it will be, if this Query was extracted
467 * from a rule or somehow got here other than via the parser).
468 * Therefore, grab the appropriate lock type for the relation,
469 * and do not release it until end of transaction. This protects
470 * the rewriter and planner against schema changes mid-query.
472 * If the relation is the query's result relation, then RewriteQuery()
473 * already got the right lock on it, so we need no additional lock.
474 * Otherwise, check to see if the relation is accessed FOR UPDATE
477 if (rt_index == parsetree->resultRelation)
479 else if (intMember(rt_index, parsetree->rowMarks))
480 lockmode = RowShareLock;
482 lockmode = AccessShareLock;
484 rel = heap_openr(rte->relname, lockmode);
486 rules = rel->rd_rules;
489 heap_close(rel, NoLock);
494 * Collect the RIR rules that we must apply
497 for (i = 0; i < rules->numLocks; i++)
499 rule = rules->rules[i];
500 if (rule->event != CMD_SELECT)
503 if (rule->attrno > 0)
505 /* per-attr rule; do we need it? */
506 if (!attribute_used((Node *) parsetree, rt_index,
511 locks = lappend(locks, rule);
521 parsetree = ApplyRetrieveRule(parsetree,
529 heap_close(rel, NoLock);
533 * Recurse into sublink subqueries, too.
535 if (parsetree->hasSubLinks)
536 query_tree_walker(parsetree, fireRIRonSubLink, NULL,
537 false /* already handled the ones in rtable */);
540 * If the query was marked having aggregates, check if this is
541 * still true after rewriting. Ditto for sublinks. Note there
542 * should be no aggs in the qual at this point. (Does this code
543 * still do anything useful? The view-becomes-subselect-in-FROM
544 * approach doesn't look like it could remove aggs or sublinks...)
546 if (parsetree->hasAggs)
548 parsetree->hasAggs = checkExprHasAggs((Node *) parsetree);
549 if (parsetree->hasAggs)
550 if (checkExprHasAggs((Node *) parsetree->jointree))
551 elog(ERROR, "fireRIRrules: failed to remove aggs from qual");
553 if (parsetree->hasSubLinks)
555 parsetree->hasSubLinks = checkExprHasSubLink((Node *) parsetree);
563 * idea is to fire regular rules first, then qualified instead
564 * rules and unqualified instead rules last. Any lemming is counted for.
567 orderRules(List *locks)
570 List *instead_rules = NIL;
571 List *instead_qualified = NIL;
576 RewriteRule *rule_lock = (RewriteRule *) lfirst(i);
578 if (rule_lock->isInstead)
580 if (rule_lock->qual == NULL)
581 instead_rules = lappend(instead_rules, rule_lock);
583 instead_qualified = lappend(instead_qualified, rule_lock);
586 regular = lappend(regular, rule_lock);
588 return nconc(nconc(regular, instead_qualified), instead_rules);
593 * Modify the given query by adding 'AND NOT rule_qual' to its qualification.
594 * This is used to generate suitable "else clauses" for conditional INSTEAD
597 * The rule_qual may contain references to OLD or NEW. OLD references are
598 * replaced by references to the specified rt_index (the relation that the
599 * rule applies to). NEW references are only possible for INSERT and UPDATE
600 * queries on the relation itself, and so they should be replaced by copies
601 * of the related entries in the query's own targetlist.
604 CopyAndAddQual(Query *parsetree,
609 Query *new_tree = (Query *) copyObject(parsetree);
610 Node *new_qual = (Node *) copyObject(rule_qual);
612 /* Fix references to OLD */
613 ChangeVarNodes(new_qual, PRS2_OLD_VARNO, rt_index, 0);
614 /* Fix references to NEW */
615 if (event == CMD_INSERT || event == CMD_UPDATE)
616 new_qual = ResolveNew(new_qual,
619 parsetree->targetList,
622 /* And attach the fixed qual */
623 AddNotQual(new_tree, new_qual);
632 * Iterate through rule locks applying rules.
633 * All rules create their own parsetrees. Instead rules
634 * with rule qualification save the original parsetree
635 * and add their negated qualification to it. Real instead
636 * rules finally throw away the original parsetree.
638 * remember: reality is for dead birds -- glass
642 fireRules(Query *parsetree,
647 List **qual_products)
652 /* choose rule to fire from list of rules */
656 locks = orderRules(locks); /* real instead rules last */
660 RewriteRule *rule_lock = (RewriteRule *) lfirst(i);
665 /* multiple rule action time */
666 *instead_flag = rule_lock->isInstead;
667 event_qual = rule_lock->qual;
668 actions = rule_lock->actions;
670 if (event_qual != NULL && *instead_flag)
675 * If there are instead rules with qualifications,
676 * the original query is still performed. But all
677 * the negated rule qualifications of the instead
678 * rules are added so it does its actions only
679 * in cases where the rule quals of all instead
680 * rules are false. Think of it as the default
681 * action in a case. We save this in *qual_products
682 * so deepRewriteQuery() can add it to the query
683 * list after we mangled it up enough.
686 if (*qual_products == NIL)
687 qual_product = parsetree;
689 qual_product = (Query *) lfirst(*qual_products);
691 qual_product = CopyAndAddQual(qual_product,
696 *qual_products = makeList1(qual_product);
701 Query *rule_action = lfirst(r);
704 if (rule_action->commandType == CMD_NOTHING)
707 info = gatherRewriteMeta(parsetree, rule_action, event_qual,
708 rt_index, event, *instead_flag);
710 /* handle escapable cases, or those handled by other code */
719 results = lappend(results, info->rule_action);
725 * If this was an unqualified instead rule,
726 * throw away an eventually saved 'default' parsetree
729 if (event_qual == NULL && *instead_flag)
730 *qual_products = NIL;
738 RewriteQuery(Query *parsetree, bool *instead_flag, List **qual_products)
741 List *product_queries = NIL;
743 RangeTblEntry *rt_entry;
744 Relation rt_entry_relation;
745 RuleLock *rt_entry_locks;
747 Assert(parsetree != NULL);
749 event = parsetree->commandType;
752 * SELECT rules are handled later when we have all the queries that
753 * should get executed
755 if (event == CMD_SELECT)
759 * Utilities aren't rewritten at all - why is this here?
761 if (event == CMD_UTILITY)
765 * the statement is an update, insert or delete - fire rules on it.
767 result_relation = parsetree->resultRelation;
768 Assert(result_relation != 0);
769 rt_entry = rt_fetch(result_relation, parsetree->rtable);
772 * This may well be the first access to the result relation during
773 * the current statement (it will be, if this Query was extracted
774 * from a rule or somehow got here other than via the parser).
775 * Therefore, grab the appropriate lock type for a result relation,
776 * and do not release it until end of transaction. This protects the
777 * rewriter and planner against schema changes mid-query.
779 rt_entry_relation = heap_openr(rt_entry->relname, RowExclusiveLock);
781 rt_entry_locks = rt_entry_relation->rd_rules;
783 if (rt_entry_locks != NULL)
785 List *locks = matchLocks(event, rt_entry_locks,
786 result_relation, parsetree);
788 product_queries = fireRules(parsetree,
796 heap_close(rt_entry_relation, NoLock); /* keep lock! */
798 return product_queries;
803 * to avoid infinite recursion, we restrict the number of times a query
804 * can be rewritten. Detecting cycles is left for the reader as an exercise.
806 #ifndef REWRITE_INVOKE_MAX
807 #define REWRITE_INVOKE_MAX 10
810 static int numQueryRewriteInvoked = 0;
814 * rewrites the query and apply the rules again on the queries rewritten
817 deepRewriteQuery(Query *parsetree)
820 List *rewritten = NIL;
823 List *qual_products = NIL;
825 if (++numQueryRewriteInvoked > REWRITE_INVOKE_MAX)
827 elog(ERROR, "query rewritten %d times, may contain cycles",
828 numQueryRewriteInvoked - 1);
832 result = RewriteQuery(parsetree, &instead, &qual_products);
836 Query *pt = lfirst(n);
839 newstuff = deepRewriteQuery(pt);
841 rewritten = nconc(rewritten, newstuff);
845 * qual_products are the original query with the negated
846 * rule qualification of an instead rule
849 if (qual_products != NIL)
850 rewritten = nconc(rewritten, qual_products);
853 * The original query is appended last (if no "instead" rule)
854 * because update and delete rule actions might not do
855 * anything if they are invoked after the update or
856 * delete is performed. The command counter increment
857 * between the query execution makes the deleted (and
858 * maybe the updated) tuples disappear so the scans
859 * for them in the rule actions cannot find them.
863 rewritten = lappend(rewritten, parsetree);
874 QueryRewriteOne(Query *parsetree)
876 numQueryRewriteInvoked = 0;
879 * take a deep breath and apply all the rewrite rules - ay
881 return deepRewriteQuery(parsetree);
887 * Primary entry point to the query rewriter.
888 * Rewrite one query via query rewrite system, possibly returning 0
891 * NOTE: The code in QueryRewrite was formerly in pg_parse_and_plan(), and was
892 * moved here so that it would be invoked during EXPLAIN.
895 QueryRewrite(Query *parsetree)
904 * Apply all non-SELECT rules possibly getting 0 or many queries
906 querylist = QueryRewriteOne(parsetree);
911 * Apply all the RIR rules on each query
913 foreach(l, querylist)
915 Query *query = (Query *) lfirst(l);
917 query = fireRIRrules(query);
920 * If the query target was rewritten as a view, complain.
922 if (query->resultRelation)
924 RangeTblEntry *rte = rt_fetch(query->resultRelation,
929 switch (query->commandType)
932 elog(ERROR, "Cannot insert into a view without an appropriate rule");
935 elog(ERROR, "Cannot update a view without an appropriate rule");
938 elog(ERROR, "Cannot delete from a view without an appropriate rule");
941 elog(ERROR, "QueryRewrite: unexpected commandType %d",
942 (int) query->commandType);
948 results = lappend(results, query);