diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 97ff91fc44..6d950e9694 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -8,7 +8,7 @@ * * * 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: @@ -863,7 +863,6 @@ static void AtAbort_Cache(void) { RelationCacheAbort(); - SystemCacheAbort(); RegisterInvalid(false); } diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c index 1a96c3f5ea..6003ab6bc5 100644 --- a/src/backend/catalog/indexing.c +++ b/src/backend/catalog/indexing.c @@ -9,7 +9,7 @@ * * * 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 @@ -271,162 +227,12 @@ CatalogIndexFetchTuple(Relation heapRelation, */ /* - * 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, @@ -450,332 +256,6 @@ AttributeRelidNumIndexScan(Relation heapRelation, 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) -{ - 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); return tuple; } @@ -796,7 +276,6 @@ ClassNameIndexScan(Relation heapRelation, Datum relName) idesc = index_openr(ClassNameIndex); tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1); - index_close(idesc); return tuple; } @@ -817,162 +296,6 @@ ClassOidIndexScan(Relation heapRelation, Datum 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; } diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 1c0b39c84b..39e05d0fb0 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * 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" 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); /* ---------------- @@ -155,25 +154,23 @@ CreateCacheMemoryContext(void) /* -------------------------------- * 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]); \ @@ -186,26 +183,21 @@ do { \ #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 @@ -218,16 +210,21 @@ CatalogCacheInitializeCache(CatCache * cache, 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 @@ -235,65 +232,45 @@ CatalogCacheInitializeCache(CatCache * cache, */ 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; - - 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); + keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid; } 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 -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; } @@ -345,65 +322,65 @@ CatalogCacheComputeHashIndex(CatCache * cacheInP) * -------------------------------- */ 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); } /* -------------------------------- @@ -506,8 +483,6 @@ CatalogCacheIdInvalidate(int cacheId, /* XXX */ * public functions * * ResetSystemCache - * SystemCacheAbort - * InitIndexedSysCache * InitSysCache * SearchSysCache * RelationInvalidateCatalogCacheTuple @@ -562,27 +537,6 @@ ResetSystemCache(void) 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 * @@ -629,34 +583,24 @@ SystemCacheRelationFlushed(Oid relId) #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 @@ -714,46 +658,15 @@ InitSysCache(char *relname, * 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 @@ -773,36 +686,34 @@ InitSysCache(char *relname, /* -------------------------------- - * 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)) @@ -812,63 +723,22 @@ SearchSelfReferences(CatCache * cache) 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; } /* -------------------------------- @@ -879,13 +749,14 @@ SearchSelfReferences(CatCache * cache) * -------------------------------- */ 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; @@ -898,29 +769,24 @@ SearchSysCache(CatCache * cache, * 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 @@ -941,7 +807,7 @@ SearchSysCache(CatCache * cache, HeapKeyTest(ct->ct_tup, cache->cc_tupdesc, cache->cc_nkeys, - cache->cc_skey, + cur_skey, res); if (res) break; @@ -975,73 +841,89 @@ SearchSysCache(CatCache * cache, * 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; + Relation idesc; + IndexScanDesc isd; + RetrieveIndexResult indexRes; + HeapTupleData tuple; + Buffer buffer; - /* 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); + CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan", + cache->cc_relname); - /* ---------- - * 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)) + 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); @@ -1051,8 +933,6 @@ SearchSysCache(CatCache * cache, 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. @@ -1067,6 +947,8 @@ SearchSysCache(CatCache * cache, */ Dlelem *lru_elt; + CACHE1_elog(DEBUG, "SearchSysCache: found tuple"); + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); /* @@ -1104,17 +986,16 @@ SearchSysCache(CatCache * cache, 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); } /* ---------------- @@ -1141,7 +1022,6 @@ RelationInvalidateCatalogCacheTuple(Relation relation, void (*function) (int, Index, ItemPointer)) { CatCache *ccp; - Oid relationId; /* ---------------- * sanity checks @@ -1159,15 +1039,18 @@ RelationInvalidateCatalogCacheTuple(Relation relation, * 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); } } diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index be902d7842..3ed5a8e9fd 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * 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.... * */ +#include "postgres.h" + #include #include #include #include #include -#include "postgres.h" - -#include "utils/builtins.h" #include "access/genam.h" #include "access/heapam.h" #include "access/istrat.h" @@ -55,6 +54,7 @@ #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" @@ -1127,7 +1127,9 @@ IndexedAccessMethodInitialize(Relation relation) * 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. * -------------------------------- @@ -1219,7 +1221,7 @@ formrdesc(char *relationName, 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 */ @@ -1231,23 +1233,30 @@ formrdesc(char *relationName, relation->rd_node.relNode = 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 * ---------------- */ 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)); } diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index e8f602c2ec..7f35f19208 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * 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 @@ -55,19 +55,16 @@ 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 @@ -85,293 +82,264 @@ 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)]; @@ -412,12 +380,11 @@ InitCatalogCache() { 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, @@ -469,12 +436,11 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */ 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)", @@ -569,7 +535,6 @@ SysCacheGetAttr(int cacheId, HeapTuple tup, 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); diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h index 7150a43d2d..725586efdf 100644 --- a/src/include/catalog/indexing.h +++ b/src/include/catalog/indexing.h @@ -1,14 +1,14 @@ /*------------------------------------------------------------------------- * * 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 $ * *------------------------------------------------------------------------- */ @@ -116,55 +116,15 @@ extern void CatalogOpenIndices(int nIndices, char **names, Relation *idescs); 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); - - /* diff --git a/src/include/utils/catcache.h b/src/include/utils/catcache.h index 369dfd02c5..e55b6492d8 100644 --- a/src/include/utils/catcache.h +++ b/src/include/utils/catcache.h @@ -3,11 +3,17 @@ * 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 $ * *------------------------------------------------------------------------- */ @@ -20,18 +26,7 @@ #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. */ @@ -53,22 +48,18 @@ typedef struct catctup 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; @@ -79,17 +70,17 @@ typedef struct 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));