1/*-------------------------------------------------------------------------
2 *
3 * rewriteSupport.c
4 *
5 *
6 * Portions Copyright (c) 1996-2019, 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/htup_details.h"
18#include "access/table.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
28
29/*
30 * Is there a rule by the given name?
31 */
32bool
33IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
34{
35 return SearchSysCacheExists2(RULERELNAME,
36 ObjectIdGetDatum(owningRel),
37 PointerGetDatum(ruleName));
38}
39
40
41/*
42 * SetRelationRuleStatus
43 * Set the value of the relation's relhasrules field in pg_class.
44 *
45 * NOTE: caller must be holding an appropriate lock on the relation.
46 *
47 * NOTE: an important side-effect of this operation is that an SI invalidation
48 * message is sent out to all backends --- including me --- causing relcache
49 * entries to be flushed or updated with the new set of rules for the table.
50 * This must happen even if we find that no change is needed in the pg_class
51 * row.
52 */
53void
54SetRelationRuleStatus(Oid relationId, bool relHasRules)
55{
56 Relation relationRelation;
57 HeapTuple tuple;
58 Form_pg_class classForm;
59
60 /*
61 * Find the tuple to update in pg_class, using syscache for the lookup.
62 */
63 relationRelation = table_open(RelationRelationId, RowExclusiveLock);
64 tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
65 if (!HeapTupleIsValid(tuple))
66 elog(ERROR, "cache lookup failed for relation %u", relationId);
67 classForm = (Form_pg_class) GETSTRUCT(tuple);
68
69 if (classForm->relhasrules != relHasRules)
70 {
71 /* Do the update */
72 classForm->relhasrules = relHasRules;
73
74 CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple);
75 }
76 else
77 {
78 /* no need to change tuple, but force relcache rebuild anyway */
79 CacheInvalidateRelcacheByTuple(tuple);
80 }
81
82 heap_freetuple(tuple);
83 table_close(relationRelation, RowExclusiveLock);
84}
85
86/*
87 * Find rule oid.
88 *
89 * If missing_ok is false, throw an error if rule name not found. If
90 * true, just return InvalidOid.
91 */
92Oid
93get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
94{
95 HeapTuple tuple;
96 Form_pg_rewrite ruleform;
97 Oid ruleoid;
98
99 /* Find the rule's pg_rewrite tuple, get its OID */
100 tuple = SearchSysCache2(RULERELNAME,
101 ObjectIdGetDatum(relid),
102 PointerGetDatum(rulename));
103 if (!HeapTupleIsValid(tuple))
104 {
105 if (missing_ok)
106 return InvalidOid;
107 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 ruleform = (Form_pg_rewrite) GETSTRUCT(tuple);
113 Assert(relid == ruleform->ev_class);
114 ruleoid = ruleform->oid;
115 ReleaseSysCache(tuple);
116 return ruleoid;
117}
118