Header And Logo

PostgreSQL
| The world's most advanced open source database.

rewriteSupport.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * rewriteSupport.c
00004  *
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  * Portions Copyright (c) 1994, Regents of the University of California
00008  *
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/rewrite/rewriteSupport.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 #include "postgres.h"
00016 
00017 #include "access/heapam.h"
00018 #include "access/htup_details.h"
00019 #include "catalog/indexing.h"
00020 #include "catalog/pg_rewrite.h"
00021 #include "rewrite/rewriteSupport.h"
00022 #include "utils/fmgroids.h"
00023 #include "utils/inval.h"
00024 #include "utils/lsyscache.h"
00025 #include "utils/rel.h"
00026 #include "utils/syscache.h"
00027 #include "utils/tqual.h"
00028 
00029 
00030 /*
00031  * Is there a rule by the given name?
00032  */
00033 bool
00034 IsDefinedRewriteRule(Oid owningRel, const char *ruleName)
00035 {
00036     return SearchSysCacheExists2(RULERELNAME,
00037                                  ObjectIdGetDatum(owningRel),
00038                                  PointerGetDatum(ruleName));
00039 }
00040 
00041 
00042 /*
00043  * SetRelationRuleStatus
00044  *      Set the value of the relation's relhasrules field in pg_class.
00045  *
00046  * NOTE: caller must be holding an appropriate lock on the relation.
00047  *
00048  * NOTE: an important side-effect of this operation is that an SI invalidation
00049  * message is sent out to all backends --- including me --- causing relcache
00050  * entries to be flushed or updated with the new set of rules for the table.
00051  * This must happen even if we find that no change is needed in the pg_class
00052  * row.
00053  */
00054 void
00055 SetRelationRuleStatus(Oid relationId, bool relHasRules)
00056 {
00057     Relation    relationRelation;
00058     HeapTuple   tuple;
00059     Form_pg_class classForm;
00060 
00061     /*
00062      * Find the tuple to update in pg_class, using syscache for the lookup.
00063      */
00064     relationRelation = heap_open(RelationRelationId, RowExclusiveLock);
00065     tuple = SearchSysCacheCopy1(RELOID, ObjectIdGetDatum(relationId));
00066     if (!HeapTupleIsValid(tuple))
00067         elog(ERROR, "cache lookup failed for relation %u", relationId);
00068     classForm = (Form_pg_class) GETSTRUCT(tuple);
00069 
00070     if (classForm->relhasrules != relHasRules)
00071     {
00072         /* Do the update */
00073         classForm->relhasrules = relHasRules;
00074 
00075         simple_heap_update(relationRelation, &tuple->t_self, tuple);
00076 
00077         /* Keep the catalog indexes up to date */
00078         CatalogUpdateIndexes(relationRelation, tuple);
00079     }
00080     else
00081     {
00082         /* no need to change tuple, but force relcache rebuild anyway */
00083         CacheInvalidateRelcacheByTuple(tuple);
00084     }
00085 
00086     heap_freetuple(tuple);
00087     heap_close(relationRelation, RowExclusiveLock);
00088 }
00089 
00090 /*
00091  * Find rule oid.
00092  *
00093  * If missing_ok is false, throw an error if rule name not found.  If
00094  * true, just return InvalidOid.
00095  */
00096 Oid
00097 get_rewrite_oid(Oid relid, const char *rulename, bool missing_ok)
00098 {
00099     HeapTuple   tuple;
00100     Oid         ruleoid;
00101 
00102     /* Find the rule's pg_rewrite tuple, get its OID */
00103     tuple = SearchSysCache2(RULERELNAME,
00104                             ObjectIdGetDatum(relid),
00105                             PointerGetDatum(rulename));
00106     if (!HeapTupleIsValid(tuple))
00107     {
00108         if (missing_ok)
00109             return InvalidOid;
00110         ereport(ERROR,
00111                 (errcode(ERRCODE_UNDEFINED_OBJECT),
00112                  errmsg("rule \"%s\" for relation \"%s\" does not exist",
00113                         rulename, get_rel_name(relid))));
00114     }
00115     Assert(relid == ((Form_pg_rewrite) GETSTRUCT(tuple))->ev_class);
00116     ruleoid = HeapTupleGetOid(tuple);
00117     ReleaseSysCache(tuple);
00118     return ruleoid;
00119 }
00120 
00121 /*
00122  * Find rule oid, given only a rule name but no rel OID.
00123  *
00124  * If there's more than one, it's an error.  If there aren't any, that's an
00125  * error, too.  In general, this should be avoided - it is provided to support
00126  * syntax that is compatible with pre-7.3 versions of PG, where rule names
00127  * were unique across the entire database.
00128  */
00129 Oid
00130 get_rewrite_oid_without_relid(const char *rulename,
00131                               Oid *reloid, bool missing_ok)
00132 {
00133     Relation    RewriteRelation;
00134     HeapScanDesc scanDesc;
00135     ScanKeyData scanKeyData;
00136     HeapTuple   htup;
00137     Oid         ruleoid;
00138 
00139     /* Search pg_rewrite for such a rule */
00140     ScanKeyInit(&scanKeyData,
00141                 Anum_pg_rewrite_rulename,
00142                 BTEqualStrategyNumber, F_NAMEEQ,
00143                 CStringGetDatum(rulename));
00144 
00145     RewriteRelation = heap_open(RewriteRelationId, AccessShareLock);
00146     scanDesc = heap_beginscan(RewriteRelation, SnapshotNow, 1, &scanKeyData);
00147 
00148     htup = heap_getnext(scanDesc, ForwardScanDirection);
00149     if (!HeapTupleIsValid(htup))
00150     {
00151         if (!missing_ok)
00152             ereport(ERROR,
00153                     (errcode(ERRCODE_UNDEFINED_OBJECT),
00154                      errmsg("rule \"%s\" does not exist", rulename)));
00155         ruleoid = InvalidOid;
00156     }
00157     else
00158     {
00159         ruleoid = HeapTupleGetOid(htup);
00160         if (reloid != NULL)
00161             *reloid = ((Form_pg_rewrite) GETSTRUCT(htup))->ev_class;
00162 
00163         htup = heap_getnext(scanDesc, ForwardScanDirection);
00164         if (HeapTupleIsValid(htup))
00165             ereport(ERROR,
00166                     (errcode(ERRCODE_DUPLICATE_OBJECT),
00167                    errmsg("there are multiple rules named \"%s\"", rulename),
00168                 errhint("Specify a relation name as well as a rule name.")));
00169     }
00170     heap_endscan(scanDesc);
00171     heap_close(RewriteRelation, AccessShareLock);
00172 
00173     return ruleoid;
00174 }