]> granicus.if.org Git - postgresql/blob - src/backend/rewrite/rewriteSupport.c
Update copyright for 2014
[postgresql] / src / backend / rewrite / rewriteSupport.c
1 /*-------------------------------------------------------------------------
2  *
3  * rewriteSupport.c
4  *
5  *
6  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        src/backend/rewrite/rewriteSupport.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "access/heapam.h"
18 #include "access/htup_details.h"
19 #include "catalog/indexing.h"
20 #include "catalog/pg_rewrite.h"
21 #include "rewrite/rewriteSupport.h"
22 #include "utils/fmgroids.h"
23 #include "utils/inval.h"
24 #include "utils/lsyscache.h"
25 #include "utils/rel.h"
26 #include "utils/syscache.h"
27 #include "utils/tqual.h"
28
29
30 /*
31  * Is there a rule by the given name?
32  */
33 bool
34 IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
35 {
36         return SearchSysCacheExists2(RULERELNAME,
37                                                                  ObjectIdGetDatum(owningRel),
38                                                                  PointerGetDatum(ruleName));
39 }
40
41
42 /*
43  * SetRelationRuleStatus
44  *              Set the value of the relation's relhasrules field in pg_class.
45  *
46  * NOTE: caller must be holding an appropriate lock on the relation.
47  *
48  * NOTE: an important side-effect of this operation is that an SI invalidation
49  * message is sent out to all backends --- including me --- causing relcache
50  * entries to be flushed or updated with the new set of rules for the table.
51  * This must happen even if we find that no change is needed in the pg_class
52  * row.
53  */
54 void
55 SetRelationRuleStatus(Oid relationId, bool relHasRules)
56 {
57         Relation        relationRelation;
58         HeapTuple       tuple;
59         Form_pg_class classForm;
60
61         /*
62          * Find the tuple to update in pg_class, using syscache for the lookup.
63          */
64         relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
65         tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
66         if (!HeapTupleIsValid(tuple))
67                 elog(ERROR, "cache lookup failed for relation %u", relationId);
68         classForm = (Form_pg_class) GETSTRUCT(tuple);
69
70         if (classForm->relhasrules != relHasRules)
71         {
72                 /* Do the update */
73                 classForm->relhasrules = relHasRules;
74
75                 simple_heap_update(relationRelation, &tuple->t_self, tuple);
76
77                 /* Keep the catalog indexes up to date */
78                 CatalogUpdateIndexes(relationRelation, tuple);
79         }
80         else
81         {
82                 /* no need to change tuple, but force relcache rebuild anyway */
83                 CacheInvalidateRelcacheByTuple(tuple);
84         }
85
86         heap_freetuple(tuple);
87         heap_close(relationRelation, RowExclusiveLock);
88 }
89
90 /*
91  * Find rule oid.
92  *
93  * If missing_ok is false, throw an error if rule name not found.  If
94  * true, just return InvalidOid.
95  */
96 Oid
97 get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
98 {
99         HeapTuple       tuple;
100         Oid                     ruleoid;
101
102         /* Find the rule's pg_rewrite tuple, get its OID */
103         tuple = SearchSysCache2(RULERELNAME,
104                                                         ObjectIdGetDatum(relid),
105                                                         PointerGetDatum(rulename));
106         if (!HeapTupleIsValid(tuple))
107         {
108                 if (missing_ok)
109                         return InvalidOid;
110                 ereport(ERROR,
111                                 (errcode(ERRCODE_UNDEFINED_OBJECT),
112                                  errmsg("rule \"%s\" for relation \"%s\" does not exist",
113                                                 rulename, get_rel_name(relid))));
114         }
115         Assert(relid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
116         ruleoid = HeapTupleGetOid(tuple);
117         ReleaseSysCache(tuple);
118         return ruleoid;
119 }
120
121 /*
122  * Find rule oid, given only a rule name but no rel OID.
123  *
124  * If there's more than one, it's an error.  If there aren't any, that's an
125  * error, too.  In general, this should be avoided - it is provided to support
126  * syntax that is compatible with pre-7.3 versions of PG, where rule names
127  * were unique across the entire database.
128  */
129 Oid
130 get_rewrite_oid_without_relid(const char *rulename,
131                                                           Oid *reloid, bool missing_ok)
132 {
133         Relation        RewriteRelation;
134         HeapScanDesc scanDesc;
135         ScanKeyData scanKeyData;
136         HeapTuple       htup;
137         Oid                     ruleoid;
138
139         /* Search pg_rewrite for such a rule */
140         ScanKeyInit(&scanKeyData,
141                                 Anum_pg_rewrite_rulename,
142                                 BTEqualStrategyNumber, F_NAMEEQ,
143                                 CStringGetDatum(rulename));
144
145         RewriteRelation = heap_open(RewriteRelationId, AccessShareLock);
146         scanDesc = heap_beginscan_catalog(RewriteRelation, 1, &scanKeyData);
147
148         htup = heap_getnext(scanDesc, ForwardScanDirection);
149         if (!HeapTupleIsValid(htup))
150         {
151                 if (!missing_ok)
152                         ereport(ERROR,
153                                         (errcode(ERRCODE_UNDEFINED_OBJECT),
154                                          errmsg("rule \"%s\" does not exist", rulename)));
155                 ruleoid = InvalidOid;
156         }
157         else
158         {
159                 ruleoid = HeapTupleGetOid(htup);
160                 if (reloid != NULL)
161                         *reloid = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class;
162
163                 htup = heap_getnext(scanDesc, ForwardScanDirection);
164                 if (HeapTupleIsValid(htup))
165                         ereport(ERROR,
166                                         (errcode(ERRCODE_DUPLICATE_OBJECT),
167                                    errmsg("there are multiple rules named \"%s\"", rulename),
168                                 errhint("Specify a relation name as well as a rule name.")));
169         }
170         heap_endscan(scanDesc);
171         heap_close(RewriteRelation, AccessShareLock);
172
173         return ruleoid;
174 }