1 /*-------------------------------------------------------------------------
4 * routines for removing rewrite rules
6 * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.52 2002/07/20 05:16:58 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "catalog/catname.h"
20 #include "catalog/dependency.h"
21 #include "catalog/indexing.h"
22 #include "catalog/pg_rewrite.h"
23 #include "miscadmin.h"
24 #include "rewrite/rewriteRemove.h"
25 #include "rewrite/rewriteSupport.h"
26 #include "utils/acl.h"
27 #include "utils/fmgroids.h"
28 #include "utils/lsyscache.h"
29 #include "utils/syscache.h"
35 * Delete a rule given its name.
38 RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior)
46 * Find the tuple for the target rule.
48 tuple = SearchSysCache(RULERELNAME,
49 ObjectIdGetDatum(owningRel),
50 PointerGetDatum(ruleName),
54 * complain if no rule with such name exists
56 if (!HeapTupleIsValid(tuple))
57 elog(ERROR, "Rule \"%s\" not found", ruleName);
60 * Verify user has appropriate permissions.
62 eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
63 Assert(eventRelationOid == owningRel);
64 aclresult = pg_class_aclcheck(eventRelationOid, GetUserId(), ACL_RULE);
65 if (aclresult != ACLCHECK_OK)
66 aclcheck_error(aclresult, get_rel_name(eventRelationOid));
71 object.classId = get_system_catalog_relid(RewriteRelationName);
72 object.objectId = HeapTupleGetOid(tuple);
73 object.objectSubId = 0;
75 ReleaseSysCache(tuple);
77 performDeletion(&object, behavior);
82 * Guts of rule deletion.
85 RemoveRewriteRuleById(Oid ruleOid)
87 Relation RewriteRelation;
90 Relation event_relation;
96 * Open the pg_rewrite relation.
98 RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
101 * Find the tuple for the target rule.
103 ScanKeyEntryInitialize(&skey[0], 0x0,
104 ObjectIdAttributeNumber, F_OIDEQ,
105 ObjectIdGetDatum(ruleOid));
107 rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true,
108 SnapshotNow, 1, skey);
110 tuple = systable_getnext(rcscan);
112 if (!HeapTupleIsValid(tuple))
113 elog(ERROR, "RemoveRewriteRuleById: Rule %u does not exist",
117 * We had better grab AccessExclusiveLock so that we know no other
118 * rule additions/deletions are going on for this relation. Else we
119 * cannot set relhasrules correctly. Besides, we don't want to be
120 * changing the ruleset while queries are executing on the rel.
122 eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
123 event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
125 hasMoreRules = event_relation->rd_rules != NULL &&
126 event_relation->rd_rules->numLocks > 1;
129 * Now delete the pg_rewrite tuple for the rule
131 simple_heap_delete(RewriteRelation, &tuple->t_self);
133 systable_endscan(rcscan);
135 heap_close(RewriteRelation, RowExclusiveLock);
138 * Set pg_class 'relhasrules' field correctly for event relation.
140 * Important side effect: an SI notice is broadcast to force all backends
141 * (including me!) to update relcache entries with the new rule set.
142 * Therefore, must do this even if relhasrules is still true!
144 SetRelationRuleStatus(eventRelationOid, hasMoreRules, false);
146 /* Close rel, but keep lock till commit... */
147 heap_close(event_relation, NoLock);