OSDN Git Service

pgindent run for 8.2.
[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-2006, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/rewrite/rewriteRemove.c,v 1.68 2006/10/04 00:29:56 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
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
30
31 /*
32  * RemoveRewriteRule
33  *
34  * Delete a rule given its name.
35  */
36 void
37 RemoveRewriteRule(Oid owningRel, const char *ruleName, DropBehavior behavior,
38                                   bool missing_ok)
39 {
40         HeapTuple       tuple;
41         Oid                     eventRelationOid;
42         ObjectAddress object;
43
44         /*
45          * Find the tuple for the target rule.
46          */
47         tuple = SearchSysCache(RULERELNAME,
48                                                    ObjectIdGetDatum(owningRel),
49                                                    PointerGetDatum(ruleName),
50                                                    0, 0);
51
52         /*
53          * complain if no rule with such name exists
54          */
55         if (!HeapTupleIsValid(tuple))
56         {
57                 if (!missing_ok)
58                         ereport(ERROR,
59                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
60                                          errmsg("rule \"%s\" for relation \"%s\" does not exist",
61                                                         ruleName, get_rel_name(owningRel))));
62                 else
63                         ereport(NOTICE,
64                                         (errmsg("rule \"%s\" for relation \"%s\" does not exist, skipping",
65                                                         ruleName, get_rel_name(owningRel))));
66                 return;
67         }
68
69         /*
70          * Verify user has appropriate permissions.
71          */
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));
77
78         /*
79          * Do the deletion
80          */
81         object.classId = RewriteRelationId;
82         object.objectId = HeapTupleGetOid(tuple);
83         object.objectSubId = 0;
84
85         ReleaseSysCache(tuple);
86
87         performDeletion(&object, behavior);
88 }
89
90
91 /*
92  * Guts of rule deletion.
93  */
94 void
95 RemoveRewriteRuleById(Oid ruleOid)
96 {
97         Relation        RewriteRelation;
98         ScanKeyData skey[1];
99         SysScanDesc rcscan;
100         Relation        event_relation;
101         HeapTuple       tuple;
102         Oid                     eventRelationOid;
103         bool            hasMoreRules;
104
105         /*
106          * Open the pg_rewrite relation.
107          */
108         RewriteRelation = heap_open(RewriteRelationId, RowExclusiveLock);
109
110         /*
111          * Find the tuple for the target rule.
112          */
113         ScanKeyInit(&skey[0],
114                                 ObjectIdAttributeNumber,
115                                 BTEqualStrategyNumber, F_OIDEQ,
116                                 ObjectIdGetDatum(ruleOid));
117
118         rcscan = systable_beginscan(RewriteRelation, RewriteOidIndexId, true,
119                                                                 SnapshotNow, 1, skey);
120
121         tuple = systable_getnext(rcscan);
122
123         if (!HeapTupleIsValid(tuple))
124                 elog(ERROR, "could not find tuple for rule %u", ruleOid);
125
126         /*
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.
131          */
132         eventRelationOid = ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class;
133         event_relation = heap_open(eventRelationOid, AccessExclusiveLock);
134
135         hasMoreRules = event_relation->rd_rules != NULL &&
136                 event_relation->rd_rules->numLocks > 1;
137
138         /*
139          * Now delete the pg_rewrite tuple for the rule
140          */
141         simple_heap_delete(RewriteRelation, &tuple->t_self);
142
143         systable_endscan(rcscan);
144
145         heap_close(RewriteRelation, RowExclusiveLock);
146
147         /*
148          * Set pg_class 'relhasrules' field correctly for event relation.
149          *
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!
153          */
154         SetRelationRuleStatus(eventRelationOid, hasMoreRules, false);
155
156         /* Close rel, but keep lock till commit... */
157         heap_close(event_relation, NoLock);
158 }