OSDN Git Service

1fd5f36ce55851b43889540844e17b6a020424a1
[pg-rex/syncrep.git] / src / backend / rewrite / rewriteRemove.c
1 /*-------------------------------------------------------------------------
2  *
3  * rewriteRemove.c
4  *        routines for removing rewrite rules
5  *
6  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $Header: /cvsroot/pgsql/src/backend/rewrite/rewriteRemove.c,v 1.52 2002/07/20 05:16:58 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
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"
30
31
32 /*
33  * RemoveRewriteRule
34  *
35  * Delete a rule given its name.
36  */
37 void
38 RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior)
39 {
40         HeapTuple       tuple;
41         Oid                     eventRelationOid;
42         AclResult       aclresult;
43         ObjectAddress object;
44
45         /*
46          * Find the tuple for the target rule.
47          */
48         tuple = SearchSysCache(RULERELNAME,
49                                                    ObjectIdGetDatum(owningRel),
50                                                    PointerGetDatum(ruleName),
51                                                    0, 0);
52
53         /*
54          * complain if no rule with such name exists
55          */
56         if (!HeapTupleIsValid(tuple))
57                 elog(ERROR, "Rule \"%s\" not found", ruleName);
58
59         /*
60          * Verify user has appropriate permissions.
61          */
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));
67
68         /*
69          * Do the deletion
70          */
71         object.classId = get_system_catalog_relid(RewriteRelationName);
72         object.objectId = HeapTupleGetOid(tuple);
73         object.objectSubId = 0;
74
75         ReleaseSysCache(tuple);
76
77         performDeletion(&object, behavior);
78 }
79
80
81 /*
82  * Guts of rule deletion.
83  */
84 void
85 RemoveRewriteRuleById(Oid ruleOid)
86 {
87         Relation        RewriteRelation;
88         ScanKeyData             skey[1];
89         SysScanDesc             rcscan;
90         Relation        event_relation;
91         HeapTuple       tuple;
92         Oid                     eventRelationOid;
93         bool            hasMoreRules;
94
95         /*
96          * Open the pg_rewrite relation.
97          */
98         RewriteRelation = heap_openr(RewriteRelationName, RowExclusiveLock);
99
100         /*
101          * Find the tuple for the target rule.
102          */
103         ScanKeyEntryInitialize(&skey[0], 0x0,
104                                                    ObjectIdAttributeNumber, F_OIDEQ,
105                                                    ObjectIdGetDatum(ruleOid));
106
107         rcscan = systable_beginscan(RewriteRelation, RewriteOidIndex, true,
108                                                                 SnapshotNow, 1, skey);
109
110         tuple = systable_getnext(rcscan);
111
112         if (!HeapTupleIsValid(tuple))
113                 elog(ERROR, "RemoveRewriteRuleById: Rule %u does not exist",
114                          ruleOid);
115
116         /*
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.
121          */
122         eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
123         event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
124
125         hasMoreRules = event_relation->rd_rules != NULL &&
126                 event_relation->rd_rules->numLocks > 1;
127
128         /*
129          * Now delete the pg_rewrite tuple for the rule
130          */
131         simple_heap_delete(RewriteRelation, &tuple->t_self);
132
133         systable_endscan(rcscan);
134
135         heap_close(RewriteRelation, RowExclusiveLock);
136
137         /*
138          * Set pg_class 'relhasrules' field correctly for event relation.
139          *
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!
143          */
144         SetRelationRuleStatus(eventRelationOid, hasMoreRules, false);
145
146         /* Close rel, but keep lock till commit... */
147         heap_close(event_relation, NoLock);
148 }