Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * rewriteSupport.c
4 : *
5 : *
6 : * Portions Copyright (c) 1996-2017, 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 4 : IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
35 : {
36 4 : 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 523 : 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 523 : relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
65 523 : tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
66 523 : if (!HeapTupleIsValid(tuple))
67 0 : elog(ERROR, "cache lookup failed for relation %u", relationId);
68 523 : classForm = (Form_pg_class) GETSTRUCT(tuple);
69 :
70 523 : if (classForm->relhasrules != relHasRules)
71 : {
72 : /* Do the update */
73 438 : classForm->relhasrules = relHasRules;
74 :
75 438 : CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
76 : }
77 : else
78 : {
79 : /* no need to change tuple, but force relcache rebuild anyway */
80 85 : CacheInvalidateRelcacheByTuple(tuple);
81 : }
82 :
83 523 : heap_freetuple(tuple);
84 523 : heap_close(relationRelation, RowExclusiveLock);
85 523 : }
86 :
87 : /*
88 : * Find rule oid.
89 : *
90 : * If missing_ok is false, throw an error if rule name not found. If
91 : * true, just return InvalidOid.
92 : */
93 : Oid
94 30 : get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
95 : {
96 : HeapTuple tuple;
97 : Oid ruleoid;
98 :
99 : /* Find the rule's pg_rewrite tuple, get its OID */
100 30 : tuple = SearchSysCache2(RULERELNAME,
101 : ObjectIdGetDatum(relid),
102 : PointerGetDatum(rulename));
103 30 : if (!HeapTupleIsValid(tuple))
104 : {
105 3 : if (missing_ok)
106 1 : return InvalidOid;
107 2 : ereport(ERROR,
108 : (errcode(ERRCODE_UNDEFINED_OBJECT),
109 : errmsg("rule \"%s\" for relation \"%s\" does not exist",
110 : rulename, get_rel_name(relid))));
111 : }
112 27 : Assert(relid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
113 27 : ruleoid = HeapTupleGetOid(tuple);
114 27 : ReleaseSysCache(tuple);
115 27 : return ruleoid;
116 : }
|