diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 97ff91fc4403f0a6e8335eb179edf5c62378a1db..6d950e969425b96d8e491c34fcef841abe2f60fe 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 1a96c3f5ea538b33263ab468f0e6d56ae5432ba4..6003ab6bc5383af0202af81a7972e8915c5aa492 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,148 +256,13 @@ 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)
+ClassNameIndexScan(Relation heapRelation, Datum relName)
 {
 	Relation	idesc;
 	ScanKeyData skey[1];
@@ -601,18 +272,17 @@ LanguageNameIndexScan(Relation heapRelation, Datum lanName)
 						   (bits16) 0x0,
 						   (AttrNumber) 1,
 						   (RegProcedure) F_NAMEEQ,
-						   lanName);
+						   relName);
 
-	idesc = index_openr(LanguageNameIndex);
+	idesc = index_openr(ClassNameIndex);
 	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
 	index_close(idesc);
 	return tuple;
 }
 
 
 HeapTuple
-LanguageOidIndexScan(Relation heapRelation, Datum lanId)
+ClassOidIndexScan(Relation heapRelation, Datum relId)
 {
 	Relation	idesc;
 	ScanKeyData skey[1];
@@ -622,357 +292,10 @@ LanguageOidIndexScan(Relation heapRelation, Datum lanId)
 						   (bits16) 0x0,
 						   (AttrNumber) 1,
 						   (RegProcedure) F_OIDEQ,
-						   lanId);
+						   relId);
 
-	idesc = index_openr(LanguageOidIndex);
+	idesc = index_openr(ClassOidIndex);
 	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ListenerPidRelnameIndexScan(Relation heapRelation,
-							Datum pid, Datum relName)
-{
-	Relation	idesc;
-	ScanKeyData skey[2];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_INT4EQ,
-						   pid);
-
-	ScanKeyEntryInitialize(&skey[1],
-						   (bits16) 0x0,
-						   (AttrNumber) 2,
-						   (RegProcedure) F_NAMEEQ,
-						   relName);
-
-	idesc = index_openr(ListenerPidRelnameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-OperatorNameIndexScan(Relation heapRelation,
-					  Datum oprName,
-					  Datum oprLeft,
-					  Datum oprRight,
-					  Datum oprKind)
-{
-	Relation	idesc;
-	ScanKeyData skey[4];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   oprName);
-
-	ScanKeyEntryInitialize(&skey[1],
-						   (bits16) 0x0,
-						   (AttrNumber) 2,
-						   (RegProcedure) F_OIDEQ,
-						   oprLeft);
-
-	ScanKeyEntryInitialize(&skey[2],
-						   (bits16) 0x0,
-						   (AttrNumber) 3,
-						   (RegProcedure) F_OIDEQ,
-						   oprRight);
-
-	ScanKeyEntryInitialize(&skey[3],
-						   (bits16) 0x0,
-						   (AttrNumber) 4,
-						   (RegProcedure) F_CHAREQ,
-						   oprKind);
-
-	idesc = index_openr(OperatorNameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 4);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-OperatorOidIndexScan(Relation heapRelation, Datum oprId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   oprId);
-
-	idesc = index_openr(OperatorOidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ProcedureNameIndexScan(Relation heapRelation,
-					   Datum procName,
-					   Datum nargs,
-					   Datum argTypes)
-{
-	Relation	idesc;
-	ScanKeyData skey[3];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   procName);
-
-	ScanKeyEntryInitialize(&skey[1],
-						   (bits16) 0x0,
-						   (AttrNumber) 2,
-						   (RegProcedure) F_INT2EQ,
-						   nargs);
-
-	ScanKeyEntryInitialize(&skey[2],
-						   (bits16) 0x0,
-						   (AttrNumber) 3,
-						   (RegProcedure) F_OIDVECTOREQ,
-						   argTypes);
-
-	idesc = index_openr(ProcedureNameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 3);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ProcedureOidIndexScan(Relation heapRelation, Datum procId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   procId);
-
-	idesc = index_openr(ProcedureOidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ClassNameIndexScan(Relation heapRelation, Datum relName)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   relName);
-
-	idesc = index_openr(ClassNameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ClassOidIndexScan(Relation heapRelation, Datum relId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   relId);
-
-	idesc = index_openr(ClassOidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-RewriteRulenameIndexScan(Relation heapRelation, Datum ruleName)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   ruleName);
-
-	idesc = index_openr(RewriteRulenameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-RewriteOidIndexScan(Relation heapRelation, Datum rewriteId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   rewriteId);
-
-	idesc = index_openr(RewriteOidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ShadowNameIndexScan(Relation heapRelation, Datum useName)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   useName);
-
-	idesc = index_openr(ShadowNameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-ShadowSysidIndexScan(Relation heapRelation, Datum sysId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_INT4EQ,
-						   sysId);
-
-	idesc = index_openr(ShadowSysidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-StatisticRelidAttnumIndexScan(Relation heapRelation,
-							  Datum relId,
-							  Datum attNum)
-{
-	Relation	idesc;
-	ScanKeyData skey[2];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   relId);
-
-	ScanKeyEntryInitialize(&skey[1],
-						   (bits16) 0x0,
-						   (AttrNumber) 2,
-						   (RegProcedure) F_INT2EQ,
-						   attNum);
-
-	idesc = index_openr(StatisticRelidAttnumIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 2);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-TypeNameIndexScan(Relation heapRelation, Datum typeName)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_NAMEEQ,
-						   typeName);
-
-	idesc = index_openr(TypeNameIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
-	index_close(idesc);
-	return tuple;
-}
-
-
-HeapTuple
-TypeOidIndexScan(Relation heapRelation, Datum typeId)
-{
-	Relation	idesc;
-	ScanKeyData skey[1];
-	HeapTuple	tuple;
-
-	ScanKeyEntryInitialize(&skey[0],
-						   (bits16) 0x0,
-						   (AttrNumber) 1,
-						   (RegProcedure) F_OIDEQ,
-						   typeId);
-
-	idesc = index_openr(TypeOidIndex);
-	tuple = CatalogIndexFetchTuple(heapRelation, idesc, skey, 1);
-
 	index_close(idesc);
 	return tuple;
 }
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index 1c0b39c84b548b65b3c8fea0e5fbb270050ab8fd..39e05d0fb09ccb8d3faffd76c8ebfbaea0fddca0 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;
+			keytype = tupdesc->attrs[cache->cc_key[i] - 1]->atttypid;
+		}
+		else
+		{
+			if (cache->cc_key[i] != ObjectIdAttributeNumber)
+				elog(FATAL, "CatalogCacheInit: only sys attr supported is OID");
+			keytype = OIDOID;
+		}
 
-			cache->cc_hashfunc[i] = GetCCHashFunc(keytype);
+		cache->cc_hashfunc[i] = GetCCHashFunc(keytype);
+		/*
+		 * If GetCCHashFunc liked the type, safe to index into eqproc[]
+		 */
+		cache->cc_skey[i].sk_procedure = EQPROC(keytype);
 
-			/*
-			 * If GetCCHashFunc liked the type, safe to index into
-			 * eqproc[]
-			 */
-			cache->cc_skey[i].sk_procedure = EQPROC(keytype);
+		fmgr_info(cache->cc_skey[i].sk_procedure,
+				  &cache->cc_skey[i].sk_func);
+		cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
 
-			fmgr_info(cache->cc_skey[i].sk_procedure,
-					  &cache->cc_skey[i].sk_func);
-			cache->cc_skey[i].sk_nargs = cache->cc_skey[i].sk_func.fn_nargs;
+		/* Initialize sk_attno suitably for index scans */
+		cache->cc_skey[i].sk_attno = i+1;
 
-			CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %x",
-						RelationGetRelationName(relation),
-						i,
-						cache);
-		}
+		CACHE4_elog(DEBUG, "CatalogCacheInit %s %d %p",
+					cache->cc_relname,
+					i,
+					cache);
 	}
 
 	/* ----------------
-	 *	return to the caller's memory context
+	 *	mark this cache fully initialized
 	 * ----------------
 	 */
-	MemoryContextSwitchTo(oldcxt);
-
-	/* ----------------
-	 *	close the relation if we opened it
-	 * ----------------
-	 */
-	if (didopen)
-		heap_close(relation, NoLock);
-
-	/* ----------------
-	 *	initialize index information for the cache.  this
-	 *	should only be done once per cache.
-	 * ----------------
-	 */
-	if (cache->cc_indname != NULL && cache->indexId == InvalidOid)
-	{
-		if (!IsIgnoringSystemIndexes() && RelationGetForm(relation)->relhasindex)
-		{
-
-			/*
-			 * If the index doesn't exist we are in trouble.
-			 */
-			relation = index_openr(cache->cc_indname);
-			Assert(relation);
-			cache->indexId = RelationGetRelid(relation);
-			index_close(relation);
-		}
-		else
-			cache->cc_indname = NULL;
-	}
+	cache->cc_tupdesc = tupdesc;
 }
 
 /* --------------------------------
@@ -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;
-
-		/* We call the scanfunc with all four arguments to satisfy the
-		 * declared prototype, even though the function will likely not
-		 * use all four.
-		 */
-		indextp = cache->cc_iscanfunc(relation, v1, v2, v3, v4);
-
-		/* ----------
-		 *	If we got a tuple copy it into our context.  wieck - 10/18/1996
-		 *	And free the tuple that was allocated in the
-		 *	transaction's context.   tgl - 02/03/2000
-		 * ----------
-		 */
-		if (HeapTupleIsValid(indextp))
+		Relation	idesc;
+		IndexScanDesc isd;
+		RetrieveIndexResult indexRes;
+		HeapTupleData tuple;
+		Buffer		buffer;
+
+		CACHE2_elog(DEBUG, "SearchSysCache(%s): performing index scan",
+					cache->cc_relname);
+
+		idesc = index_openr(cache->cc_indname);
+		isd = index_beginscan(idesc, false, cache->cc_nkeys, cur_skey);
+		tuple.t_datamcxt = CurrentMemoryContext;
+		tuple.t_data = NULL;
+		while ((indexRes = index_getnext(isd, ForwardScanDirection)))
 		{
-			oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
-			ntp = heap_copytuple(indextp);
-			MemoryContextSwitchTo(oldcxt);
-			heap_freetuple(indextp);
+			tuple.t_self = indexRes->heap_iptr;
+			heap_fetch(relation, SnapshotNow, &tuple, &buffer);
+			pfree(indexRes);
+			if (tuple.t_data != NULL)
+			{
+				/* Copy tuple into our context */
+				oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
+				ntp = heap_copytuple(&tuple);
+				MemoryContextSwitchTo(oldcxt);
+				ReleaseBuffer(buffer);
+				break;
+			}
 		}
+		index_endscan(isd);
+		index_close(idesc);
 	}
 	else
 	{
 		HeapScanDesc sd;
+		int			i;
+
+		CACHE2_elog(DEBUG, "SearchSysCache(%s): performing heap scan",
+					cache->cc_relname);
+
+		/*
+		 * For a heap scan, sk_attno has to be set to the heap attribute
+		 * number(s), not the index attribute numbers.
+		 */
+		for (i = 0; i < cache->cc_nkeys; ++i)
+			cur_skey[i].sk_attno = cache->cc_key[i];
 
 		sd = heap_beginscan(relation, 0, SnapshotNow,
-							cache->cc_nkeys, cache->cc_skey);
+							cache->cc_nkeys, cur_skey);
 
 		ntp = heap_getnext(sd, 0);
 
-
 		if (HeapTupleIsValid(ntp))
 		{
-			CACHE1_elog(DEBUG, "SearchSysCache: found tuple");
+			/* Copy tuple into our context */
 			oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
 			ntp = heap_copytuple(ntp);
 			MemoryContextSwitchTo(oldcxt);
@@ -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 be902d7842325927d30f479b8c7b453f30a63d4d..3ed5a8e9fd4bdc63fa88b7ba711baa77f39ef2d2 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 <sys/types.h>
 #include <errno.h>
 #include <sys/file.h>
 #include <fcntl.h>
 #include <unistd.h>
 
-#include "postgres.h"
-
-#include "utils/builtins.h"
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "access/istrat.h"
@@ -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 */
@@ -1232,22 +1234,29 @@ formrdesc(char *relationName,
 		relation->rd_rel->relfilenode = RelationGetRelid(relation);
 
 	/* ----------------
-	 *	add new reldesc to relcache
+	 *	initialize the rel-has-index flag, using hardwired knowledge
 	 * ----------------
 	 */
-	RelationCacheInsert(relation);
+	relation->rd_rel->relhasindex = false;
 
-	/*
-	 * Determining this requires a scan on pg_class, but to do the scan
-	 * the rdesc for pg_class must already exist.  Therefore we must do
-	 * the check (and possible set) after cache insertion.
-	 *
-	 * XXX I believe the above comment is misguided; we should be running
-	 * in bootstrap or init processing mode here, and CatalogHasIndex
-	 * relies on hard-wired info in those cases.
+	/* In bootstrap mode, we have no indexes */
+	if (!IsBootstrapProcessingMode())
+	{
+		for (i = 0; IndexedCatalogNames[i] != NULL; i++)
+		{
+			if (strcmp(IndexedCatalogNames[i], relationName) == 0)
+			{
+				relation->rd_rel->relhasindex = true;
+				break;
+			}
+		}
+	}
+
+	/* ----------------
+	 *	add new reldesc to relcache
+	 * ----------------
 	 */
-	relation->rd_rel->relhasindex =
-		CatalogHasIndex(relationName, RelationGetRelid(relation));
+	RelationCacheInsert(relation);
 }
 
 
diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c
index e8f602c2ec2bb2c2a10113bc96e1aa8486cd008a..7f35f192089d5688a422136438ad6f72b8f0c001 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 7150a43d2df729c5e702feef75db8621906f614c..725586efdfde1adec9e8dcb81144f1871c905c8f 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 369dfd02c5963c227e8791bbfb19ff1ae192cdb5..e55b6492d8c8a77eb5b094235ed1931361935b3d 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));