1 /*-------------------------------------------------------------------------
4 * routines for removing rewrite rules
6 * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * $PostgreSQL: pgsql/src/backend/rewrite/rewriteRemove.c,v 1.68 2006/10/04 00:29:56 momjian Exp $
13 *-------------------------------------------------------------------------
17 #include "access/genam.h"
18 #include "access/heapam.h"
19 #include "catalog/dependency.h"
20 #include "catalog/indexing.h"
21 #include "catalog/pg_rewrite.h"
22 #include "miscadmin.h"
23 #include "rewrite/rewriteRemove.h"
24 #include "rewrite/rewriteSupport.h"
25 #include "utils/acl.h"
26 #include "utils/fmgroids.h"
27 #include "utils/lsyscache.h"
28 #include "utils/syscache.h"
34 * Delete a rule given its name.
37 RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior,
45 * Find the tuple for the target rule.
47 tuple = SearchSysCache(RULERELNAME,
48 ObjectIdGetDatum(owningRel),
49 PointerGetDatum(ruleName),
53 * complain if no rule with such name exists
55 if (!HeapTupleIsValid(tuple))
59 (errcode(ERRCODE_UNDEFINED_OBJECT),
60 errmsg("rule \"%s\" for relation \"%s\" does not exist",
61 ruleName, get_rel_name(owningRel))));
64 (errmsg("rule \"%s\" for relation \"%s\" does not exist, skipping",
65 ruleName, get_rel_name(owningRel))));
70 * Verify user has appropriate permissions.
72 eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
73 Assert(eventRelationOid == owningRel);
74 if (!pg_class_ownercheck(eventRelationOid, GetUserId()))
75 aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
76 get_rel_name(eventRelationOid));
81 object.classId = RewriteRelationId;
82 object.objectId = HeapTupleGetOid(tuple);
83 object.objectSubId = 0;
85 ReleaseSysCache(tuple);
87 performDeletion(&object, behavior);
92 * Guts of rule deletion.
95 RemoveRewriteRuleById(Oid ruleOid)
97 Relation RewriteRelation;
100 Relation event_relation;
102 Oid eventRelationOid;
106 * Open the pg_rewrite relation.
108 RewriteRelation = heap_open(RewriteRelationId, RowExclusiveLock);
111 * Find the tuple for the target rule.
113 ScanKeyInit(&skey[0],
114 ObjectIdAttributeNumber,
115 BTEqualStrategyNumber, F_OIDEQ,
116 ObjectIdGetDatum(ruleOid));
118 rcscan = systable_beginscan(RewriteRelation, RewriteOidIndexId, true,
119 SnapshotNow, 1, skey);
121 tuple = systable_getnext(rcscan);
123 if (!HeapTupleIsValid(tuple))
124 elog(ERROR, "could not find tuple for rule %u", ruleOid);
127 * We had better grab AccessExclusiveLock so that we know no other rule
128 * additions/deletions are going on for this relation. Else we cannot set
129 * relhasrules correctly. Besides, we don't want to be changing the
130 * ruleset while queries are executing on the rel.
132 eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
133 event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
135 hasMoreRules = event_relation->rd_rules != NULL &&
136 event_relation->rd_rules->numLocks > 1;
139 * Now delete the pg_rewrite tuple for the rule
141 simple_heap_delete(RewriteRelation, &tuple->t_self);
143 systable_endscan(rcscan);
145 heap_close(RewriteRelation, RowExclusiveLock);
148 * Set pg_class 'relhasrules' field correctly for event relation.
150 * Important side effect: an SI notice is broadcast to force all backends
151 * (including me!) to update relcache entries with the new rule set.
152 * Therefore, must do this even if relhasrules is still true!
154 SetRelationRuleStatus(eventRelationOid, hasMoreRules, false);
156 /* Close rel, but keep lock till commit... */
157 heap_close(event_relation, NoLock);