1 /*-------------------------------------------------------------------------
4 * routines for removing rewrite rules
6 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
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"
29 #include "utils/tqual.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
))
60 (errcode(ERRCODE_UNDEFINED_OBJECT
),
61 errmsg("rule \"%s\" for relation \"%s\" does not exist",
62 ruleName
, get_rel_name(owningRel
))));
65 (errmsg("rule \"%s\" for relation \"%s\" does not exist, skipping",
66 ruleName
, get_rel_name(owningRel
))));
71 * Verify user has appropriate permissions.
73 eventRelationOid
= ((Form_pg_rewrite
) GETSTRUCT(tuple
))->ev_class
;
74 Assert(eventRelationOid
== owningRel
);
75 if (!pg_class_ownercheck(eventRelationOid
, GetUserId()))
76 aclcheck_error(ACLCHECK_NOT_OWNER
, ACL_KIND_CLASS
,
77 get_rel_name(eventRelationOid
));
82 object
.classId
= RewriteRelationId
;
83 object
.objectId
= HeapTupleGetOid(tuple
);
84 object
.objectSubId
= 0;
86 ReleaseSysCache(tuple
);
88 performDeletion(&object
, behavior
);
93 * Guts of rule deletion.
96 RemoveRewriteRuleById(Oid ruleOid
)
98 Relation RewriteRelation
;
101 Relation event_relation
;
103 Oid eventRelationOid
;
107 * Open the pg_rewrite relation.
109 RewriteRelation
= heap_open(RewriteRelationId
, RowExclusiveLock
);
112 * Find the tuple for the target rule.
114 ScanKeyInit(&skey
[0],
115 ObjectIdAttributeNumber
,
116 BTEqualStrategyNumber
, F_OIDEQ
,
117 ObjectIdGetDatum(ruleOid
));
119 rcscan
= systable_beginscan(RewriteRelation
, RewriteOidIndexId
, true,
120 SnapshotNow
, 1, skey
);
122 tuple
= systable_getnext(rcscan
);
124 if (!HeapTupleIsValid(tuple
))
125 elog(ERROR
, "could not find tuple for rule %u", ruleOid
);
128 * We had better grab AccessExclusiveLock so that we know no other rule
129 * additions/deletions are going on for this relation. Else we cannot set
130 * relhasrules correctly. Besides, we don't want to be changing the
131 * ruleset while queries are executing on the rel.
133 eventRelationOid
= ((Form_pg_rewrite
) GETSTRUCT(tuple
))->ev_class
;
134 event_relation
= heap_open(eventRelationOid
, AccessExclusiveLock
);
136 hasMoreRules
= event_relation
->rd_rules
!= NULL
&&
137 event_relation
->rd_rules
->numLocks
> 1;
140 * Now delete the pg_rewrite tuple for the rule
142 simple_heap_delete(RewriteRelation
, &tuple
->t_self
);
144 systable_endscan(rcscan
);
146 heap_close(RewriteRelation
, RowExclusiveLock
);
149 * Set pg_class 'relhasrules' field correctly for event relation.
151 * Important side effect: an SI notice is broadcast to force all backends
152 * (including me!) to update relcache entries with the new rule set.
153 * Therefore, must do this even if relhasrules is still true!
155 SetRelationRuleStatus(eventRelationOid
, hasMoreRules
, false);
157 /* Close rel, but keep lock till commit... */
158 heap_close(event_relation
, NoLock
);