Clean up syscache so that recursive invocation is safe, and remove error

message about recursive use of a syscache.  Also remove most of the
specialized indexscan routines in indexing.c --- it turns out that
catcache.c is perfectly able to perform the indexscan for itself,
in fact has already looked up all the information needed to do so!
This should be faster as well as needing far less boilerplate code.
This commit is contained in:
Tom Lane 2000-11-10 00:33:12 +00:00
parent 700032ad6f
commit ddeab22565
7 changed files with 346 additions and 1216 deletions

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* Transaction aborts can now occur two ways: * Transaction aborts can now occur two ways:
@ -863,7 +863,6 @@ static void
AtAbort_Cache(void) AtAbort_Cache(void)
{ {
RelationCacheAbort(); RelationCacheAbort();
SystemCacheAbort();
RegisterInvalid(false); RegisterInvalid(false);
} }

View File

@ -9,7 +9,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -176,50 +176,6 @@ CatalogIndexInsert(Relation *idescs,
} }
} }
/*
* 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 * CatalogIndexFetchTuple() -- Get a tuple that satisfies a scan key
@ -271,162 +227,12 @@ CatalogIndexFetchTuple(Relation heapRelation,
*/ */
/* /*
* The remainder of the file is for individual index scan routines. Each * The remainder of the file is for individual index scan routines.
* index should be scanned according to how it was defined during bootstrap * These routines provide canned scanning code for certain widely-used
* (that is, functional or normal) and what arguments the cache lookup * indexes. Most indexes don't need one of these.
* requires. Each routine returns the heap tuple that qualifies.
*/ */
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 HeapTuple
AttributeRelidNumIndexScan(Relation heapRelation, AttributeRelidNumIndexScan(Relation heapRelation,
Datum relid, Datum relid,
@ -450,332 +256,6 @@ AttributeRelidNumIndexScan(Relation heapRelation,
idesc = index_openr(AttributeRelidNumIndex); idesc = index_openr(AttributeRelidNumIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2); 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)
{
Relation idesc;
ScanKeyData skey[1];
HeapTuple tuple;
ScanKeyEntryInitialize(&skey[0],
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) F_NAMEEQ,
lanName);
idesc = index_openr(LanguageNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
index_close(idesc);
return tuple;
}
HeapTuple
LanguageOidIndexScan(Relation heapRelation, Datum lanId)
{
Relation idesc;
ScanKeyData skey[1];
HeapTuple tuple;
ScanKeyEntryInitialize(&skey[0],
(bits16) 0x0,
(AttrNumber) 1,
(RegProcedure) F_OIDEQ,
lanId);
idesc = index_openr(LanguageOidIndex);
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); index_close(idesc);
return tuple; return tuple;
} }
@ -796,7 +276,6 @@ ClassNameIndexScan(Relation heapRelation, Datum relName)
idesc = index_openr(ClassNameIndex); idesc = index_openr(ClassNameIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1); tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
index_close(idesc); index_close(idesc);
return tuple; return tuple;
} }
@ -817,162 +296,6 @@ ClassOidIndexScan(Relation heapRelation, Datum relId)
idesc = index_openr(ClassOidIndex); idesc = index_openr(ClassOidIndex);
tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1); 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); index_close(idesc);
return tuple; return tuple;
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -29,12 +29,11 @@
#include "utils/syscache.h" #include "utils/syscache.h"
static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e); static void CatCacheRemoveCTup(CatCache *cache, Dlelem *e);
static Index CatalogCacheComputeHashIndex(CatCache *cacheInP); static Index CatalogCacheComputeHashIndex(CatCache *cache,
static Index CatalogCacheComputeTupleHashIndex(CatCache *cacheInOutP, ScanKey cur_skey);
Relation relation, static Index CatalogCacheComputeTupleHashIndex(CatCache *cache,
HeapTuple tuple); HeapTuple tuple);
static void CatalogCacheInitializeCache(CatCache *cache, static void CatalogCacheInitializeCache(CatCache *cache);
Relation relation);
static Datum cc_hashname(PG_FUNCTION_ARGS); static Datum cc_hashname(PG_FUNCTION_ARGS);
/* ---------------- /* ----------------
@ -155,25 +154,23 @@ CreateCacheMemoryContext(void)
/* -------------------------------- /* --------------------------------
* CatalogCacheInitializeCache * 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 #ifdef CACHEDEBUG
#define CatalogCacheInitializeCache_DEBUG1 \ #define CatalogCacheInitializeCache_DEBUG1 \
do { \ elog(DEBUG, "CatalogCacheInitializeCache: cache @%p %s", cache, \
elog(DEBUG, "CatalogCacheInitializeCache: cache @%08lx", cache); \ cache->cc_relname)
if (relation) \
elog(DEBUG, "CatalogCacheInitializeCache: called w/relation(inval)"); \
else \
elog(DEBUG, "CatalogCacheInitializeCache: called w/relname %s", \
cache->cc_relname) \
} while(0)
#define CatalogCacheInitializeCache_DEBUG2 \ #define CatalogCacheInitializeCache_DEBUG2 \
do { \ do { \
if (cache->cc_key[i] > 0) { \ 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], \ 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 { \ } else { \
elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \ elog(DEBUG, "CatalogCacheInitializeCache: load %d/%d w/%d", \
i+1, cache->cc_nkeys, cache->cc_key[i]); \ i+1, cache->cc_nkeys, cache->cc_key[i]); \
@ -186,26 +183,21 @@ do { \
#endif #endif
static void static void
CatalogCacheInitializeCache(CatCache * cache, CatalogCacheInitializeCache(CatCache *cache)
Relation relation)
{ {
Relation relation;
MemoryContext oldcxt; MemoryContext oldcxt;
bool didopen = false;
short i;
TupleDesc tupdesc; TupleDesc tupdesc;
short i;
CatalogCacheInitializeCache_DEBUG1; CatalogCacheInitializeCache_DEBUG1;
/* ---------------- /*
* If no relation was passed we must open it to get access to * Open the relation without locking --- we only need the tupdesc,
* its fields. * which we assume will never change ...
* ----------------
*/ */
if (!RelationIsValid(relation)) relation = heap_openr(cache->cc_relname, NoLock);
{ Assert(RelationIsValid(relation));
relation = heap_openr(cache->cc_relname, NoLock);
didopen = true;
}
/* ---------------- /* ----------------
* switch to the cache context so our allocations * switch to the cache context so our allocations
@ -218,16 +210,21 @@ CatalogCacheInitializeCache(CatCache * cache,
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); 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)); 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 * initialize cache's key information
@ -235,65 +232,45 @@ CatalogCacheInitializeCache(CatCache * cache,
*/ */
for (i = 0; i < cache->cc_nkeys; ++i) for (i = 0; i < cache->cc_nkeys; ++i)
{ {
Oid keytype;
CatalogCacheInitializeCache_DEBUG2; CatalogCacheInitializeCache_DEBUG2;
if (cache->cc_key[i] > 0) 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;
cache->cc_hashfunc[i] = GetCCHashFunc(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;
CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %x",
RelationGetRelationName(relation),
i,
cache);
}
}
/* ----------------
* return to the caller's memory context
* ----------------
*/
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 else
cache->cc_indname = NULL; {
if (cache->cc_key[i] != ObjectIdAttributeNumber)
elog(FATAL, "CatalogCacheInit: only sys attr supported is OID");
keytype = OIDOID;
}
cache->cc_hashfunc[i] = GetCCHashFunc(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;
/* Initialize sk_attno suitably for index scans */
cache->cc_skey[i].sk_attno = i+1;
CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %p",
cache->cc_relname,
i,
cache);
} }
/* ----------------
* mark this cache fully initialized
* ----------------
*/
cache->cc_tupdesc = tupdesc;
} }
/* -------------------------------- /* --------------------------------
@ -301,42 +278,42 @@ CatalogCacheInitializeCache(CatCache * cache,
* -------------------------------- * --------------------------------
*/ */
static Index static Index
CatalogCacheComputeHashIndex(CatCache * cacheInP) CatalogCacheComputeHashIndex(CatCache *cache, ScanKey cur_skey)
{ {
uint32 hashIndex = 0; uint32 hashIndex = 0;
CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %x", CACHE4_elog(DEBUG, "CatalogCacheComputeHashIndex %s %d %p",
cacheInP->cc_relname, cache->cc_relname,
cacheInP->cc_nkeys, cache->cc_nkeys,
cacheInP); cache);
switch (cacheInP->cc_nkeys) switch (cache->cc_nkeys)
{ {
case 4: case 4:
hashIndex ^= hashIndex ^=
DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[3], DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[3],
cacheInP->cc_skey[3].sk_argument)) << 9; cur_skey[3].sk_argument)) << 9;
/* FALLTHROUGH */ /* FALLTHROUGH */
case 3: case 3:
hashIndex ^= hashIndex ^=
DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[2], DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[2],
cacheInP->cc_skey[2].sk_argument)) << 6; cur_skey[2].sk_argument)) << 6;
/* FALLTHROUGH */ /* FALLTHROUGH */
case 2: case 2:
hashIndex ^= hashIndex ^=
DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[1], DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[1],
cacheInP->cc_skey[1].sk_argument)) << 3; cur_skey[1].sk_argument)) << 3;
/* FALLTHROUGH */ /* FALLTHROUGH */
case 1: case 1:
hashIndex ^= hashIndex ^=
DatumGetUInt32(DirectFunctionCall1(cacheInP->cc_hashfunc[0], DatumGetUInt32(DirectFunctionCall1(cache->cc_hashfunc[0],
cacheInP->cc_skey[0].sk_argument)); cur_skey[0].sk_argument));
break; break;
default: default:
elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cacheInP->cc_nkeys); elog(FATAL, "CCComputeHashIndex: %d cc_nkeys", cache->cc_nkeys);
break; break;
} }
hashIndex %= (uint32) cacheInP->cc_size; hashIndex %= (uint32) cache->cc_size;
return (Index) hashIndex; return (Index) hashIndex;
} }
@ -345,65 +322,65 @@ CatalogCacheComputeHashIndex(CatCache * cacheInP)
* -------------------------------- * --------------------------------
*/ */
static Index static Index
CatalogCacheComputeTupleHashIndex(CatCache * cacheInOutP, CatalogCacheComputeTupleHashIndex(CatCache *cache,
Relation relation,
HeapTuple tuple) HeapTuple tuple)
{ {
ScanKeyData cur_skey[4];
bool isNull = false; bool isNull = false;
/* XXX is this really needed? */ /* Copy pre-initialized overhead data for scankey */
if (cacheInOutP->relationId == InvalidOid) memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
CatalogCacheInitializeCache(cacheInOutP, relation);
switch (cacheInOutP->cc_nkeys) /* Now extract key fields from tuple, insert into scankey */
switch (cache->cc_nkeys)
{ {
case 4: case 4:
cacheInOutP->cc_skey[3].sk_argument = cur_skey[3].sk_argument =
(cacheInOutP->cc_key[3] == ObjectIdAttributeNumber) (cache->cc_key[3] == ObjectIdAttributeNumber)
? (Datum) tuple->t_data->t_oid ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple, : fastgetattr(tuple,
cacheInOutP->cc_key[3], cache->cc_key[3],
RelationGetDescr(relation), cache->cc_tupdesc,
&isNull); &isNull);
Assert(!isNull); Assert(!isNull);
/* FALLTHROUGH */ /* FALLTHROUGH */
case 3: case 3:
cacheInOutP->cc_skey[2].sk_argument = cur_skey[2].sk_argument =
(cacheInOutP->cc_key[2] == ObjectIdAttributeNumber) (cache->cc_key[2] == ObjectIdAttributeNumber)
? (Datum) tuple->t_data->t_oid ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple, : fastgetattr(tuple,
cacheInOutP->cc_key[2], cache->cc_key[2],
RelationGetDescr(relation), cache->cc_tupdesc,
&isNull); &isNull);
Assert(!isNull); Assert(!isNull);
/* FALLTHROUGH */ /* FALLTHROUGH */
case 2: case 2:
cacheInOutP->cc_skey[1].sk_argument = cur_skey[1].sk_argument =
(cacheInOutP->cc_key[1] == ObjectIdAttributeNumber) (cache->cc_key[1] == ObjectIdAttributeNumber)
? (Datum) tuple->t_data->t_oid ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple, : fastgetattr(tuple,
cacheInOutP->cc_key[1], cache->cc_key[1],
RelationGetDescr(relation), cache->cc_tupdesc,
&isNull); &isNull);
Assert(!isNull); Assert(!isNull);
/* FALLTHROUGH */ /* FALLTHROUGH */
case 1: case 1:
cacheInOutP->cc_skey[0].sk_argument = cur_skey[0].sk_argument =
(cacheInOutP->cc_key[0] == ObjectIdAttributeNumber) (cache->cc_key[0] == ObjectIdAttributeNumber)
? (Datum) tuple->t_data->t_oid ? ObjectIdGetDatum(tuple->t_data->t_oid)
: fastgetattr(tuple, : fastgetattr(tuple,
cacheInOutP->cc_key[0], cache->cc_key[0],
RelationGetDescr(relation), cache->cc_tupdesc,
&isNull); &isNull);
Assert(!isNull); Assert(!isNull);
break; break;
default: default:
elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys", elog(FATAL, "CCComputeTupleHashIndex: %d cc_nkeys",
cacheInOutP->cc_nkeys); cache->cc_nkeys);
break; break;
} }
return CatalogCacheComputeHashIndex(cacheInOutP); return CatalogCacheComputeHashIndex(cache, cur_skey);
} }
/* -------------------------------- /* --------------------------------
@ -506,8 +483,6 @@ CatalogCacheIdInvalidate(int cacheId, /* XXX */
* public functions * public functions
* *
* ResetSystemCache * ResetSystemCache
* SystemCacheAbort
* InitIndexedSysCache
* InitSysCache * InitSysCache
* SearchSysCache * SearchSysCache
* RelationInvalidateCatalogCacheTuple * RelationInvalidateCatalogCacheTuple
@ -562,27 +537,6 @@ ResetSystemCache(void)
CACHE1_elog(DEBUG, "end of ResetSystemCache call"); 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 * SystemCacheRelationFlushed
* *
@ -629,34 +583,24 @@ SystemCacheRelationFlushed(Oid relId)
#ifdef CACHEDEBUG #ifdef CACHEDEBUG
#define InitSysCache_DEBUG1 \ #define InitSysCache_DEBUG1 \
do { \ do { \
elog(DEBUG, "InitSysCache: rid=%u id=%d nkeys=%d size=%d\n", \ elog(DEBUG, "InitSysCache: rel=%s id=%d nkeys=%d size=%d\n", \
cp->relationId, cp->id, cp->cc_nkeys, cp->cc_size); \ cp->cc_relname, 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); \
} \
} while(0) } while(0)
#else #else
#define InitSysCache_DEBUG1 #define InitSysCache_DEBUG1
#endif #endif
CatCache * CatCache *
InitSysCache(char *relname, InitSysCache(int id,
char *relname,
char *indname, char *indname,
int id,
int nkeys, int nkeys,
int *key, int *key)
ScanFunc iScanfuncP)
{ {
CatCache *cp; CatCache *cp;
int i;
MemoryContext oldcxt; MemoryContext oldcxt;
int i;
/* ---------------- /* ----------------
* first switch to the cache context so our allocations * first switch to the cache context so our allocations
@ -714,46 +658,15 @@ InitSysCache(char *relname,
* cache's other internal fields. * cache's other internal fields.
* ---------------- * ----------------
*/ */
cp->relationId = InvalidOid;
cp->indexId = InvalidOid;
cp->cc_relname = relname; cp->cc_relname = relname;
cp->cc_indname = indname; cp->cc_indname = indname;
cp->cc_tupdesc = (TupleDesc) NULL; cp->cc_tupdesc = (TupleDesc) NULL;
cp->id = id; cp->id = id;
cp->busy = false;
cp->cc_maxtup = MAXTUP; cp->cc_maxtup = MAXTUP;
cp->cc_size = NCCBUCK; cp->cc_size = NCCBUCK;
cp->cc_nkeys = nkeys; 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) for (i = 0; i < nkeys; ++i)
{
cp->cc_key[i] = key[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 * all done. new cache is initialized. print some debugging
@ -773,36 +686,34 @@ InitSysCache(char *relname,
/* -------------------------------- /* --------------------------------
* SearchSelfReferences * IndexScanOK
* *
* This call searches for self-referencing information, * This function checks for tuples that will be fetched by
* which causes infinite recursion in the system catalog cache. * IndexSupportInitialize() during relcache initialization for
* This code short-circuits the normal index lookup for cache loads * certain system indexes that support critical syscaches.
* in those cases and replaces it with a heap scan. * We can't use an indexscan to fetch these, else we'll get into
* * infinite recursion. A plain heap scan will work, however.
* cache should already be initialized
* -------------------------------- * --------------------------------
*/ */
static HeapTuple static bool
SearchSelfReferences(CatCache * cache) IndexScanOK(CatCache *cache, ScanKey cur_skey)
{ {
HeapTuple ntp;
Relation rel;
if (cache->id == INDEXRELID) if (cache->id == INDEXRELID)
{ {
static Oid indexSelfOid = InvalidOid; static Oid indexSelfOid = InvalidOid;
static HeapTuple indexSelfTuple = NULL;
/* One-time lookup of the OID of pg_index_indexrelid_index */
if (!OidIsValid(indexSelfOid)) if (!OidIsValid(indexSelfOid))
{ {
Relation rel;
ScanKeyData key; ScanKeyData key;
HeapScanDesc sd; HeapScanDesc sd;
HeapTuple ntp;
/* Find oid of pg_index_indexrelid_index */
rel = heap_openr(RelationRelationName, AccessShareLock); rel = heap_openr(RelationRelationName, AccessShareLock);
ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname, ScanKeyEntryInitialize(&key, 0, Anum_pg_class_relname,
F_NAMEEQ, PointerGetDatum(IndexRelidIndex)); F_NAMEEQ,
PointerGetDatum(IndexRelidIndex));
sd = heap_beginscan(rel, false, SnapshotNow, 1, &key); sd = heap_beginscan(rel, false, SnapshotNow, 1, &key);
ntp = heap_getnext(sd, 0); ntp = heap_getnext(sd, 0);
if (!HeapTupleIsValid(ntp)) if (!HeapTupleIsValid(ntp))
@ -812,63 +723,22 @@ SearchSelfReferences(CatCache * cache)
heap_endscan(sd); heap_endscan(sd);
heap_close(rel, AccessShareLock); 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? */ /* Looking for pg_index_indexrelid_index? */
if (!HeapTupleIsValid(indexSelfTuple)) if (DatumGetObjectId(cur_skey[0].sk_argument) == indexSelfOid)
{ return false;
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;
} }
else if (cache->id == OPEROID) else if (cache->id == OPEROID)
{ {
/* bootstrapping this requires preloading a range of rows. bjm */ /* Looking for an OID comparison function? */
static HeapTuple operatorSelfTuple[MAX_OIDCMP - MIN_OIDCMP + 1]; Oid lookup_oid = DatumGetObjectId(cur_skey[0].sk_argument);
Oid lookup_oid = (Oid) cache->cc_skey[0].sk_argument;
if (lookup_oid < MIN_OIDCMP || lookup_oid > MAX_OIDCMP) if (lookup_oid >= MIN_OIDCMP && lookup_oid <= MAX_OIDCMP)
return (HeapTuple) 0; return false;
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];
} }
else
return (HeapTuple) 0;
/* Normal case, allow index scan */
return true;
} }
/* -------------------------------- /* --------------------------------
@ -879,13 +749,14 @@ SearchSelfReferences(CatCache * cache)
* -------------------------------- * --------------------------------
*/ */
HeapTuple HeapTuple
SearchSysCache(CatCache * cache, SearchSysCache(CatCache *cache,
Datum v1, Datum v1,
Datum v2, Datum v2,
Datum v3, Datum v3,
Datum v4) Datum v4)
{ {
unsigned hash; ScanKeyData cur_skey[4];
Index hash;
CatCTup *ct = NULL; CatCTup *ct = NULL;
CatCTup *nct; CatCTup *nct;
CatCTup *nct2; CatCTup *nct2;
@ -898,29 +769,24 @@ SearchSysCache(CatCache * cache,
* one-time startup overhead * one-time startup overhead
* ---------------- * ----------------
*/ */
if (cache->relationId == InvalidOid) if (cache->cc_tupdesc == NULL)
CatalogCacheInitializeCache(cache, NULL); CatalogCacheInitializeCache(cache);
/* ---------------- /* ----------------
* initialize the search key information * initialize the search key information
* ---------------- * ----------------
*/ */
cache->cc_skey[0].sk_argument = v1; memcpy(cur_skey, cache->cc_skey, sizeof(cur_skey));
cache->cc_skey[1].sk_argument = v2; cur_skey[0].sk_argument = v1;
cache->cc_skey[2].sk_argument = v3; cur_skey[1].sk_argument = v2;
cache->cc_skey[3].sk_argument = v4; cur_skey[2].sk_argument = v3;
cur_skey[3].sk_argument = v4;
/*
* resolve self referencing informtion
*/
if ((ntp = SearchSelfReferences(cache)) != NULL)
return ntp;
/* ---------------- /* ----------------
* find the hash bucket in which to look for the tuple * 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 * scan the hash bucket until we find a match or exhaust our tuples
@ -941,7 +807,7 @@ SearchSysCache(CatCache * cache,
HeapKeyTest(ct->ct_tup, HeapKeyTest(ct->ct_tup,
cache->cc_tupdesc, cache->cc_tupdesc,
cache->cc_nkeys, cache->cc_nkeys,
cache->cc_skey, cur_skey,
res); res);
if (res) if (res)
break; break;
@ -975,73 +841,89 @@ SearchSysCache(CatCache * cache,
* retrieve it directly from the relation. If it's found, * retrieve it directly from the relation. If it's found,
* we add it to the cache. * we add it to the cache.
* *
* To guard against possible infinite recursion, we mark this cache * NOTE: it is possible for recursive cache lookups to occur while
* "busy" while trying to load a new entry for it. It is OK to * reading the relation --- for example, due to shared-cache-inval
* recursively invoke SearchSysCache for a different cache, but * messages being processed during heap_open(). This is OK. It's
* a recursive call for the same cache will error out. (We could * even possible for one of those lookups to find and enter the
* store the specific key(s) being looked for, and consider only * very same tuple we are trying to fetch here. If that happens,
* a recursive request for the same key to be an error, but this * we will enter a second copy of the tuple into the cache. The
* simple scheme is sufficient for now.) * 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 * open the relation associated with the cache
* ---------------- * ----------------
*/ */
relation = heap_open(cache->relationId, AccessShareLock); relation = heap_openr(cache->cc_relname, AccessShareLock);
CACHE2_elog(DEBUG, "SearchSysCache(%s)",
RelationGetRelationName(relation));
/* ---------------- /* ----------------
* Scan the relation to find the tuple. If there's an index, and * 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 if ((RelationGetForm(relation))->relhasindex &&
&& !IsIgnoringSystemIndexes()) !IsIgnoringSystemIndexes() &&
IndexScanOK(cache, cur_skey))
{ {
HeapTuple indextp; Relation idesc;
IndexScanDesc isd;
RetrieveIndexResult indexRes;
HeapTupleData tuple;
Buffer buffer;
/* We call the scanfunc with all four arguments to satisfy the CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan",
* declared prototype, even though the function will likely not cache->cc_relname);
* use all four.
*/
indextp = cache->cc_iscanfunc(relation, v1, v2, v3, v4);
/* ---------- idesc = index_openr(cache->cc_indname);
* If we got a tuple copy it into our context. wieck - 10/18/1996 isd = index_beginscan(idesc, false, cache->cc_nkeys, cur_skey);
* And free the tuple that was allocated in the tuple.t_datamcxt = CurrentMemoryContext;
* transaction's context. tgl - 02/03/2000 tuple.t_data = NULL;
* ---------- while ((indexRes = index_getnext(isd, ForwardScanDirection)))
*/
if (HeapTupleIsValid(indextp))
{ {
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); tuple.t_self = indexRes->heap_iptr;
ntp = heap_copytuple(indextp); heap_fetch(relation, SnapshotNow, &tuple, &buffer);
MemoryContextSwitchTo(oldcxt); pfree(indexRes);
heap_freetuple(indextp); 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 else
{ {
HeapScanDesc sd; 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, sd = heap_beginscan(relation, 0, SnapshotNow,
cache->cc_nkeys, cache->cc_skey); cache->cc_nkeys, cur_skey);
ntp = heap_getnext(sd, 0); ntp = heap_getnext(sd, 0);
if (HeapTupleIsValid(ntp)) if (HeapTupleIsValid(ntp))
{ {
CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); /* Copy tuple into our context */
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
ntp = heap_copytuple(ntp); ntp = heap_copytuple(ntp);
MemoryContextSwitchTo(oldcxt); MemoryContextSwitchTo(oldcxt);
@ -1051,8 +933,6 @@ SearchSysCache(CatCache * cache,
heap_endscan(sd); heap_endscan(sd);
} }
cache->busy = false;
/* ---------------- /* ----------------
* scan is complete. if tup is valid, we can add it to the cache. * 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. * note we have already copied it into the cache memory context.
@ -1067,6 +947,8 @@ SearchSysCache(CatCache * cache,
*/ */
Dlelem *lru_elt; Dlelem *lru_elt;
CACHE1_elog(DEBUG, "SearchSysCache: found tuple");
oldcxt = MemoryContextSwitchTo(CacheMemoryContext); oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
/* /*
@ -1104,17 +986,16 @@ SearchSysCache(CatCache * cache,
if (ct != nct) /* shouldn't be possible, but be safe... */ if (ct != nct) /* shouldn't be possible, but be safe... */
{ {
CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal", CACHE2_elog(DEBUG, "SearchSysCache(%s): Overflow, LRU removal",
RelationGetRelationName(relation)); cache->cc_relname);
CatCacheRemoveCTup(cache, elt); CatCacheRemoveCTup(cache, elt);
} }
} }
CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples", CACHE4_elog(DEBUG, "SearchSysCache(%s): Contains %d/%d tuples",
RelationGetRelationName(relation), cache->cc_relname, cache->cc_ntup, cache->cc_maxtup);
cache->cc_ntup, cache->cc_maxtup);
CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d", CACHE3_elog(DEBUG, "SearchSysCache(%s): put in bucket %d",
RelationGetRelationName(relation), hash); cache->cc_relname, hash);
} }
/* ---------------- /* ----------------
@ -1141,7 +1022,6 @@ RelationInvalidateCatalogCacheTuple(Relation relation,
void (*function) (int, Index, ItemPointer)) void (*function) (int, Index, ItemPointer))
{ {
CatCache *ccp; CatCache *ccp;
Oid relationId;
/* ---------------- /* ----------------
* sanity checks * sanity checks
@ -1159,15 +1039,18 @@ RelationInvalidateCatalogCacheTuple(Relation relation,
* in the proper hash bucket * in the proper hash bucket
* ---------------- * ----------------
*/ */
relationId = RelationGetRelid(relation);
for (ccp = Caches; ccp; ccp = ccp->cc_next) for (ccp = Caches; ccp; ccp = ccp->cc_next)
{ {
if (relationId != ccp->relationId) if (strcmp(ccp->cc_relname, RelationGetRelationName(relation)) != 0)
continue; continue;
/* Just in case cache hasn't finished initialization yet... */
if (ccp->cc_tupdesc == NULL)
CatalogCacheInitializeCache(ccp);
(*function) (ccp->id, (*function) (ccp->id,
CatalogCacheComputeTupleHashIndex(ccp, relation, tuple), CatalogCacheComputeTupleHashIndex(ccp, tuple),
&tuple->t_self); &tuple->t_self);
} }
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -27,15 +27,14 @@
* careful.... * careful....
* *
*/ */
#include "postgres.h"
#include <sys/types.h> #include <sys/types.h>
#include <errno.h> #include <errno.h>
#include <sys/file.h> #include <sys/file.h>
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include "postgres.h"
#include "utils/builtins.h"
#include "access/genam.h" #include "access/genam.h"
#include "access/heapam.h" #include "access/heapam.h"
#include "access/istrat.h" #include "access/istrat.h"
@ -55,6 +54,7 @@
#include "lib/hasht.h" #include "lib/hasht.h"
#include "miscadmin.h" #include "miscadmin.h"
#include "storage/smgr.h" #include "storage/smgr.h"
#include "utils/builtins.h"
#include "utils/catcache.h" #include "utils/catcache.h"
#include "utils/fmgroids.h" #include "utils/fmgroids.h"
#include "utils/memutils.h" #include "utils/memutils.h"
@ -1127,7 +1127,9 @@ IndexedAccessMethodInitialize(Relation relation)
* This is a special cut-down version of RelationBuildDesc() * This is a special cut-down version of RelationBuildDesc()
* used by RelationCacheInitialize() in initializing the relcache. * used by RelationCacheInitialize() in initializing the relcache.
* The relation descriptor is built just from the supplied parameters, * 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. * NOTE: we assume we are already switched into CacheMemoryContext.
* -------------------------------- * --------------------------------
@ -1219,7 +1221,7 @@ formrdesc(char *relationName,
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid; 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 */ RelationInitLockInfo(relation); /* see lmgr.c */
@ -1231,23 +1233,30 @@ formrdesc(char *relationName,
relation->rd_node.relNode = relation->rd_node.relNode =
relation->rd_rel->relfilenode = RelationGetRelid(relation); relation->rd_rel->relfilenode = RelationGetRelid(relation);
/* ----------------
* initialize the rel-has-index flag, using hardwired knowledge
* ----------------
*/
relation->rd_rel->relhasindex = false;
/* 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 * add new reldesc to relcache
* ---------------- * ----------------
*/ */
RelationCacheInsert(relation); RelationCacheInsert(relation);
/*
* 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.
*/
relation->rd_rel->relhasindex =
CatalogHasIndex(relationName, RelationGetRelid(relation));
} }

View File

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * NOTES
* These routines allow the parser/planner/executor to perform * These routines allow the parser/planner/executor to perform
@ -55,19 +55,16 @@
Add your entry to the cacheinfo[] array below. All cache lists are Add your entry to the cacheinfo[] array below. All cache lists are
alphabetical, so add it in the proper place. Specify the relation alphabetical, so add it in the proper place. Specify the relation
name, number of arguments, argument attribute numbers, index name, name, index name, number of keys, and key attribute numbers.
and index lookup function.
In include/catalog/indexing.h, add a define for the number of indexes 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 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 array to hold the index names, and use DECLARE_UNIQUE_INDEX to define
prototype, and use DECLARE_UNIQUE_INDEX to define the index. Cache the index. Cache lookups return only one row, so the index should be
lookups return only one row, so the index should be unique. unique in most cases.
In backend/catalog/indexing.c, initialize the relation array with In backend/catalog/indexing.c, initialize the relation array with
the index names for the relation, and create the index lookup function. the index names for the relation.
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.
Finally, any place your relation gets heap_insert() or Finally, any place your relation gets heap_insert() or
heap_update calls, include code to do a CatalogIndexInsert() to update heap_update calls, include code to do a CatalogIndexInsert() to update
@ -85,293 +82,264 @@
struct cachedesc struct cachedesc
{ {
char *name; /* name of the relation being cached */ 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 nkeys; /* # of keys needed for cache lookup */
int key[4]; /* attribute numbers of key attrs */ 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[] = { static struct cachedesc cacheinfo[] = {
{AggregateRelationName, /* AGGNAME */ {AggregateRelationName, /* AGGNAME */
AggregateNameTypeIndex,
2, 2,
{ {
Anum_pg_aggregate_aggname, Anum_pg_aggregate_aggname,
Anum_pg_aggregate_aggbasetype, Anum_pg_aggregate_aggbasetype,
0, 0,
0 0
}, }},
AggregateNameTypeIndex,
(ScanFunc) AggregateNameTypeIndexScan},
{AccessMethodRelationName, /* AMNAME */ {AccessMethodRelationName, /* AMNAME */
AmNameIndex,
1, 1,
{ {
Anum_pg_am_amname, Anum_pg_am_amname,
0, 0,
0, 0,
0 0
}, }},
AmNameIndex,
(ScanFunc) AmNameIndexScan},
{AccessMethodOperatorRelationName, /* AMOPOPID */ {AccessMethodOperatorRelationName, /* AMOPOPID */
AccessMethodOpidIndex,
3, 3,
{ {
Anum_pg_amop_amopclaid, Anum_pg_amop_amopclaid,
Anum_pg_amop_amopopr, Anum_pg_amop_amopopr,
Anum_pg_amop_amopid, Anum_pg_amop_amopid,
0 0
}, }},
AccessMethodOpidIndex,
(ScanFunc) AccessMethodOpidIndexScan},
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
AccessMethodStrategyIndex,
3, 3,
{ {
Anum_pg_amop_amopid, Anum_pg_amop_amopid,
Anum_pg_amop_amopclaid, Anum_pg_amop_amopclaid,
Anum_pg_amop_amopstrategy, Anum_pg_amop_amopstrategy,
0 0
}, }},
AccessMethodStrategyIndex,
(ScanFunc) AccessMethodStrategyIndexScan},
{AttributeRelationName, /* ATTNAME */ {AttributeRelationName, /* ATTNAME */
AttributeRelidNameIndex,
2, 2,
{ {
Anum_pg_attribute_attrelid, Anum_pg_attribute_attrelid,
Anum_pg_attribute_attname, Anum_pg_attribute_attname,
0, 0,
0 0
}, }},
AttributeRelidNameIndex,
(ScanFunc) AttributeRelidNameIndexScan},
{AttributeRelationName, /* ATTNUM */ {AttributeRelationName, /* ATTNUM */
AttributeRelidNumIndex,
2, 2,
{ {
Anum_pg_attribute_attrelid, Anum_pg_attribute_attrelid,
Anum_pg_attribute_attnum, Anum_pg_attribute_attnum,
0, 0,
0 0
}, }},
AttributeRelidNumIndex,
(ScanFunc) AttributeRelidNumIndexScan},
{OperatorClassRelationName, /* CLADEFTYPE */ {OperatorClassRelationName, /* CLADEFTYPE */
OpclassDeftypeIndex,
1, 1,
{ {
Anum_pg_opclass_opcdeftype, Anum_pg_opclass_opcdeftype,
0, 0,
0, 0,
0 0
}, }},
OpclassDeftypeIndex,
(ScanFunc) OpclassDeftypeIndexScan},
{OperatorClassRelationName, /* CLANAME */ {OperatorClassRelationName, /* CLANAME */
OpclassNameIndex,
1, 1,
{ {
Anum_pg_opclass_opcname, Anum_pg_opclass_opcname,
0, 0,
0, 0,
0 0
}, }},
OpclassNameIndex,
(ScanFunc) OpclassNameIndexScan},
{GroupRelationName, /* GRONAME */ {GroupRelationName, /* GRONAME */
GroupNameIndex,
1, 1,
{ {
Anum_pg_group_groname, Anum_pg_group_groname,
0, 0,
0, 0,
0 0
}, }},
GroupNameIndex,
(ScanFunc) GroupNameIndexScan},
{GroupRelationName, /* GROSYSID */ {GroupRelationName, /* GROSYSID */
GroupSysidIndex,
1, 1,
{ {
Anum_pg_group_grosysid, Anum_pg_group_grosysid,
0, 0,
0, 0,
0 0
}, }},
GroupSysidIndex,
(ScanFunc) GroupSysidIndexScan},
{IndexRelationName, /* INDEXRELID */ {IndexRelationName, /* INDEXRELID */
IndexRelidIndex,
1, 1,
{ {
Anum_pg_index_indexrelid, Anum_pg_index_indexrelid,
0, 0,
0, 0,
0 0
}, }},
IndexRelidIndex,
(ScanFunc) IndexRelidIndexScan},
{InheritsRelationName, /* INHRELID */ {InheritsRelationName, /* INHRELID */
InheritsRelidSeqnoIndex,
2, 2,
{ {
Anum_pg_inherits_inhrelid, Anum_pg_inherits_inhrelid,
Anum_pg_inherits_inhseqno, Anum_pg_inherits_inhseqno,
0, 0,
0 0
}, }},
InheritsRelidSeqnoIndex,
(ScanFunc) InheritsRelidSeqnoIndexScan},
{LanguageRelationName, /* LANGNAME */ {LanguageRelationName, /* LANGNAME */
LanguageNameIndex,
1, 1,
{ {
Anum_pg_language_lanname, Anum_pg_language_lanname,
0, 0,
0, 0,
0 0
}, }},
LanguageNameIndex,
(ScanFunc) LanguageNameIndexScan},
{LanguageRelationName, /* LANGOID */ {LanguageRelationName, /* LANGOID */
LanguageOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }},
LanguageOidIndex,
(ScanFunc) LanguageOidIndexScan},
{ListenerRelationName, /* LISTENREL */ {ListenerRelationName, /* LISTENREL */
ListenerPidRelnameIndex,
2, 2,
{ {
Anum_pg_listener_pid, Anum_pg_listener_pid,
Anum_pg_listener_relname, Anum_pg_listener_relname,
0, 0,
0 0
}, }},
ListenerPidRelnameIndex,
(ScanFunc) ListenerPidRelnameIndexScan},
{OperatorRelationName, /* OPERNAME */ {OperatorRelationName, /* OPERNAME */
OperatorNameIndex,
4, 4,
{ {
Anum_pg_operator_oprname, Anum_pg_operator_oprname,
Anum_pg_operator_oprleft, Anum_pg_operator_oprleft,
Anum_pg_operator_oprright, Anum_pg_operator_oprright,
Anum_pg_operator_oprkind Anum_pg_operator_oprkind
}, }},
OperatorNameIndex,
(ScanFunc) OperatorNameIndexScan},
{OperatorRelationName, /* OPEROID */ {OperatorRelationName, /* OPEROID */
OperatorOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }},
OperatorOidIndex,
(ScanFunc) OperatorOidIndexScan},
{ProcedureRelationName, /* PROCNAME */ {ProcedureRelationName, /* PROCNAME */
ProcedureNameIndex,
3, 3,
{ {
Anum_pg_proc_proname, Anum_pg_proc_proname,
Anum_pg_proc_pronargs, Anum_pg_proc_pronargs,
Anum_pg_proc_proargtypes, Anum_pg_proc_proargtypes,
0 0
}, }},
ProcedureNameIndex,
(ScanFunc) ProcedureNameIndexScan},
{ProcedureRelationName, /* PROCOID */ {ProcedureRelationName, /* PROCOID */
ProcedureOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }},
ProcedureOidIndex,
(ScanFunc) ProcedureOidIndexScan},
{RelationRelationName, /* RELNAME */ {RelationRelationName, /* RELNAME */
ClassNameIndex,
1, 1,
{ {
Anum_pg_class_relname, Anum_pg_class_relname,
0, 0,
0, 0,
0 0
}, }},
ClassNameIndex,
(ScanFunc) ClassNameIndexScan},
{RelationRelationName, /* RELOID */ {RelationRelationName, /* RELOID */
ClassOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }},
ClassOidIndex,
(ScanFunc) ClassOidIndexScan},
{RewriteRelationName, /* REWRITENAME */ {RewriteRelationName, /* REWRITENAME */
RewriteRulenameIndex,
1, 1,
{ {
Anum_pg_rewrite_rulename, Anum_pg_rewrite_rulename,
0, 0,
0, 0,
0 0
}, }},
RewriteRulenameIndex,
(ScanFunc) RewriteRulenameIndexScan},
{RewriteRelationName, /* RULEOID */ {RewriteRelationName, /* RULEOID */
RewriteOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }},
RewriteOidIndex,
(ScanFunc) RewriteOidIndexScan},
{ShadowRelationName, /* SHADOWNAME */ {ShadowRelationName, /* SHADOWNAME */
ShadowNameIndex,
1, 1,
{ {
Anum_pg_shadow_usename, Anum_pg_shadow_usename,
0, 0,
0, 0,
0 0
}, }},
ShadowNameIndex,
(ScanFunc) ShadowNameIndexScan},
{ShadowRelationName, /* SHADOWSYSID */ {ShadowRelationName, /* SHADOWSYSID */
ShadowSysidIndex,
1, 1,
{ {
Anum_pg_shadow_usesysid, Anum_pg_shadow_usesysid,
0, 0,
0, 0,
0 0
}, }},
ShadowSysidIndex,
(ScanFunc) ShadowSysidIndexScan},
{StatisticRelationName, /* STATRELID */ {StatisticRelationName, /* STATRELID */
StatisticRelidAttnumIndex,
2, 2,
{ {
Anum_pg_statistic_starelid, Anum_pg_statistic_starelid,
Anum_pg_statistic_staattnum, Anum_pg_statistic_staattnum,
0, 0,
0 0
}, }},
StatisticRelidAttnumIndex,
(ScanFunc) StatisticRelidAttnumIndexScan},
{TypeRelationName, /* TYPENAME */ {TypeRelationName, /* TYPENAME */
TypeNameIndex,
1, 1,
{ {
Anum_pg_type_typname, Anum_pg_type_typname,
0, 0,
0, 0,
0 0
}, }},
TypeNameIndex,
(ScanFunc) TypeNameIndexScan},
{TypeRelationName, /* TYPEOID */ {TypeRelationName, /* TYPEOID */
TypeOidIndex,
1, 1,
{ {
ObjectIdAttributeNumber, ObjectIdAttributeNumber,
0, 0,
0, 0,
0 0
}, }}
TypeOidIndex,
(ScanFunc) TypeOidIndexScan}
}; };
static CatCache *SysCache[lengthof(cacheinfo)]; static CatCache *SysCache[lengthof(cacheinfo)];
@ -412,12 +380,11 @@ InitCatalogCache()
{ {
Assert(!PointerIsValid(SysCache[cacheId])); Assert(!PointerIsValid(SysCache[cacheId]));
SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name, SysCache[cacheId] = InitSysCache(cacheId,
cacheinfo[cacheId].name,
cacheinfo[cacheId].indname, cacheinfo[cacheId].indname,
cacheId,
cacheinfo[cacheId].nkeys, cacheinfo[cacheId].nkeys,
cacheinfo[cacheId].key, cacheinfo[cacheId].key);
cacheinfo[cacheId].iScanFunc);
if (!PointerIsValid(SysCache[cacheId])) if (!PointerIsValid(SysCache[cacheId]))
{ {
elog(ERROR, elog(ERROR,
@ -469,12 +436,11 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
if (!PointerIsValid(SysCache[cacheId])) if (!PointerIsValid(SysCache[cacheId]))
{ {
SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name, SysCache[cacheId] = InitSysCache(cacheId,
cacheinfo[cacheId].name,
cacheinfo[cacheId].indname, cacheinfo[cacheId].indname,
cacheId,
cacheinfo[cacheId].nkeys, cacheinfo[cacheId].nkeys,
cacheinfo[cacheId].key, cacheinfo[cacheId].key);
cacheinfo[cacheId].iScanFunc);
if (!PointerIsValid(SysCache[cacheId])) if (!PointerIsValid(SysCache[cacheId]))
elog(ERROR, elog(ERROR,
"InitCatalogCache: Can't init cache %s(%d)", "InitCatalogCache: Can't init cache %s(%d)",
@ -569,7 +535,6 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
if (cacheId < 0 || cacheId >= SysCacheSize) if (cacheId < 0 || cacheId >= SysCacheSize)
elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId); elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId);
if (!PointerIsValid(SysCache[cacheId]) || if (!PointerIsValid(SysCache[cacheId]) ||
SysCache[cacheId]->relationId == InvalidOid ||
!PointerIsValid(SysCache[cacheId]->cc_tupdesc)) !PointerIsValid(SysCache[cacheId]->cc_tupdesc))
elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId); elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);

View File

@ -1,14 +1,14 @@
/*------------------------------------------------------------------------- /*-------------------------------------------------------------------------
* *
* indexing.h * indexing.h
* This include provides some definitions to support indexing * This file provides some definitions to support indexing
* on system catalogs * on system catalogs
* *
* *
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -116,55 +116,15 @@ extern void CatalogOpenIndices(int nIndices, char **names, Relation *idescs);
extern void CatalogCloseIndices(int nIndices, Relation *idescs); extern void CatalogCloseIndices(int nIndices, Relation *idescs);
extern void CatalogIndexInsert(Relation *idescs, int nIndices, extern void CatalogIndexInsert(Relation *idescs, int nIndices,
Relation heapRelation, HeapTuple heapTuple); 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! * 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, extern HeapTuple AttributeRelidNumIndexScan(Relation heapRelation,
Datum relid, Datum attnum); Datum relid, Datum attnum);
extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName); extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
extern HeapTuple ClassOidIndexScan(Relation heapRelation, Datum relId); 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);
/* /*

View File

@ -3,11 +3,17 @@
* catcache.h * catcache.h
* Low-level catalog cache definitions. * 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) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California * 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 $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -20,18 +26,7 @@
#include "lib/dllist.h" #include "lib/dllist.h"
/* /*
* Functions that implement index scans for caches must match this signature * struct catctup: individual tuple in the cache.
* (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 catcache: information for managing a cache. * struct catcache: information for managing a cache.
*/ */
@ -53,22 +48,18 @@ typedef struct catctup
typedef struct catcache typedef struct catcache
{ {
Oid relationId; int id; /* cache identifier --- see syscache.h */
Oid indexId; struct catcache *cc_next; /* link to next catcache */
char *cc_relname; /* relation name for defered open */ char *cc_relname; /* name of relation the tuples come from */
char *cc_indname; /* index name for defered open */ char *cc_indname; /* name of index matching cache keys */
ScanFunc cc_iscanfunc; /* index scan function */ TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
TupleDesc cc_tupdesc; /* tuple descriptor from reldesc */ short cc_ntup; /* # of tuples in this cache */
int id; /* XXX could be improved -hirohama */
bool busy; /* for detecting recursive lookups */
short cc_ntup; /* # of tuples in this cache */
short cc_maxtup; /* max # of tuples allowed (LRU) */ short cc_maxtup; /* max # of tuples allowed (LRU) */
short cc_nkeys; short cc_size; /* # of hash buckets in this cache */
short cc_size; short cc_nkeys; /* number of keys (1..4) */
short cc_key[4]; /* AttrNumber of each key */ short cc_key[4]; /* AttrNumber of each key */
PGFunction cc_hashfunc[4]; /* hash function to use for each key */ PGFunction cc_hashfunc[4]; /* hash function to use for each key */
ScanKeyData cc_skey[4]; ScanKeyData cc_skey[4]; /* precomputed key info for indexscans */
struct catcache *cc_next;
Dllist *cc_lrulist; /* LRU list, most recent first */ Dllist *cc_lrulist; /* LRU list, most recent first */
Dllist *cc_cache[NCCBUCK + 1]; /* hash buckets */ Dllist *cc_cache[NCCBUCK + 1]; /* hash buckets */
} CatCache; } CatCache;
@ -79,17 +70,17 @@ typedef struct catcache
extern MemoryContext CacheMemoryContext; extern MemoryContext CacheMemoryContext;
extern void CreateCacheMemoryContext(void); extern void CreateCacheMemoryContext(void);
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
ItemPointer pointer); extern CatCache *InitSysCache(int id, char *relname, char *indname,
extern void ResetSystemCache(void); int nkeys, int *key);
extern void SystemCacheRelationFlushed(Oid relId); extern HeapTuple SearchSysCache(CatCache *cache,
extern void SystemCacheAbort(void);
extern CatCache *InitSysCache(char *relname, char *indname, int id,
int nkeys, int *key,
ScanFunc iScanfuncP);
extern HeapTuple SearchSysCache(CatCache * cache,
Datum v1, Datum v2, Datum v1, Datum v2,
Datum v3, Datum v4); 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, extern void RelationInvalidateCatalogCacheTuple(Relation relation,
HeapTuple tuple, HeapTuple tuple,
void (*function) (int, Index, ItemPointer)); void (*function) (int, Index, ItemPointer));