| /*------------------------------------------------------------------------- |
| * |
| * rewriteSupport.c |
| * |
| * |
| * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group |
| * Portions Copyright (c) 1994, Regents of the University of California |
| * |
| * |
| * IDENTIFICATION |
| * src/backend/rewrite/rewriteSupport.c |
| * |
| *------------------------------------------------------------------------- |
| */ |
| #include "postgres.h" |
| |
| #include "access/htup_details.h" |
| #include "access/table.h" |
| #include "catalog/indexing.h" |
| #include "catalog/pg_rewrite.h" |
| #include "rewrite/rewriteSupport.h" |
| #include "utils/fmgroids.h" |
| #include "utils/inval.h" |
| #include "utils/lsyscache.h" |
| #include "utils/rel.h" |
| #include "utils/syscache.h" |
| |
| |
| /* |
| * Is there a rule by the given name? |
| */ |
| bool |
| IsDefinedRewriteRule(Oid owningRel, const char *ruleName) |
| { |
| return SearchSysCacheExists2(RULERELNAME, |
| ObjectIdGetDatum(owningRel), |
| PointerGetDatum(ruleName)); |
| } |
| |
| |
| /* |
| * SetRelationRuleStatus |
| * Set the value of the relation's relhasrules field in pg_class. |
| * |
| * NOTE: caller must be holding an appropriate lock on the relation. |
| * |
| * NOTE: an important side-effect of this operation is that an SI invalidation |
| * message is sent out to all backends --- including me --- causing relcache |
| * entries to be flushed or updated with the new set of rules for the table. |
| * This must happen even if we find that no change is needed in the pg_class |
| * row. |
| */ |
| void |
| SetRelationRuleStatus(Oid relationId, bool relHasRules) |
| { |
| Relation relationRelation; |
| HeapTuple tuple; |
| Form_pg_class classForm; |
| |
| /* |
| * Find the tuple to update in pg_class, using syscache for the lookup. |
| */ |
| relationRelation = table_open(RelationRelationId, RowExclusiveLock); |
| tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId)); |
| if (!HeapTupleIsValid(tuple)) |
| elog(ERROR, "cache lookup failed for relation %u", relationId); |
| classForm = (Form_pg_class) GETSTRUCT(tuple); |
| |
| if (classForm->relhasrules != relHasRules) |
| { |
| /* Do the update */ |
| classForm->relhasrules = relHasRules; |
| |
| CatalogTupleUpdate(relationRelation, &tuple->t_self, tuple); |
| } |
| else |
| { |
| /* no need to change tuple, but force relcache rebuild anyway */ |
| CacheInvalidateRelcacheByTuple(tuple); |
| } |
| |
| heap_freetuple(tuple); |
| table_close(relationRelation, RowExclusiveLock); |
| } |
| |
| /* |
| * Find rule oid. |
| * |
| * If missing_ok is false, throw an error if rule name not found. If |
| * true, just return InvalidOid. |
| */ |
| Oid |
| get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok) |
| { |
| HeapTuple tuple; |
| Form_pg_rewrite ruleform; |
| Oid ruleoid; |
| |
| /* Find the rule's pg_rewrite tuple, get its OID */ |
| tuple = SearchSysCache2(RULERELNAME, |
| ObjectIdGetDatum(relid), |
| PointerGetDatum(rulename)); |
| if (!HeapTupleIsValid(tuple)) |
| { |
| if (missing_ok) |
| return InvalidOid; |
| ereport(ERROR, |
| (errcode(ERRCODE_UNDEFINED_OBJECT), |
| errmsg("rule \"%s\" for relation \"%s\" does not exist", |
| rulename, get_rel_name(relid)))); |
| } |
| ruleform = (Form_pg_rewrite) GETSTRUCT(tuple); |
| Assert(relid == ruleform->ev_class); |
| ruleoid = ruleform->oid; |
| ReleaseSysCache(tuple); |
| return ruleoid; |
| } |