*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.81 2000/11/08 22:09:55 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.82 2000/11/10 00:33:08 tgl Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
AtAbort_Cache(void)
{
RelationCacheAbort();
- SystemCacheAbort();
RegisterInvalid(false);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.72 2000/10/24 01:38:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.73 2000/11/10 00:33:09 tgl Exp $
*
*-------------------------------------------------------------------------
*/
}
}
-/*
- * This is needed at initialization when reldescs for some of the crucial
- * system catalogs are created and nailed into the cache.
- */
-bool
-CatalogHasIndex(char *catName, Oid catId)
-{
- Relation pg_class;
- HeapTuple htup;
- Form_pg_class pgRelP;
- int i;
-
- Assert(IsSystemRelationName(catName));
-
- /*
- * If we're bootstraping we don't have pg_class (or any indices).
- */
- if (IsBootstrapProcessingMode())
- return false;
-
- if (IsInitProcessingMode())
- {
- for (i = 0; IndexedCatalogNames[i] != NULL; i++)
- {
- if (strcmp(IndexedCatalogNames[i], catName) == 0)
- return true;
- }
- return false;
- }
-
- pg_class = heap_openr(RelationRelationName, AccessShareLock);
- htup = ClassOidIndexScan(pg_class, catId);
- heap_close(pg_class, AccessShareLock);
-
- if (!HeapTupleIsValid(htup))
- {
- elog(NOTICE, "CatalogHasIndex: no relation with oid %u", catId);
- return false;
- }
-
- pgRelP = (Form_pg_class) GETSTRUCT(htup);
- return pgRelP->relhasindex;
-}
-
/*
* CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
*/
/*
- * The remainder of the file is for individual index scan routines. Each
- * index should be scanned according to how it was defined during bootstrap
- * (that is, functional or normal) and what arguments the cache lookup
- * requires. Each routine returns the heap tuple that qualifies.
+ * The remainder of the file is for individual index scan routines.
+ * These routines provide canned scanning code for certain widely-used
+ * indexes. Most indexes don't need one of these.
*/
-HeapTuple
-AggregateNameTypeIndexScan(Relation heapRelation,
- Datum aggName, Datum aggType)
-{
- Relation idesc;
- ScanKeyData skey[2];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- aggName);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_OIDEQ,
- aggType);
-
- idesc = index_openr(AggregateNameTypeIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-AmNameIndexScan(Relation heapRelation, Datum amName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- amName);
-
- idesc = index_openr(AmNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-AccessMethodOpidIndexScan(Relation heapRelation,
- Datum claid,
- Datum opopr,
- Datum opid)
-{
- Relation idesc;
- ScanKeyData skey[3];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- claid);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_OIDEQ,
- opopr);
-
- ScanKeyEntryInitialize(&skey[2],
- (bits16) 0x0,
- (AttrNumber) 3,
- (RegProcedure) F_OIDEQ,
- opid);
-
- idesc = index_openr(AccessMethodOpidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);
-
- index_close(idesc);
- return tuple;
-}
-
-HeapTuple
-AccessMethodStrategyIndexScan(Relation heapRelation,
- Datum opid,
- Datum claid,
- Datum opstrategy)
-{
- Relation idesc;
- ScanKeyData skey[3];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- opid);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_OIDEQ,
- claid);
-
- ScanKeyEntryInitialize(&skey[2],
- (bits16) 0x0,
- (AttrNumber) 3,
- (RegProcedure) F_INT2EQ,
- opstrategy);
-
- idesc = index_openr(AccessMethodStrategyIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-AttributeRelidNameIndexScan(Relation heapRelation,
- Datum relid,
- Datum attname)
-{
- Relation idesc;
- ScanKeyData skey[2];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- relid);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_NAMEEQ,
- attname);
-
- idesc = index_openr(AttributeRelidNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
- index_close(idesc);
- return tuple;
-}
-
-
HeapTuple
AttributeRelidNumIndexScan(Relation heapRelation,
Datum relid,
idesc = index_openr(AttributeRelidNumIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-OpclassDeftypeIndexScan(Relation heapRelation, Datum defType)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- defType);
-
- idesc = index_openr(OpclassDeftypeIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-OpclassNameIndexScan(Relation heapRelation, Datum opcName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- opcName);
-
- idesc = index_openr(OpclassNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-GroupNameIndexScan(Relation heapRelation, Datum groName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- groName);
-
- idesc = index_openr(GroupNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-GroupSysidIndexScan(Relation heapRelation, Datum sysId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_INT4EQ,
- sysId);
-
- idesc = index_openr(GroupSysidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-IndexRelidIndexScan(Relation heapRelation, Datum relid)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- relid);
-
- idesc = index_openr(IndexRelidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-InheritsRelidSeqnoIndexScan(Relation heapRelation,
- Datum relid,
- Datum seqno)
-{
- Relation idesc;
- ScanKeyData skey[2];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- relid);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_INT4EQ,
- seqno);
-
- idesc = index_openr(InheritsRelidSeqnoIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
index_close(idesc);
return tuple;
}
HeapTuple
-LanguageNameIndexScan(Relation heapRelation, Datum lanName)
+ClassNameIndexScan(Relation heapRelation, Datum relName)
{
Relation idesc;
ScanKeyData skey[1];
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) F_NAMEEQ,
- lanName);
+ relName);
- idesc = index_openr(LanguageNameIndex);
+ idesc = index_openr(ClassNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
index_close(idesc);
return tuple;
}
HeapTuple
-LanguageOidIndexScan(Relation heapRelation, Datum lanId)
+ClassOidIndexScan(Relation heapRelation, Datum relId)
{
Relation idesc;
ScanKeyData skey[1];
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) F_OIDEQ,
- lanId);
+ relId);
- idesc = index_openr(LanguageOidIndex);
+ idesc = index_openr(ClassOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ListenerPidRelnameIndexScan(Relation heapRelation,
- Datum pid, Datum relName)
-{
- Relation idesc;
- ScanKeyData skey[2];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_INT4EQ,
- pid);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_NAMEEQ,
- relName);
-
- idesc = index_openr(ListenerPidRelnameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-OperatorNameIndexScan(Relation heapRelation,
- Datum oprName,
- Datum oprLeft,
- Datum oprRight,
- Datum oprKind)
-{
- Relation idesc;
- ScanKeyData skey[4];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- oprName);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_OIDEQ,
- oprLeft);
-
- ScanKeyEntryInitialize(&skey[2],
- (bits16) 0x0,
- (AttrNumber) 3,
- (RegProcedure) F_OIDEQ,
- oprRight);
-
- ScanKeyEntryInitialize(&skey[3],
- (bits16) 0x0,
- (AttrNumber) 4,
- (RegProcedure) F_CHAREQ,
- oprKind);
-
- idesc = index_openr(OperatorNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 4);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-OperatorOidIndexScan(Relation heapRelation, Datum oprId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- oprId);
-
- idesc = index_openr(OperatorOidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ProcedureNameIndexScan(Relation heapRelation,
- Datum procName,
- Datum nargs,
- Datum argTypes)
-{
- Relation idesc;
- ScanKeyData skey[3];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- procName);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_INT2EQ,
- nargs);
-
- ScanKeyEntryInitialize(&skey[2],
- (bits16) 0x0,
- (AttrNumber) 3,
- (RegProcedure) F_OIDVECTOREQ,
- argTypes);
-
- idesc = index_openr(ProcedureNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ProcedureOidIndexScan(Relation heapRelation, Datum procId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- procId);
-
- idesc = index_openr(ProcedureOidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ClassNameIndexScan(Relation heapRelation, Datum relName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- relName);
-
- idesc = index_openr(ClassNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ClassOidIndexScan(Relation heapRelation, Datum relId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- relId);
-
- idesc = index_openr(ClassOidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-RewriteRulenameIndexScan(Relation heapRelation, Datum ruleName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- ruleName);
-
- idesc = index_openr(RewriteRulenameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-RewriteOidIndexScan(Relation heapRelation, Datum rewriteId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- rewriteId);
-
- idesc = index_openr(RewriteOidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ShadowNameIndexScan(Relation heapRelation, Datum useName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- useName);
-
- idesc = index_openr(ShadowNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-ShadowSysidIndexScan(Relation heapRelation, Datum sysId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_INT4EQ,
- sysId);
-
- idesc = index_openr(ShadowSysidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-StatisticRelidAttnumIndexScan(Relation heapRelation,
- Datum relId,
- Datum attNum)
-{
- Relation idesc;
- ScanKeyData skey[2];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- relId);
-
- ScanKeyEntryInitialize(&skey[1],
- (bits16) 0x0,
- (AttrNumber) 2,
- (RegProcedure) F_INT2EQ,
- attNum);
-
- idesc = index_openr(StatisticRelidAttnumIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-TypeNameIndexScan(Relation heapRelation, Datum typeName)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_NAMEEQ,
- typeName);
-
- idesc = index_openr(TypeNameIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
- index_close(idesc);
- return tuple;
-}
-
-
-HeapTuple
-TypeOidIndexScan(Relation heapRelation, Datum typeId)
-{
- Relation idesc;
- ScanKeyData skey[1];
- HeapTuple tuple;
-
- ScanKeyEntryInitialize(&skey[0],
- (bits16) 0x0,
- (AttrNumber) 1,
- (RegProcedure) F_OIDEQ,
- typeId);
-
- idesc = index_openr(TypeOidIndex);
- tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
index_close(idesc);
return tuple;
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.70 2000/08/06 04:17:16 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.71 2000/11/10 00:33:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/syscache.h"
static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e);
-static Index CatalogCacheComputeHashIndex(CatCache *cacheInP);
-static Index CatalogCacheComputeTupleHashIndex(CatCache *cacheInOutP,
- Relation relation,
- HeapTuple tuple);
-static void CatalogCacheInitializeCache(CatCache *cache,
- Relation relation);
+static Index CatalogCacheComputeHashIndex(CatCache *cache,
+ ScanKey cur_skey);
+static Index CatalogCacheComputeTupleHashIndex(CatCache *cache,
+ HeapTuple tuple);
+static void CatalogCacheInitializeCache(CatCache *cache);
static Datum cc_hashname(PG_FUNCTION_ARGS);
/* ----------------
/* --------------------------------
* CatalogCacheInitializeCache
+ *
+ * This function does final initialization of a catcache: obtain the tuple
+ * descriptor and set up the hash and equality function links. We assume
+ * that the relcache entry can be opened at this point!
* --------------------------------
*/
#ifdef CACHEDEBUG
#define CatalogCacheInitializeCache_DEBUG1 \
-do { \
- elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \
- if (relation) \
- elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \
- else \
- elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \
- cache->cc_relname) \
-} while(0)
+ elog(DEBUG, "CatalogCacheInitializeCache: cache @%p %s", cache, \
+ cache->cc_relname)
#define CatalogCacheInitializeCache_DEBUG2 \
do { \
if (cache->cc_key[i] > 0) { \
- elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %d", \
+ elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d, %u", \
i+1, cache->cc_nkeys, cache->cc_key[i], \
- relation->rd_att->attrs[cache->cc_key[i] - 1]->attlen); \
+ tupdesc->attrs[cache->cc_key[i] - 1]->atttypid); \
} else { \
elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \
i+1, cache->cc_nkeys, cache->cc_key[i]); \
#endif
static void
-CatalogCacheInitializeCache(CatCache * cache,
- Relation relation)
+CatalogCacheInitializeCache(CatCache *cache)
{
+ Relation relation;
MemoryContext oldcxt;
- bool didopen = false;
- short i;
TupleDesc tupdesc;
+ short i;
CatalogCacheInitializeCache_DEBUG1;
- /* ----------------
- * If no relation was passed we must open it to get access to
- * its fields.
- * ----------------
+ /*
+ * Open the relation without locking --- we only need the tupdesc,
+ * which we assume will never change ...
*/
- if (!RelationIsValid(relation))
- {
- relation = heap_openr(cache->cc_relname, NoLock);
- didopen = true;
- }
+ relation = heap_openr(cache->cc_relname, NoLock);
+ Assert(RelationIsValid(relation));
/* ----------------
* switch to the cache context so our allocations
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
/* ----------------
- * initialize the cache's relation id and tuple descriptor
+ * copy the relcache's tuple descriptor to permanent cache storage
* ----------------
*/
- Assert(RelationIsValid(relation));
- cache->relationId = RelationGetRelid(relation);
tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation));
- cache->cc_tupdesc = tupdesc;
- CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: relid %u, %d keys",
- cache->relationId, cache->cc_nkeys);
+ /* ----------------
+ * return to the caller's memory context and close the rel
+ * ----------------
+ */
+ MemoryContextSwitchTo(oldcxt);
+
+ heap_close(relation, NoLock);
+
+ CACHE3_elog(DEBUG, "CatalogCacheInitializeCache: %s, %d keys",
+ cache->cc_relname, cache->cc_nkeys);
/* ----------------
* initialize cache's key information
*/
for (i = 0; i < cache->cc_nkeys; ++i)
{
+ Oid keytype;
+
CatalogCacheInitializeCache_DEBUG2;
if (cache->cc_key[i] > 0)
{
- Oid keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid;
+ keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid;
+ }
+ else
+ {
+ if (cache->cc_key[i] != ObjectIdAttributeNumber)
+ elog(FATAL, "CatalogCacheInit: only sys attr supported is OID");
+ keytype = OIDOID;
+ }
- cache->cc_hashfunc[i] = GetCCHashFunc(keytype);
+ cache->cc_hashfunc[i] = GetCCHashFunc(keytype);
+ /*
+ * If GetCCHashFunc liked the type, safe to index into eqproc[]
+ */
+ cache->cc_skey[i].sk_procedure = EQPROC(keytype);
- /*
- * If GetCCHashFunc liked the type, safe to index into
- * eqproc[]
- */
- cache->cc_skey[i].sk_procedure = EQPROC(keytype);
+ fmgr_info(cache->cc_skey[i].sk_procedure,
+ &cache->cc_skey[i].sk_func);
+ cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
- fmgr_info(cache->cc_skey[i].sk_procedure,
- &cache->cc_skey[i].sk_func);
- cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
+ /* Initialize sk_attno suitably for index scans */
+ cache->cc_skey[i].sk_attno = i+1;
- CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %x",
- RelationGetRelationName(relation),
- i,
- cache);
- }
+ CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %p",
+ cache->cc_relname,
+ i,
+ cache);
}
/* ----------------
- * return to the caller's memory context
+ * mark this cache fully initialized
* ----------------
*/
- MemoryContextSwitchTo(oldcxt);
-
- /* ----------------
- * close the relation if we opened it
- * ----------------
- */
- if (didopen)
- heap_close(relation, NoLock);
-
- /* ----------------
- * initialize index information for the cache. this
- * should only be done once per cache.
- * ----------------
- */
- if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
- {
- if (!IsIgnoringSystemIndexes() && RelationGetForm(relation)->relhasindex)
- {
-
- /*
- * If the index doesn't exist we are in trouble.
- */
- relation = index_openr(cache->cc_indname);
- Assert(relation);
- cache->indexId = RelationGetRelid(relation);
- index_close(relation);
- }
- else
- cache->cc_indname = NULL;
- }
+ cache->cc_tupdesc = tupdesc;
}
/* --------------------------------
* --------------------------------
*/
static Index
-CatalogCacheComputeHashIndex(CatCache * cacheInP)
+CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey)
{
uint32 hashIndex = 0;
- CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %x",
- cacheInP->cc_relname,
- cacheInP->cc_nkeys,
- cacheInP);
+ CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %p",
+ cache->cc_relname,
+ cache->cc_nkeys,
+ cache);
- switch (cacheInP->cc_nkeys)
+ switch (cache->cc_nkeys)
{
case 4:
hashIndex ^=
- DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[3],
- cacheInP->cc_skey[3].sk_argument)) << 9;
+ DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[3],
+ cur_skey[3].sk_argument)) << 9;
/* FALLTHROUGH */
case 3:
hashIndex ^=
- DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[2],
- cacheInP->cc_skey[2].sk_argument)) << 6;
+ DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[2],
+ cur_skey[2].sk_argument)) << 6;
/* FALLTHROUGH */
case 2:
hashIndex ^=
- DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[1],
- cacheInP->cc_skey[1].sk_argument)) << 3;
+ DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[1],
+ cur_skey[1].sk_argument)) << 3;
/* FALLTHROUGH */
case 1:
hashIndex ^=
- DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[0],
- cacheInP->cc_skey[0].sk_argument));
+ DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[0],
+ cur_skey[0].sk_argument));
break;
default:
- elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys);
+ elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cache->cc_nkeys);
break;
}
- hashIndex %= (uint32) cacheInP->cc_size;
+ hashIndex %= (uint32) cache->cc_size;
return (Index) hashIndex;
}
* --------------------------------
*/
static Index
-CatalogCacheComputeTupleHashIndex(CatCache * cacheInOutP,
- Relation relation,
+CatalogCacheComputeTupleHashIndex(CatCache *cache,
HeapTuple tuple)
{
+ ScanKeyData cur_skey[4];
bool isNull = false;
- /* XXX is this really needed? */
- if (cacheInOutP->relationId == InvalidOid)
- CatalogCacheInitializeCache(cacheInOutP, relation);
+ /* Copy pre-initialized overhead data for scankey */
+ memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
- switch (cacheInOutP->cc_nkeys)
+ /* Now extract key fields from tuple, insert into scankey */
+ switch (cache->cc_nkeys)
{
case 4:
- cacheInOutP->cc_skey[3].sk_argument =
- (cacheInOutP->cc_key[3] == ObjectIdAttributeNumber)
- ? (Datum) tuple->t_data->t_oid
+ cur_skey[3].sk_argument =
+ (cache->cc_key[3] == ObjectIdAttributeNumber)
+ ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple,
- cacheInOutP->cc_key[3],
- RelationGetDescr(relation),
+ cache->cc_key[3],
+ cache->cc_tupdesc,
&isNull);
Assert(!isNull);
/* FALLTHROUGH */
case 3:
- cacheInOutP->cc_skey[2].sk_argument =
- (cacheInOutP->cc_key[2] == ObjectIdAttributeNumber)
- ? (Datum) tuple->t_data->t_oid
+ cur_skey[2].sk_argument =
+ (cache->cc_key[2] == ObjectIdAttributeNumber)
+ ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple,
- cacheInOutP->cc_key[2],
- RelationGetDescr(relation),
+ cache->cc_key[2],
+ cache->cc_tupdesc,
&isNull);
Assert(!isNull);
/* FALLTHROUGH */
case 2:
- cacheInOutP->cc_skey[1].sk_argument =
- (cacheInOutP->cc_key[1] == ObjectIdAttributeNumber)
- ? (Datum) tuple->t_data->t_oid
+ cur_skey[1].sk_argument =
+ (cache->cc_key[1] == ObjectIdAttributeNumber)
+ ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple,
- cacheInOutP->cc_key[1],
- RelationGetDescr(relation),
+ cache->cc_key[1],
+ cache->cc_tupdesc,
&isNull);
Assert(!isNull);
/* FALLTHROUGH */
case 1:
- cacheInOutP->cc_skey[0].sk_argument =
- (cacheInOutP->cc_key[0] == ObjectIdAttributeNumber)
- ? (Datum) tuple->t_data->t_oid
+ cur_skey[0].sk_argument =
+ (cache->cc_key[0] == ObjectIdAttributeNumber)
+ ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple,
- cacheInOutP->cc_key[0],
- RelationGetDescr(relation),
+ cache->cc_key[0],
+ cache->cc_tupdesc,
&isNull);
Assert(!isNull);
break;
default:
elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys",
- cacheInOutP->cc_nkeys);
+ cache->cc_nkeys);
break;
}
- return CatalogCacheComputeHashIndex(cacheInOutP);
+ return CatalogCacheComputeHashIndex(cache, cur_skey);
}
/* --------------------------------
* public functions
*
* ResetSystemCache
- * SystemCacheAbort
- * InitIndexedSysCache
* InitSysCache
* SearchSysCache
* RelationInvalidateCatalogCacheTuple
CACHE1_elog(DEBUG, "end of ResetSystemCache call");
}
-/* --------------------------------
- * SystemCacheAbort
- *
- * This routine is called to clean up catcache state as needed during
- * transaction abort.
- * --------------------------------
- */
-void
-SystemCacheAbort(void)
-{
- CatCache *cache;
-
- /* ----------------
- * clear the "cache busy" flags, which may have been left set if we
- * elog'd out during a cache lookup attempt.
- * ----------------
- */
- for (cache = Caches; PointerIsValid(cache); cache = cache->cc_next)
- cache->busy = false;
-}
-
/* --------------------------------
* SystemCacheRelationFlushed
*
#ifdef CACHEDEBUG
#define InitSysCache_DEBUG1 \
do { \
- elog(DEBUG, "InitSysCache: rid=%u id=%d nkeys=%d size=%d\n", \
- cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \
- for (i = 0; i < nkeys; i += 1) \
- { \
- elog(DEBUG, "InitSysCache: key=%d skey=[%d %d %d %d]\n", \
- cp->cc_key[i], \
- cp->cc_skey[i].sk_flags, \
- cp->cc_skey[i].sk_attno, \
- cp->cc_skey[i].sk_procedure, \
- cp->cc_skey[i].sk_argument); \
- } \
+ elog(DEBUG, "InitSysCache: rel=%s id=%d nkeys=%d size=%d\n", \
+ cp->cc_relname, cp->id, cp->cc_nkeys, cp->cc_size); \
} while(0)
#else
#define InitSysCache_DEBUG1
#endif
-CatCache *
-InitSysCache(char *relname,
+CatCache *
+InitSysCache(int id,
+ char *relname,
char *indname,
- int id,
int nkeys,
- int *key,
- ScanFunc iScanfuncP)
+ int *key)
{
CatCache *cp;
- int i;
MemoryContext oldcxt;
+ int i;
/* ----------------
* first switch to the cache context so our allocations
* cache's other internal fields.
* ----------------
*/
- cp->relationId = InvalidOid;
- cp->indexId = InvalidOid;
cp->cc_relname = relname;
cp->cc_indname = indname;
cp->cc_tupdesc = (TupleDesc) NULL;
cp->id = id;
- cp->busy = false;
cp->cc_maxtup = MAXTUP;
cp->cc_size = NCCBUCK;
cp->cc_nkeys = nkeys;
- cp->cc_iscanfunc = iScanfuncP;
-
- /* ----------------
- * partially initialize the cache's key information
- * CatalogCacheInitializeCache() will do the rest
- * ----------------
- */
for (i = 0; i < nkeys; ++i)
- {
cp->cc_key[i] = key[i];
- if (!key[i])
- elog(FATAL, "InitSysCache: called with 0 key[%d]", i);
- if (key[i] < 0)
- {
- if (key[i] != ObjectIdAttributeNumber)
- elog(FATAL, "InitSysCache: called with %d key[%d]", key[i], i);
- else
- {
- cp->cc_hashfunc[i] = GetCCHashFunc(OIDOID);
- ScanKeyEntryInitialize(&cp->cc_skey[i],
- (bits16) 0,
- (AttrNumber) key[i],
- (RegProcedure) F_OIDEQ,
- (Datum) 0);
- continue;
- }
- }
-
- cp->cc_skey[i].sk_attno = key[i];
- }
/* ----------------
* all done. new cache is initialized. print some debugging
/* --------------------------------
- * SearchSelfReferences
+ * IndexScanOK
*
- * This call searches for self-referencing information,
- * which causes infinite recursion in the system catalog cache.
- * This code short-circuits the normal index lookup for cache loads
- * in those cases and replaces it with a heap scan.
- *
- * cache should already be initialized
+ * This function checks for tuples that will be fetched by
+ * IndexSupportInitialize() during relcache initialization for
+ * certain system indexes that support critical syscaches.
+ * We can't use an indexscan to fetch these, else we'll get into
+ * infinite recursion. A plain heap scan will work, however.
* --------------------------------
*/
-static HeapTuple
-SearchSelfReferences(CatCache * cache)
+static bool
+IndexScanOK(CatCache *cache, ScanKey cur_skey)
{
- HeapTuple ntp;
- Relation rel;
-
if (cache->id == INDEXRELID)
{
static Oid indexSelfOid = InvalidOid;
- static HeapTuple indexSelfTuple = NULL;
+ /* One-time lookup of the OID of pg_index_indexrelid_index */
if (!OidIsValid(indexSelfOid))
{
+ Relation rel;
ScanKeyData key;
HeapScanDesc sd;
+ HeapTuple ntp;
- /* Find oid of pg_index_indexrelid_index */
rel = heap_openr(RelationRelationName, AccessShareLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
- F_NAMEEQ, PointerGetDatum(IndexRelidIndex));
+ F_NAMEEQ,
+ PointerGetDatum(IndexRelidIndex));
sd = heap_beginscan(rel, false, SnapshotNow, 1, &key);
ntp = heap_getnext(sd, 0);
if (!HeapTupleIsValid(ntp))
heap_endscan(sd);
heap_close(rel, AccessShareLock);
}
- /* Looking for something other than pg_index_indexrelid_index? */
- if ((Oid) cache->cc_skey[0].sk_argument != indexSelfOid)
- return (HeapTuple) 0;
- /* Do we need to load our private copy of the tuple? */
- if (!HeapTupleIsValid(indexSelfTuple))
- {
- HeapScanDesc sd;
- MemoryContext oldcxt;
-
- rel = heap_open(cache->relationId, AccessShareLock);
- sd = heap_beginscan(rel, false, SnapshotNow, 1, cache->cc_skey);
- ntp = heap_getnext(sd, 0);
- if (!HeapTupleIsValid(ntp))
- elog(ERROR, "SearchSelfReferences: tuple not found");
- if (!CacheMemoryContext)
- CreateCacheMemoryContext();
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- indexSelfTuple = heap_copytuple(ntp);
- MemoryContextSwitchTo(oldcxt);
- heap_endscan(sd);
- heap_close(rel, AccessShareLock);
- }
- return indexSelfTuple;
+ /* Looking for pg_index_indexrelid_index? */
+ if (DatumGetObjectId(cur_skey[0].sk_argument) == indexSelfOid)
+ return false;
}
else if (cache->id == OPEROID)
{
- /* bootstrapping this requires preloading a range of rows. bjm */
- static HeapTuple operatorSelfTuple[MAX_OIDCMP - MIN_OIDCMP + 1];
- Oid lookup_oid = (Oid) cache->cc_skey[0].sk_argument;
+ /* Looking for an OID comparison function? */
+ Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument);
- if (lookup_oid < MIN_OIDCMP || lookup_oid > MAX_OIDCMP)
- return (HeapTuple) 0;
-
- if (!HeapTupleIsValid(operatorSelfTuple[lookup_oid - MIN_OIDCMP]))
- {
- HeapScanDesc sd;
- MemoryContext oldcxt;
-
- rel = heap_open(cache->relationId, AccessShareLock);
- sd = heap_beginscan(rel, false, SnapshotNow, 1, cache->cc_skey);
- ntp = heap_getnext(sd, 0);
- if (!HeapTupleIsValid(ntp))
- elog(ERROR, "SearchSelfReferences: tuple not found");
- if (!CacheMemoryContext)
- CreateCacheMemoryContext();
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- operatorSelfTuple[lookup_oid - MIN_OIDCMP] = heap_copytuple(ntp);
- MemoryContextSwitchTo(oldcxt);
- heap_endscan(sd);
- heap_close(rel, AccessShareLock);
- }
- return operatorSelfTuple[lookup_oid - MIN_OIDCMP];
+ if (lookup_oid >= MIN_OIDCMP && lookup_oid <= MAX_OIDCMP)
+ return false;
}
- else
- return (HeapTuple) 0;
+ /* Normal case, allow index scan */
+ return true;
}
/* --------------------------------
* --------------------------------
*/
HeapTuple
-SearchSysCache(CatCache * cache,
+SearchSysCache(CatCache *cache,
Datum v1,
Datum v2,
Datum v3,
Datum v4)
{
- unsigned hash;
+ ScanKeyData cur_skey[4];
+ Index hash;
CatCTup *ct = NULL;
CatCTup *nct;
CatCTup *nct2;
* one-time startup overhead
* ----------------
*/
- if (cache->relationId == InvalidOid)
- CatalogCacheInitializeCache(cache, NULL);
+ if (cache->cc_tupdesc == NULL)
+ CatalogCacheInitializeCache(cache);
/* ----------------
* initialize the search key information
* ----------------
*/
- cache->cc_skey[0].sk_argument = v1;
- cache->cc_skey[1].sk_argument = v2;
- cache->cc_skey[2].sk_argument = v3;
- cache->cc_skey[3].sk_argument = v4;
-
- /*
- * resolve self referencing informtion
- */
- if ((ntp = SearchSelfReferences(cache)) != NULL)
- return ntp;
+ memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
+ cur_skey[0].sk_argument = v1;
+ cur_skey[1].sk_argument = v2;
+ cur_skey[2].sk_argument = v3;
+ cur_skey[3].sk_argument = v4;
/* ----------------
* find the hash bucket in which to look for the tuple
* ----------------
*/
- hash = CatalogCacheComputeHashIndex(cache);
+ hash = CatalogCacheComputeHashIndex(cache, cur_skey);
/* ----------------
* scan the hash bucket until we find a match or exhaust our tuples
HeapKeyTest(ct->ct_tup,
cache->cc_tupdesc,
cache->cc_nkeys,
- cache->cc_skey,
+ cur_skey,
res);
if (res)
break;
* retrieve it directly from the relation. If it's found,
* we add it to the cache.
*
- * To guard against possible infinite recursion, we mark this cache
- * "busy" while trying to load a new entry for it. It is OK to
- * recursively invoke SearchSysCache for a different cache, but
- * a recursive call for the same cache will error out. (We could
- * store the specific key(s) being looked for, and consider only
- * a recursive request for the same key to be an error, but this
- * simple scheme is sufficient for now.)
+ * NOTE: it is possible for recursive cache lookups to occur while
+ * reading the relation --- for example, due to shared-cache-inval
+ * messages being processed during heap_open(). This is OK. It's
+ * even possible for one of those lookups to find and enter the
+ * very same tuple we are trying to fetch here. If that happens,
+ * we will enter a second copy of the tuple into the cache. The
+ * first copy will never be referenced again, and will eventually
+ * age out of the cache, so there's no functional problem. This case
+ * is rare enough that it's not worth expending extra cycles to detect.
* ----------------
*/
- if (cache->busy)
- elog(ERROR, "SearchSysCache: recursive use of cache %d", cache->id);
- cache->busy = true;
-
/* ----------------
* open the relation associated with the cache
* ----------------
*/
- relation = heap_open(cache->relationId, AccessShareLock);
- CACHE2_elog(DEBUG, "SearchSysCache(%s)",
- RelationGetRelationName(relation));
+ relation = heap_openr(cache->cc_relname, AccessShareLock);
/* ----------------
* Scan the relation to find the tuple. If there's an index, and
- * if this isn't bootstrap (initdb) time, use the index.
+ * if it's safe to do so, use the index. Else do a heap scan.
* ----------------
*/
- CACHE1_elog(DEBUG, "SearchSysCache: performing scan");
+ ntp = NULL;
- if ((RelationGetForm(relation))->relhasindex
- && !IsIgnoringSystemIndexes())
+ if ((RelationGetForm(relation))->relhasindex &&
+ !IsIgnoringSystemIndexes() &&
+ IndexScanOK(cache, cur_skey))
{
- HeapTuple indextp;
-
- /* We call the scanfunc with all four arguments to satisfy the
- * declared prototype, even though the function will likely not
- * use all four.
- */
- indextp = cache->cc_iscanfunc(relation, v1, v2, v3, v4);
-
- /* ----------
- * If we got a tuple copy it into our context. wieck - 10/18/1996
- * And free the tuple that was allocated in the
- * transaction's context. tgl - 02/03/2000
- * ----------
- */
- if (HeapTupleIsValid(indextp))
+ Relation idesc;
+ IndexScanDesc isd;
+ RetrieveIndexResult indexRes;
+ HeapTupleData tuple;
+ Buffer buffer;
+
+ CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan",
+ cache->cc_relname);
+
+ idesc = index_openr(cache->cc_indname);
+ isd = index_beginscan(idesc, false, cache->cc_nkeys, cur_skey);
+ tuple.t_datamcxt = CurrentMemoryContext;
+ tuple.t_data = NULL;
+ while ((indexRes = index_getnext(isd, ForwardScanDirection)))
{
- oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- ntp = heap_copytuple(indextp);
- MemoryContextSwitchTo(oldcxt);
- heap_freetuple(indextp);
+ tuple.t_self = indexRes->heap_iptr;
+ heap_fetch(relation, SnapshotNow, &tuple, &buffer);
+ pfree(indexRes);
+ if (tuple.t_data != NULL)
+ {
+ /* Copy tuple into our context */
+ oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+ ntp = heap_copytuple(&tuple);
+ MemoryContextSwitchTo(oldcxt);
+ ReleaseBuffer(buffer);
+ break;
+ }
}
+ index_endscan(isd);
+ index_close(idesc);
}
else
{
HeapScanDesc sd;
+ int i;
+
+ CACHE2_elog(DEBUG, "SearchSysCache(%s): performing heap scan",
+ cache->cc_relname);
+
+ /*
+ * For a heap scan, sk_attno has to be set to the heap attribute
+ * number(s), not the index attribute numbers.
+ */
+ for (i = 0; i < cache->cc_nkeys; ++i)
+ cur_skey[i].sk_attno = cache->cc_key[i];
sd = heap_beginscan(relation, 0, SnapshotNow,
- cache->cc_nkeys, cache->cc_skey);
+ cache->cc_nkeys, cur_skey);
ntp = heap_getnext(sd, 0);
-
if (HeapTupleIsValid(ntp))
{
- CACHE1_elog(DEBUG, "SearchSysCache: found tuple");
+ /* Copy tuple into our context */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
ntp = heap_copytuple(ntp);
MemoryContextSwitchTo(oldcxt);
heap_endscan(sd);
}
- cache->busy = false;
-
/* ----------------
* scan is complete. if tup is valid, we can add it to the cache.
* note we have already copied it into the cache memory context.
*/
Dlelem *lru_elt;
+ CACHE1_elog(DEBUG, "SearchSysCache: found tuple");
+
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
/*
if (ct != nct) /* shouldn't be possible, but be safe... */
{
CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal",
- RelationGetRelationName(relation));
+ cache->cc_relname);
CatCacheRemoveCTup(cache, elt);
}
}
CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples",
- RelationGetRelationName(relation),
- cache->cc_ntup, cache->cc_maxtup);
+ cache->cc_relname, cache->cc_ntup, cache->cc_maxtup);
CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d",
- RelationGetRelationName(relation), hash);
+ cache->cc_relname, hash);
}
/* ----------------
void (*function) (int, Index, ItemPointer))
{
CatCache *ccp;
- Oid relationId;
/* ----------------
* sanity checks
* in the proper hash bucket
* ----------------
*/
- relationId = RelationGetRelid(relation);
for (ccp = Caches; ccp; ccp = ccp->cc_next)
{
- if (relationId != ccp->relationId)
+ if (strcmp(ccp->cc_relname, RelationGetRelationName(relation)) != 0)
continue;
+ /* Just in case cache hasn't finished initialization yet... */
+ if (ccp->cc_tupdesc == NULL)
+ CatalogCacheInitializeCache(ccp);
+
(*function) (ccp->id,
- CatalogCacheComputeTupleHashIndex(ccp, relation, tuple),
+ CatalogCacheComputeTupleHashIndex(ccp, tuple),
&tuple->t_self);
}
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.115 2000/11/08 22:10:01 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.116 2000/11/10 00:33:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* careful....
*
*/
+#include "postgres.h"
+
#include <sys/types.h>
#include <errno.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
-#include "postgres.h"
-
-#include "utils/builtins.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/istrat.h"
#include "lib/hasht.h"
#include "miscadmin.h"
#include "storage/smgr.h"
+#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/memutils.h"
* This is a special cut-down version of RelationBuildDesc()
* used by RelationCacheInitialize() in initializing the relcache.
* The relation descriptor is built just from the supplied parameters,
- * without actually looking at any system table entries.
+ * without actually looking at any system table entries. We cheat
+ * quite a lot since we only need to work for a few basic system
+ * catalogs...
*
* NOTE: we assume we are already switched into CacheMemoryContext.
* --------------------------------
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
/* ----------------
- * initialize the relation lock manager information
+ * initialize the relation's lock manager and RelFileNode information
* ----------------
*/
RelationInitLockInfo(relation); /* see lmgr.c */
relation->rd_rel->relfilenode = RelationGetRelid(relation);
/* ----------------
- * add new reldesc to relcache
+ * initialize the rel-has-index flag, using hardwired knowledge
* ----------------
*/
- RelationCacheInsert(relation);
+ relation->rd_rel->relhasindex = false;
- /*
- * Determining this requires a scan on pg_class, but to do the scan
- * the rdesc for pg_class must already exist. Therefore we must do
- * the check (and possible set) after cache insertion.
- *
- * XXX I believe the above comment is misguided; we should be running
- * in bootstrap or init processing mode here, and CatalogHasIndex
- * relies on hard-wired info in those cases.
+ /* In bootstrap mode, we have no indexes */
+ if (!IsBootstrapProcessingMode())
+ {
+ for (i = 0; IndexedCatalogNames[i] != NULL; i++)
+ {
+ if (strcmp(IndexedCatalogNames[i], relationName) == 0)
+ {
+ relation->rd_rel->relhasindex = true;
+ break;
+ }
+ }
+ }
+
+ /* ----------------
+ * add new reldesc to relcache
+ * ----------------
*/
- relation->rd_rel->relhasindex =
- CatalogHasIndex(relationName, RelationGetRelid(relation));
+ RelationCacheInsert(relation);
}
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.55 2000/06/20 01:41:22 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.56 2000/11/10 00:33:10 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
Add your entry to the cacheinfo[] array below. All cache lists are
alphabetical, so add it in the proper place. Specify the relation
- name, number of arguments, argument attribute numbers, index name,
- and index lookup function.
+ name, index name, number of keys, and key attribute numbers.
In include/catalog/indexing.h, add a define for the number of indexes
on the relation, add define(s) for the index name(s), add an extern
- array to hold the index names, define the index lookup function
- prototype, and use DECLARE_UNIQUE_INDEX to define the index. Cache
- lookups return only one row, so the index should be unique.
+ array to hold the index names, and use DECLARE_UNIQUE_INDEX to define
+ the index. Cache lookups return only one row, so the index should be
+ unique in most cases.
In backend/catalog/indexing.c, initialize the relation array with
- the index names for the relation, and create the index lookup function.
- Pick one that has similar arguments and copy that one, but keep the
- function names in the same order as the cache list for clarity.
+ the index names for the relation.
Finally, any place your relation gets heap_insert() or
heap_update calls, include code to do a CatalogIndexInsert() to update
struct cachedesc
{
char *name; /* name of the relation being cached */
+ char *indname; /* name of index relation for this cache */
int nkeys; /* # of keys needed for cache lookup */
int key[4]; /* attribute numbers of key attrs */
- char *indname; /* name of index relation for this cache */
- ScanFunc iScanFunc; /* function to handle index scans */
};
static struct cachedesc cacheinfo[] = {
{AggregateRelationName, /* AGGNAME */
+ AggregateNameTypeIndex,
2,
{
Anum_pg_aggregate_aggname,
Anum_pg_aggregate_aggbasetype,
0,
0
- },
- AggregateNameTypeIndex,
- (ScanFunc) AggregateNameTypeIndexScan},
+ }},
{AccessMethodRelationName, /* AMNAME */
+ AmNameIndex,
1,
{
Anum_pg_am_amname,
0,
0,
0
- },
- AmNameIndex,
- (ScanFunc) AmNameIndexScan},
+ }},
{AccessMethodOperatorRelationName, /* AMOPOPID */
+ AccessMethodOpidIndex,
3,
{
Anum_pg_amop_amopclaid,
Anum_pg_amop_amopopr,
Anum_pg_amop_amopid,
0
- },
- AccessMethodOpidIndex,
- (ScanFunc) AccessMethodOpidIndexScan},
+ }},
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
+ AccessMethodStrategyIndex,
3,
{
Anum_pg_amop_amopid,
Anum_pg_amop_amopclaid,
Anum_pg_amop_amopstrategy,
0
- },
- AccessMethodStrategyIndex,
- (ScanFunc) AccessMethodStrategyIndexScan},
+ }},
{AttributeRelationName, /* ATTNAME */
+ AttributeRelidNameIndex,
2,
{
Anum_pg_attribute_attrelid,
Anum_pg_attribute_attname,
0,
0
- },
- AttributeRelidNameIndex,
- (ScanFunc) AttributeRelidNameIndexScan},
+ }},
{AttributeRelationName, /* ATTNUM */
+ AttributeRelidNumIndex,
2,
{
Anum_pg_attribute_attrelid,
Anum_pg_attribute_attnum,
0,
0
- },
- AttributeRelidNumIndex,
- (ScanFunc) AttributeRelidNumIndexScan},
+ }},
{OperatorClassRelationName, /* CLADEFTYPE */
+ OpclassDeftypeIndex,
1,
{
Anum_pg_opclass_opcdeftype,
0,
0,
0
- },
- OpclassDeftypeIndex,
- (ScanFunc) OpclassDeftypeIndexScan},
+ }},
{OperatorClassRelationName, /* CLANAME */
+ OpclassNameIndex,
1,
{
Anum_pg_opclass_opcname,
0,
0,
0
- },
- OpclassNameIndex,
- (ScanFunc) OpclassNameIndexScan},
+ }},
{GroupRelationName, /* GRONAME */
+ GroupNameIndex,
1,
{
Anum_pg_group_groname,
0,
0,
0
- },
- GroupNameIndex,
- (ScanFunc) GroupNameIndexScan},
+ }},
{GroupRelationName, /* GROSYSID */
+ GroupSysidIndex,
1,
{
Anum_pg_group_grosysid,
0,
0,
0
- },
- GroupSysidIndex,
- (ScanFunc) GroupSysidIndexScan},
+ }},
{IndexRelationName, /* INDEXRELID */
+ IndexRelidIndex,
1,
{
Anum_pg_index_indexrelid,
0,
0,
0
- },
- IndexRelidIndex,
- (ScanFunc) IndexRelidIndexScan},
+ }},
{InheritsRelationName, /* INHRELID */
+ InheritsRelidSeqnoIndex,
2,
{
Anum_pg_inherits_inhrelid,
Anum_pg_inherits_inhseqno,
0,
0
- },
- InheritsRelidSeqnoIndex,
- (ScanFunc) InheritsRelidSeqnoIndexScan},
+ }},
{LanguageRelationName, /* LANGNAME */
+ LanguageNameIndex,
1,
{
Anum_pg_language_lanname,
0,
0,
0
- },
- LanguageNameIndex,
- (ScanFunc) LanguageNameIndexScan},
+ }},
{LanguageRelationName, /* LANGOID */
+ LanguageOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- LanguageOidIndex,
- (ScanFunc) LanguageOidIndexScan},
+ }},
{ListenerRelationName, /* LISTENREL */
+ ListenerPidRelnameIndex,
2,
{
Anum_pg_listener_pid,
Anum_pg_listener_relname,
0,
0
- },
- ListenerPidRelnameIndex,
- (ScanFunc) ListenerPidRelnameIndexScan},
+ }},
{OperatorRelationName, /* OPERNAME */
+ OperatorNameIndex,
4,
{
Anum_pg_operator_oprname,
Anum_pg_operator_oprleft,
Anum_pg_operator_oprright,
Anum_pg_operator_oprkind
- },
- OperatorNameIndex,
- (ScanFunc) OperatorNameIndexScan},
+ }},
{OperatorRelationName, /* OPEROID */
+ OperatorOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- OperatorOidIndex,
- (ScanFunc) OperatorOidIndexScan},
+ }},
{ProcedureRelationName, /* PROCNAME */
+ ProcedureNameIndex,
3,
{
Anum_pg_proc_proname,
Anum_pg_proc_pronargs,
Anum_pg_proc_proargtypes,
0
- },
- ProcedureNameIndex,
- (ScanFunc) ProcedureNameIndexScan},
+ }},
{ProcedureRelationName, /* PROCOID */
+ ProcedureOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- ProcedureOidIndex,
- (ScanFunc) ProcedureOidIndexScan},
+ }},
{RelationRelationName, /* RELNAME */
+ ClassNameIndex,
1,
{
Anum_pg_class_relname,
0,
0,
0
- },
- ClassNameIndex,
- (ScanFunc) ClassNameIndexScan},
+ }},
{RelationRelationName, /* RELOID */
+ ClassOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- ClassOidIndex,
- (ScanFunc) ClassOidIndexScan},
+ }},
{RewriteRelationName, /* REWRITENAME */
+ RewriteRulenameIndex,
1,
{
Anum_pg_rewrite_rulename,
0,
0,
0
- },
- RewriteRulenameIndex,
- (ScanFunc) RewriteRulenameIndexScan},
+ }},
{RewriteRelationName, /* RULEOID */
+ RewriteOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- RewriteOidIndex,
- (ScanFunc) RewriteOidIndexScan},
+ }},
{ShadowRelationName, /* SHADOWNAME */
+ ShadowNameIndex,
1,
{
Anum_pg_shadow_usename,
0,
0,
0
- },
- ShadowNameIndex,
- (ScanFunc) ShadowNameIndexScan},
+ }},
{ShadowRelationName, /* SHADOWSYSID */
+ ShadowSysidIndex,
1,
{
Anum_pg_shadow_usesysid,
0,
0,
0
- },
- ShadowSysidIndex,
- (ScanFunc) ShadowSysidIndexScan},
+ }},
{StatisticRelationName, /* STATRELID */
+ StatisticRelidAttnumIndex,
2,
{
Anum_pg_statistic_starelid,
Anum_pg_statistic_staattnum,
0,
0
- },
- StatisticRelidAttnumIndex,
- (ScanFunc) StatisticRelidAttnumIndexScan},
+ }},
{TypeRelationName, /* TYPENAME */
+ TypeNameIndex,
1,
{
Anum_pg_type_typname,
0,
0,
0
- },
- TypeNameIndex,
- (ScanFunc) TypeNameIndexScan},
+ }},
{TypeRelationName, /* TYPEOID */
+ TypeOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
- },
- TypeOidIndex,
- (ScanFunc) TypeOidIndexScan}
+ }}
};
static CatCache *SysCache[lengthof(cacheinfo)];
{
Assert(!PointerIsValid(SysCache[cacheId]));
- SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
+ SysCache[cacheId] = InitSysCache(cacheId,
+ cacheinfo[cacheId].name,
cacheinfo[cacheId].indname,
- cacheId,
cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key,
- cacheinfo[cacheId].iScanFunc);
+ cacheinfo[cacheId].key);
if (!PointerIsValid(SysCache[cacheId]))
{
elog(ERROR,
if (!PointerIsValid(SysCache[cacheId]))
{
- SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
+ SysCache[cacheId] = InitSysCache(cacheId,
+ cacheinfo[cacheId].name,
cacheinfo[cacheId].indname,
- cacheId,
cacheinfo[cacheId].nkeys,
- cacheinfo[cacheId].key,
- cacheinfo[cacheId].iScanFunc);
+ cacheinfo[cacheId].key);
if (!PointerIsValid(SysCache[cacheId]))
elog(ERROR,
"InitCatalogCache: Can't init cache %s(%d)",
if (cacheId < 0 || cacheId >= SysCacheSize)
elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId);
if (!PointerIsValid(SysCache[cacheId]) ||
- SysCache[cacheId]->relationId == InvalidOid ||
!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);
/*-------------------------------------------------------------------------
*
* indexing.h
- * This include provides some definitions to support indexing
+ * This file provides some definitions to support indexing
* on system catalogs
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: indexing.h,v 1.45 2000/10/24 01:38:41 tgl Exp $
+ * $Id: indexing.h,v 1.46 2000/11/10 00:33:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void CatalogCloseIndices(int nIndices, Relation *idescs);
extern void CatalogIndexInsert(Relation *idescs, int nIndices,
Relation heapRelation, HeapTuple heapTuple);
-extern bool CatalogHasIndex(char *catName, Oid catId);
/*
- * Functions for each index to perform the necessary scan on a cache miss.
+ * Canned functions for indexscans on certain system indexes.
* All index-value arguments should be passed as Datum for portability!
*/
-extern HeapTuple AccessMethodOpidIndexScan(Relation heapRelation,
- Datum claid, Datum opopr, Datum opid);
-extern HeapTuple AccessMethodStrategyIndexScan(Relation heapRelation,
- Datum opid, Datum claid, Datum opstrategy);
-extern HeapTuple AggregateNameTypeIndexScan(Relation heapRelation,
- Datum aggName, Datum aggType);
-extern HeapTuple AmNameIndexScan(Relation heapRelation, Datum amName);
-extern HeapTuple AttributeRelidNameIndexScan(Relation heapRelation,
- Datum relid, Datum attname);
extern HeapTuple AttributeRelidNumIndexScan(Relation heapRelation,
- Datum relid, Datum attnum);
-extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
+ Datum relid, Datum attnum);
extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
extern HeapTuple ClassOidIndexScan(Relation heapRelation, Datum relId);
-extern HeapTuple GroupNameIndexScan(Relation heapRelation, Datum groName);
-extern HeapTuple GroupSysidIndexScan(Relation heapRelation, Datum sysId);
-extern HeapTuple IndexRelidIndexScan(Relation heapRelation, Datum relid);
-extern HeapTuple InheritsRelidSeqnoIndexScan(Relation heapRelation,
- Datum relid, Datum seqno);
-extern HeapTuple LanguageNameIndexScan(Relation heapRelation, Datum lanName);
-extern HeapTuple LanguageOidIndexScan(Relation heapRelation, Datum lanId);
-extern HeapTuple ListenerPidRelnameIndexScan(Relation heapRelation,
- Datum pid, Datum relName);
-extern HeapTuple OpclassDeftypeIndexScan(Relation heapRelation, Datum defType);
-extern HeapTuple OpclassNameIndexScan(Relation heapRelation, Datum opcName);
-extern HeapTuple OperatorNameIndexScan(Relation heapRelation,
- Datum oprName, Datum oprLeft,
- Datum oprRight, Datum oprKind);
-extern HeapTuple OperatorOidIndexScan(Relation heapRelation, Datum oprId);
-extern HeapTuple ProcedureNameIndexScan(Relation heapRelation,
- Datum procName, Datum nargs, Datum argTypes);
-extern HeapTuple ProcedureOidIndexScan(Relation heapRelation, Datum procId);
-extern HeapTuple RewriteOidIndexScan(Relation heapRelation, Datum rewriteId);
-extern HeapTuple RewriteRulenameIndexScan(Relation heapRelation,
- Datum ruleName);
-extern HeapTuple ShadowNameIndexScan(Relation heapRelation, Datum useName);
-extern HeapTuple ShadowSysidIndexScan(Relation heapRelation, Datum sysId);
-extern HeapTuple StatisticRelidAttnumIndexScan(Relation heapRelation,
- Datum relId, Datum attNum);
-extern HeapTuple TypeNameIndexScan(Relation heapRelation, Datum typeName);
-extern HeapTuple TypeOidIndexScan(Relation heapRelation, Datum typeId);
-
-
/*
* catcache.h
* Low-level catalog cache definitions.
*
+ * NOTE: every catalog cache must have a corresponding unique index on
+ * the system table that it caches --- ie, the index must match the keys
+ * used to do lookups in this cache. All cache fetches are done with
+ * indexscans (under normal conditions). The index should be unique to
+ * guarantee that there can only be one matching row for a key combination.
+ *
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: catcache.h,v 1.26 2000/08/06 04:16:40 tgl Exp $
+ * $Id: catcache.h,v 1.27 2000/11/10 00:33:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "lib/dllist.h"
/*
- * Functions that implement index scans for caches must match this signature
- * (except we allow unused key arguments to be omitted --- is that really
- * portable?)
- */
-typedef HeapTuple (*ScanFunc) (Relation heapRelation,
- Datum key1,
- Datum key2,
- Datum key3,
- Datum key4);
-
-/*
- * struct catctup: tuples in the cache.
+ * struct catctup: individual tuple in the cache.
* struct catcache: information for managing a cache.
*/
typedef struct catcache
{
- Oid relationId;
- Oid indexId;
- char *cc_relname; /* relation name for defered open */
- char *cc_indname; /* index name for defered open */
- ScanFunc cc_iscanfunc; /* index scan function */
- TupleDesc cc_tupdesc; /* tuple descriptor from reldesc */
- int id; /* XXX could be improved -hirohama */
- bool busy; /* for detecting recursive lookups */
- short cc_ntup; /* # of tuples in this cache */
+ int id; /* cache identifier --- see syscache.h */
+ struct catcache *cc_next; /* link to next catcache */
+ char *cc_relname; /* name of relation the tuples come from */
+ char *cc_indname; /* name of index matching cache keys */
+ TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
+ short cc_ntup; /* # of tuples in this cache */
short cc_maxtup; /* max # of tuples allowed (LRU) */
- short cc_nkeys;
- short cc_size;
+ short cc_size; /* # of hash buckets in this cache */
+ short cc_nkeys; /* number of keys (1..4) */
short cc_key[4]; /* AttrNumber of each key */
PGFunction cc_hashfunc[4]; /* hash function to use for each key */
- ScanKeyData cc_skey[4];
- struct catcache *cc_next;
+ ScanKeyData cc_skey[4]; /* precomputed key info for indexscans */
Dllist *cc_lrulist; /* LRU list, most recent first */
Dllist *cc_cache[NCCBUCK + 1]; /* hash buckets */
} CatCache;
extern MemoryContext CacheMemoryContext;
extern void CreateCacheMemoryContext(void);
-extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
- ItemPointer pointer);
-extern void ResetSystemCache(void);
-extern void SystemCacheRelationFlushed(Oid relId);
-extern void SystemCacheAbort(void);
-extern CatCache *InitSysCache(char *relname, char *indname, int id,
- int nkeys, int *key,
- ScanFunc iScanfuncP);
-extern HeapTuple SearchSysCache(CatCache * cache,
+
+extern CatCache *InitSysCache(int id, char *relname, char *indname,
+ int nkeys, int *key);
+extern HeapTuple SearchSysCache(CatCache *cache,
Datum v1, Datum v2,
Datum v3, Datum v4);
+
+extern void ResetSystemCache(void);
+extern void SystemCacheRelationFlushed(Oid relId);
+extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
+ ItemPointer pointer);
extern void RelationInvalidateCatalogCacheTuple(Relation relation,
HeapTuple tuple,
void (*function) (int, Index, ItemPointer));