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 | */ |
32 | bool |
33 | IsDefinedRewriteRule(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 | */ |
53 | void |
54 | SetRelationRuleStatus(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 | */ |
92 | Oid |
93 | get_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 | |