diff --git a/src/backend/access/common/scankey.c b/src/backend/access/common/scankey.c
index eb66d41bf2..2611217191 100644
--- a/src/backend/access/common/scankey.c
+++ b/src/backend/access/common/scankey.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.19 2001/06/01 02:41:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/scankey.c,v 1.20 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -69,3 +69,31 @@ ScanKeyEntryInitialize(ScanKey entry,
 
 	Assert(ScanKeyEntryIsLegal(entry));
 }
+
+/*
+ * ScanKeyEntryInitializeWithInfo
+ *		Initializes a scan key entry using an already-completed FmgrInfo
+ *		function lookup record.
+ *
+ * mcxt is the memory context holding the scan key; it'll be used for
+ * any subsidiary info attached to the scankey's FmgrInfo record.
+ */
+void
+ScanKeyEntryInitializeWithInfo(ScanKey entry,
+							   bits16 flags,
+							   AttrNumber attributeNumber,
+							   FmgrInfo *finfo,
+							   MemoryContext mcxt,
+							   Datum argument)
+{
+	Assert(PointerIsValid(entry));
+	Assert(RegProcedureIsValid(finfo->fn_oid));
+
+	entry->sk_flags = flags;
+	entry->sk_attno = attributeNumber;
+	entry->sk_procedure = finfo->fn_oid;
+	entry->sk_argument = argument;
+	fmgr_info_copy(&entry->sk_func, finfo, mcxt);
+
+	Assert(ScanKeyEntryIsLegal(entry));
+}
diff --git a/src/backend/access/gist/gist.c b/src/backend/access/gist/gist.c
index e05e07b636..4a702fe317 100644
--- a/src/backend/access/gist/gist.c
+++ b/src/backend/access/gist/gist.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.83 2001/08/22 18:24:26 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gist.c,v 1.84 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1542,13 +1542,6 @@ gistbulkdelete(PG_FUNCTION_ARGS)
 void
 initGISTstate(GISTSTATE *giststate, Relation index)
 {
-	RegProcedure consistent_proc,
-				union_proc,
-				compress_proc,
-				decompress_proc,
-				penalty_proc,
-				picksplit_proc,
-				equal_proc;
 	int i;
 
 	if (index->rd_att->natts > INDEX_MAX_KEYS)
@@ -1559,20 +1552,27 @@ initGISTstate(GISTSTATE *giststate, Relation index)
 
 	for (i = 0; i < index->rd_att->natts; i++)
 	{
-		consistent_proc = index_getprocid(index, i+1, GIST_CONSISTENT_PROC	);
-		union_proc 	= index_getprocid(index, i+1, GIST_UNION_PROC		);
-		compress_proc 	= index_getprocid(index, i+1, GIST_COMPRESS_PROC	);
-		decompress_proc = index_getprocid(index, i+1, GIST_DECOMPRESS_PROC	);
-		penalty_proc 	= index_getprocid(index, i+1, GIST_PENALTY_PROC		);
-		picksplit_proc 	= index_getprocid(index, i+1, GIST_PICKSPLIT_PROC	);
-		equal_proc 	= index_getprocid(index, i+1, GIST_EQUAL_PROC		);
-		fmgr_info(consistent_proc, 	&((giststate->consistentFn)[i]) 	);
-		fmgr_info(union_proc, 		&((giststate->unionFn)[i]) 		);
-		fmgr_info(compress_proc, 	&((giststate->compressFn)[i]) 		);
-		fmgr_info(decompress_proc, 	&((giststate->decompressFn)[i]) 	);
-		fmgr_info(penalty_proc, 	&((giststate->penaltyFn)[i]) 		);
-		fmgr_info(picksplit_proc, 	&((giststate->picksplitFn)[i]) 		);
-		fmgr_info(equal_proc, 		&((giststate->equalFn)[i]) 		);
+		fmgr_info_copy(&(giststate->consistentFn[i]),
+					   index_getprocinfo(index, i+1, GIST_CONSISTENT_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->unionFn[i]),
+					   index_getprocinfo(index, i+1, GIST_UNION_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->compressFn[i]),
+					   index_getprocinfo(index, i+1, GIST_COMPRESS_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->decompressFn[i]),
+					   index_getprocinfo(index, i+1, GIST_DECOMPRESS_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->penaltyFn[i]),
+					   index_getprocinfo(index, i+1, GIST_PENALTY_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->picksplitFn[i]),
+					   index_getprocinfo(index, i+1, GIST_PICKSPLIT_PROC),
+					   CurrentMemoryContext);
+		fmgr_info_copy(&(giststate->equalFn[i]),
+					   index_getprocinfo(index, i+1, GIST_EQUAL_PROC),
+					   CurrentMemoryContext);
 	}
 }
 
diff --git a/src/backend/access/hash/hashutil.c b/src/backend/access/hash/hashutil.c
index 0aac61fa02..4680061118 100644
--- a/src/backend/access/hash/hashutil.c
+++ b/src/backend/access/hash/hashutil.c
@@ -8,13 +8,14 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.26 2001/02/22 21:48:49 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hashutil.c,v 1.27 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
 
 #include "postgres.h"
 
+#include "access/genam.h"
 #include "access/hash.h"
 #include "access/iqual.h"
 
@@ -27,8 +28,8 @@ _hash_mkscankey(Relation rel, IndexTuple itup, HashMetaPage metap)
 	int			natts;
 	AttrNumber	i;
 	Datum		arg;
-	RegProcedure proc;
-	bool		null;
+	FmgrInfo   *procinfo;
+	bool		isnull;
 
 	natts = rel->rd_rel->relnatts;
 	itupdesc = RelationGetDescr(rel);
@@ -37,10 +38,14 @@ _hash_mkscankey(Relation rel, IndexTuple itup, HashMetaPage metap)
 
 	for (i = 0; i < natts; i++)
 	{
-		arg = index_getattr(itup, i + 1, itupdesc, &null);
-		proc = metap->hashm_procid;
-		ScanKeyEntryInitialize(&skey[i],
-							   0x0, (AttrNumber) (i + 1), proc, arg);
+		arg = index_getattr(itup, i + 1, itupdesc, &isnull);
+		procinfo = index_getprocinfo(rel, i + 1, HASHPROC);
+		ScanKeyEntryInitializeWithInfo(&skey[i],
+									   0x0,
+									   (AttrNumber) (i + 1),
+									   procinfo,
+									   CurrentMemoryContext,
+									   arg);
 	}
 
 	return skey;
@@ -89,10 +94,13 @@ _hash_formitem(IndexTuple itup)
 Bucket
 _hash_call(Relation rel, HashMetaPage metap, Datum key)
 {
+	FmgrInfo   *procinfo;
 	uint32		n;
 	Bucket		bucket;
 
-	n = DatumGetUInt32(OidFunctionCall1(metap->hashm_procid, key));
+	/* XXX assumes index has only one attribute */
+	procinfo = index_getprocinfo(rel, 1, HASHPROC);
+	n = DatumGetUInt32(FunctionCall1(procinfo, key));
 	bucket = n & metap->hashm_highmask;
 	if (bucket > metap->hashm_maxbucket)
 		bucket = bucket & metap->hashm_lowmask;
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 2b6be06168..2a1d3294dd 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.52 2001/07/15 22:48:15 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.53 2001/10/06 23:21:43 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relationId
@@ -428,12 +428,58 @@ index_getprocid(Relation irel,
 {
 	RegProcedure *loc;
 	int			nproc;
+	int			procindex;
 
 	nproc = irel->rd_am->amsupport;
 
+	Assert(procnum > 0 && procnum <= (uint16) nproc);
+
+	procindex = (nproc * (attnum - 1)) + (procnum - 1);
+
 	loc = irel->rd_support;
 
 	Assert(loc != NULL);
 
-	return loc[(nproc * (attnum - 1)) + (procnum - 1)];
+	return loc[procindex];
+}
+
+/* ----------------
+ *		index_getprocinfo
+ *
+ *		This routine allows index AMs to keep fmgr lookup info for
+ *		support procs in the relcache.
+ * ----------------
+ */
+struct FmgrInfo *
+index_getprocinfo(Relation irel,
+				  AttrNumber attnum,
+				  uint16 procnum)
+{
+	FmgrInfo   *locinfo;
+	int			nproc;
+	int			procindex;
+
+	nproc = irel->rd_am->amsupport;
+
+	Assert(procnum > 0 && procnum <= (uint16) nproc);
+
+	procindex = (nproc * (attnum - 1)) + (procnum - 1);
+
+	locinfo = irel->rd_supportinfo;
+
+	Assert(locinfo != NULL);
+
+	locinfo += procindex;
+
+	/* Initialize the lookup info if first time through */
+	if (locinfo->fn_oid == InvalidOid)
+	{
+		RegProcedure *loc = irel->rd_support;
+
+		Assert(loc != NULL);
+
+		fmgr_info_cxt(loc[procindex], locinfo, irel->rd_indexcxt);
+	}
+
+	return locinfo;
 }
diff --git a/src/backend/access/index/istrat.c b/src/backend/access/index/istrat.c
index 35df06aeac..568581fc18 100644
--- a/src/backend/access/index/istrat.c
+++ b/src/backend/access/index/istrat.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.52 2001/08/21 16:36:00 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/Attic/istrat.c,v 1.53 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -486,12 +486,9 @@ FillScanKeyEntry(Oid operatorObjectId, ScanKey entry)
 			 operatorObjectId);
 
 	/*
-	 * Formerly we initialized entry->sk_func here, but that's a waste of
-	 * time because ScanKey entries in strategy maps are never actually
-	 * used to invoke the operator.  Furthermore, to do that we'd have to
-	 * worry about setting the proper memory context (the map is probably
-	 * not allocated in the current memory context!)
+	 * Mark entry->sk_func invalid, until and unless someone sets it up.
 	 */
+	entry->sk_func.fn_oid = InvalidOid;
 }
 
 
diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 295387ed51..86ff810845 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.67 2001/07/15 22:48:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.68 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -435,7 +435,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	BlockNumber blkno;
 	StrategyNumber strat;
 	RetrieveIndexResult res;
-	RegProcedure proc;
 	int32		result;
 	BTScanOpaque so;
 	bool		continuescan;
@@ -532,6 +531,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	scankeys = (ScanKey) palloc(keysCount * sizeof(ScanKeyData));
 	for (i = 0; i < keysCount; i++)
 	{
+		FmgrInfo   *procinfo;
+
 		j = nKeyIs[i];
 
 		/*
@@ -545,9 +546,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 			elog(ERROR, "_bt_first: btree doesn't support is(not)null, yet");
 			return ((RetrieveIndexResult) NULL);
 		}
-		proc = index_getprocid(rel, i + 1, BTORDER_PROC);
-		ScanKeyEntryInitialize(scankeys + i, so->keyData[j].sk_flags,
-							   i + 1, proc, so->keyData[j].sk_argument);
+		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
+		ScanKeyEntryInitializeWithInfo(scankeys + i,
+									   so->keyData[j].sk_flags,
+									   i + 1,
+									   procinfo,
+									   CurrentMemoryContext,
+									   so->keyData[j].sk_argument);
 	}
 	if (nKeyIs)
 		pfree(nKeyIs);
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 28aa99237d..86d2e3cf8f 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.45 2001/05/17 14:59:31 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.46 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,7 +36,7 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 	TupleDesc	itupdesc;
 	int			natts;
 	int			i;
-	RegProcedure proc;
+	FmgrInfo   *procinfo;
 	Datum		arg;
 	bool		null;
 	bits16		flag;
@@ -48,14 +48,15 @@ _bt_mkscankey(Relation rel, IndexTuple itup)
 
 	for (i = 0; i < natts; i++)
 	{
-		proc = index_getprocid(rel, i + 1, BTORDER_PROC);
+		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
 		arg = index_getattr(itup, i + 1, itupdesc, &null);
 		flag = null ? SK_ISNULL : 0x0;
-		ScanKeyEntryInitialize(&skey[i],
-							   flag,
-							   (AttrNumber) (i + 1),
-							   proc,
-							   arg);
+		ScanKeyEntryInitializeWithInfo(&skey[i],
+									   flag,
+									   (AttrNumber) (i + 1),
+									   procinfo,
+									   CurrentMemoryContext,
+									   arg);
 	}
 
 	return skey;
@@ -76,7 +77,7 @@ _bt_mkscankey_nodata(Relation rel)
 	ScanKey		skey;
 	int			natts;
 	int			i;
-	RegProcedure proc;
+	FmgrInfo   *procinfo;
 
 	natts = RelationGetNumberOfAttributes(rel);
 
@@ -84,12 +85,13 @@ _bt_mkscankey_nodata(Relation rel)
 
 	for (i = 0; i < natts; i++)
 	{
-		proc = index_getprocid(rel, i + 1, BTORDER_PROC);
-		ScanKeyEntryInitialize(&skey[i],
-							   SK_ISNULL,
-							   (AttrNumber) (i + 1),
-							   proc,
-							   (Datum) NULL);
+		procinfo = index_getprocinfo(rel, i + 1, BTORDER_PROC);
+		ScanKeyEntryInitializeWithInfo(&skey[i],
+									   SK_ISNULL,
+									   (AttrNumber) (i + 1),
+									   procinfo,
+									   CurrentMemoryContext,
+									   (Datum) 0);
 	}
 
 	return skey;
diff --git a/src/backend/access/rtree/rtree.c b/src/backend/access/rtree/rtree.c
index f3b46f3144..42878248b0 100644
--- a/src/backend/access/rtree/rtree.c
+++ b/src/backend/access/rtree/rtree.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.64 2001/09/29 03:46:12 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtree.c,v 1.65 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1264,17 +1264,15 @@ rtbulkdelete(PG_FUNCTION_ARGS)
 static void
 initRtstate(RTSTATE *rtstate, Relation index)
 {
-	RegProcedure union_proc,
-				size_proc,
-				inter_proc;
-
-	union_proc = index_getprocid(index, 1, RT_UNION_PROC);
-	size_proc = index_getprocid(index, 1, RT_SIZE_PROC);
-	inter_proc = index_getprocid(index, 1, RT_INTER_PROC);
-	fmgr_info(union_proc, &rtstate->unionFn);
-	fmgr_info(size_proc, &rtstate->sizeFn);
-	fmgr_info(inter_proc, &rtstate->interFn);
-	return;
+	fmgr_info_copy(&rtstate->unionFn,
+				   index_getprocinfo(index, 1, RT_UNION_PROC),
+				   CurrentMemoryContext);
+	fmgr_info_copy(&rtstate->sizeFn,
+				   index_getprocinfo(index, 1, RT_SIZE_PROC),
+				   CurrentMemoryContext);
+	fmgr_info_copy(&rtstate->interFn,
+				   index_getprocinfo(index, 1, RT_INTER_PROC),
+				   CurrentMemoryContext);
 }
 
 /* for sorting SPLITCOST records in descending order */
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index b68488ae00..599e79a4ea 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.176 2001/09/06 02:07:42 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.177 2001/10/06 23:21:43 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -973,10 +973,8 @@ RelationTruncateIndexes(Oid heapId)
 
 	while (HeapTupleIsValid(indexTuple = heap_getnext(scan, 0)))
 	{
-		Oid			indexId,
-					accessMethodId;
+		Oid			indexId;
 		IndexInfo  *indexInfo;
-		HeapTuple	classTuple;
 		Relation	heapRelation,
 					currentIndex;
 
@@ -986,16 +984,6 @@ RelationTruncateIndexes(Oid heapId)
 		indexId = ((Form_pg_index) GETSTRUCT(indexTuple))->indexrelid;
 		indexInfo = BuildIndexInfo(indexTuple);
 
-		/* Fetch access method from pg_class tuple for this index */
-		classTuple = SearchSysCache(RELOID,
-									ObjectIdGetDatum(indexId),
-									0, 0, 0);
-		if (!HeapTupleIsValid(classTuple))
-			elog(ERROR, "RelationTruncateIndexes: index %u not found in pg_class",
-				 indexId);
-		accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
-		ReleaseSysCache(classTuple);
-
 		/*
 		 * We have to re-open the heap rel each time through this loop
 		 * because index_build will close it again.  We need grab no lock,
@@ -1022,8 +1010,6 @@ RelationTruncateIndexes(Oid heapId)
 		currentIndex->rd_targblock = InvalidBlockNumber;
 
 		/* Initialize the index and rebuild */
-		InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
-						  currentIndex, accessMethodId);
 		index_build(heapRelation, currentIndex, indexInfo);
 
 		/*
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index c850c55a0f..b53eab8652 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.164 2001/09/26 21:09:27 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.165 2001/10/06 23:21:43 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -644,76 +644,6 @@ UpdateIndexRelation(Oid indexoid,
 	heap_freetuple(tuple);
 }
 
-/* ----------------------------------------------------------------
- *		InitIndexStrategy
- *
- * XXX this is essentially the same as relcache.c's
- * IndexedAccessMethodInitialize(), and probably ought to be merged with it.
- * ----------------------------------------------------------------
- */
-void
-InitIndexStrategy(int numatts,
-				  Relation indexRelation,
-				  Oid accessMethodObjectId)
-{
-	IndexStrategy strategy;
-	RegProcedure *support;
-	uint16		amstrategies;
-	uint16		amsupport;
-	Size		strsize;
-
-	/*
-	 * get information from the index relation descriptor
-	 */
-	amstrategies = indexRelation->rd_am->amstrategies;
-	amsupport = indexRelation->rd_am->amsupport;
-
-	/*
-	 * compute the size of the strategy array
-	 */
-	strsize = AttributeNumberGetIndexStrategySize(numatts, amstrategies);
-
-	/*
-	 * allocate the new index strategy structure
-	 *
-	 * the index strategy has to be allocated in the same context as the
-	 * relation descriptor cache or else it will be lost at the end of the
-	 * transaction.
-	 */
-	if (!CacheMemoryContext)
-		CreateCacheMemoryContext();
-
-	strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext,
-												  strsize);
-
-	if (amsupport > 0)
-	{
-		strsize = numatts * (amsupport * sizeof(RegProcedure));
-		support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext,
-													  strsize);
-	}
-	else
-		support = (RegProcedure *) NULL;
-
-	/*
-	 * fill in the index strategy structure with information from the
-	 * catalogs.  First we must advance the command counter so that we
-	 * will see the newly-entered index catalog tuples.
-	 */
-	CommandCounterIncrement();
-
-	IndexSupportInitialize(strategy, support,
-						   &indexRelation->rd_uniqueindex,
-						   RelationGetRelid(indexRelation),
-						   accessMethodObjectId,
-						   amstrategies, amsupport, numatts);
-
-	/*
-	 * store the strategy information in the index reldesc
-	 */
-	RelationSetIndexSupport(indexRelation, strategy, support);
-}
-
 
 /* ----------------------------------------------------------------
  *		index_create
@@ -839,11 +769,13 @@ index_create(char *heapRelationName,
 						classObjectId, primary);
 
 	/*
-	 * initialize the index strategy
+	 * fill in the index strategy structure with information from the
+	 * catalogs.  First we must advance the command counter so that we
+	 * will see the newly-entered index catalog tuples.
 	 */
-	InitIndexStrategy(indexInfo->ii_NumIndexAttrs,
-					  indexRelation,
-					  accessMethodObjectId);
+	CommandCounterIncrement();
+
+	RelationInitIndexAccessInfo(indexRelation);
 
 	/*
 	 * If this is bootstrap (initdb) time, then we don't actually fill in
@@ -1935,11 +1867,9 @@ reindex_index(Oid indexId, bool force, bool inplace)
 				heapRelation;
 	ScanKeyData entry;
 	HeapScanDesc scan;
-	HeapTuple	indexTuple,
-				classTuple;
+	HeapTuple	indexTuple;
 	IndexInfo  *indexInfo;
-	Oid			heapId,
-				accessMethodId;
+	Oid			heapId;
 	bool		old;
 
 	/*
@@ -1970,15 +1900,6 @@ reindex_index(Oid indexId, bool force, bool inplace)
 	heap_endscan(scan);
 	heap_close(indexRelation, AccessShareLock);
 
-	/* Fetch the classTuple associated with this index */
-	classTuple = SearchSysCache(RELOID,
-								ObjectIdGetDatum(indexId),
-								0, 0, 0);
-	if (!HeapTupleIsValid(classTuple))
-		elog(ERROR, "reindex_index: index %u not found in pg_class", indexId);
-	accessMethodId = ((Form_pg_class) GETSTRUCT(classTuple))->relam;
-	ReleaseSysCache(classTuple);
-
 	/* Open our index relation */
 	heapRelation = heap_open(heapId, ExclusiveLock);
 	if (heapRelation == NULL)
@@ -2012,7 +1933,6 @@ reindex_index(Oid indexId, bool force, bool inplace)
 	}
 
 	/* Initialize the index and rebuild */
-	InitIndexStrategy(indexInfo->ii_NumIndexAttrs, iRel, accessMethodId);
 	index_build(heapRelation, iRel, indexInfo);
 
 	/*
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index c154762175..e83d35edbf 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.60 2001/10/02 21:39:35 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.61 2001/10/06 23:21:43 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -246,11 +246,14 @@ ProcedureCreate(char *procedureName,
 
 	if (languageObjectId == ClanguageId)
 	{
+		void   *libraryhandle;
+
 		/* If link symbol is specified as "-", substitute procedure name */
 		if (strcmp(prosrc, "-") == 0)
 			prosrc = procedureName;
-		(void) load_external_function(probin, prosrc, true);
-		(void) fetch_finfo_record(probin, prosrc);
+		(void) load_external_function(probin, prosrc, true,
+									  &libraryhandle);
+		(void) fetch_finfo_record(libraryhandle, prosrc);
 	}
 
 	/*
diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c
index ebbb8b07ee..a03ca77440 100644
--- a/src/backend/utils/adt/ri_triggers.c
+++ b/src/backend/utils/adt/ri_triggers.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 2000-2001, PostgreSQL Global Development Group
  * Copyright 1999 Jan Wieck
  *
- * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.27 2001/10/05 17:28:12 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.28 2001/10/06 23:21:44 tgl Exp $
  *
  * ----------
  */
@@ -3243,7 +3243,6 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
 	{
 		HeapTuple	opr_tup;
 		Oid			opr_proc;
-		MemoryContext	oldcontext;
 		FmgrInfo	finfo;
 
 		opr_tup = SearchSysCache(OPERNAME,
@@ -3265,9 +3264,7 @@ ri_AttributesEqual(Oid typeid, Datum oldvalue, Datum newvalue)
 		 * table entry, we must make sure any subsidiary structures of the
 		 * fmgr record are kept in TopMemoryContext.
 		 */
-		oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-		fmgr_info(opr_proc, &finfo);
-		MemoryContextSwitchTo(oldcontext);
+		fmgr_info_cxt(opr_proc, &finfo, TopMemoryContext);
 
 		entry = (RI_OpreqHashEntry *) hash_search(ri_opreq_cache,
 												  (void *) &typeid,
diff --git a/src/backend/utils/adt/varbit.c b/src/backend/utils/adt/varbit.c
index d75d05309d..a294bfc9ff 100644
--- a/src/backend/utils/adt/varbit.c
+++ b/src/backend/utils/adt/varbit.c
@@ -9,7 +9,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.18 2001/05/22 16:37:16 petere Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varbit.c,v 1.19 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,6 +19,7 @@
 #include "catalog/pg_type.h"
 #include "utils/array.h"
 #include "utils/fmgroids.h"
+#include "utils/memutils.h"
 #include "utils/varbit.h"
 
 #define HEXDIG(z)	 ((z)<10 ? ((z)+'0') : ((z)-10+'A'))
@@ -238,7 +239,7 @@ _bit(PG_FUNCTION_ARGS)
 	static FmgrInfo bit_finfo;
 
 	if (bit_finfo.fn_oid == InvalidOid)
-		fmgr_info(F_BIT, &bit_finfo);
+		fmgr_info_cxt(F_BIT, &bit_finfo, TopMemoryContext);
 
 	MemSet(&locfcinfo, 0, sizeof(locfcinfo));
 	locfcinfo.flinfo = &bit_finfo;
@@ -452,7 +453,7 @@ _varbit(PG_FUNCTION_ARGS)
 	static FmgrInfo varbit_finfo;
 
 	if (varbit_finfo.fn_oid == InvalidOid)
-		fmgr_info(F_VARBIT, &varbit_finfo);
+		fmgr_info_cxt(F_VARBIT, &varbit_finfo, TopMemoryContext);
 
 	MemSet(&locfcinfo, 0, sizeof(locfcinfo));
 	locfcinfo.flinfo = &varbit_finfo;
diff --git a/src/backend/utils/adt/varchar.c b/src/backend/utils/adt/varchar.c
index 7ed56e7962..c963709ac8 100644
--- a/src/backend/utils/adt/varchar.c
+++ b/src/backend/utils/adt/varchar.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.83 2001/10/03 05:29:24 thomas Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/varchar.c,v 1.84 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -285,7 +285,7 @@ _bpchar(PG_FUNCTION_ARGS)
 	static FmgrInfo bpchar_finfo;
 
 	if (bpchar_finfo.fn_oid == InvalidOid)
-		fmgr_info(F_BPCHAR, &bpchar_finfo);
+		fmgr_info_cxt(F_BPCHAR, &bpchar_finfo, TopMemoryContext);
 
 	MemSet(&locfcinfo, 0, sizeof(locfcinfo));
 	locfcinfo.flinfo = &bpchar_finfo;
@@ -544,7 +544,7 @@ _varchar(PG_FUNCTION_ARGS)
 	static FmgrInfo varchar_finfo;
 
 	if (varchar_finfo.fn_oid == InvalidOid)
-		fmgr_info(F_VARCHAR, &varchar_finfo);
+		fmgr_info_cxt(F_VARCHAR, &varchar_finfo, TopMemoryContext);
 
 	MemSet(&locfcinfo, 0, sizeof(locfcinfo));
 	locfcinfo.flinfo = &varchar_finfo;
diff --git a/src/backend/utils/cache/Makefile b/src/backend/utils/cache/Makefile
index 01896efdd3..5ac5a06827 100644
--- a/src/backend/utils/cache/Makefile
+++ b/src/backend/utils/cache/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for utils/cache
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.14 2000/08/31 16:10:46 petere Exp $
+#    $Header: /cvsroot/pgsql/src/backend/utils/cache/Makefile,v 1.15 2001/10/06 23:21:44 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -12,7 +12,7 @@ subdir = src/backend/utils/cache
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = catcache.o inval.o rel.o relcache.o syscache.o lsyscache.o \
+OBJS = catcache.o inval.o relcache.o syscache.o lsyscache.o \
 	fcache.o temprel.o
 
 all: SUBSYS.o
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c
index ce4363706b..77112a694e 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.82 2001/08/21 16:36:04 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/catcache.c,v 1.83 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -269,23 +269,10 @@ CatalogCacheInitializeCache(CatCache *cache)
 		 */
 		cache->cc_skey[i].sk_procedure = EQPROC(keytype);
 
-		/*
-		 * Note: to avoid any possible leakage of scan temporary data into
-		 * the cache context, we do not switch into CacheMemoryContext while
-		 * calling fmgr_info here.  Instead set fn_mcxt on return.  This
-		 * would fail to work correctly if fmgr_info allocated any subsidiary
-		 * data structures to attach to the FmgrInfo record; but it doesn't
-		 * do so for built-in functions, and all the comparator functions
-		 * for system caches should most assuredly be built-in functions.
-		 * Currently there's no real need to fix fn_mcxt either, but let's do
-		 * that anyway just to make sure it's not pointing to a dead context
-		 * later on.
-		 */
-
-		fmgr_info(cache->cc_skey[i].sk_procedure,
-				  &cache->cc_skey[i].sk_func);
-
-		cache->cc_skey[i].sk_func.fn_mcxt = CacheMemoryContext;
+		/* Do function lookup */
+		fmgr_info_cxt(cache->cc_skey[i].sk_procedure,
+					  &cache->cc_skey[i].sk_func,
+					  CacheMemoryContext);
 
 		/* Initialize sk_attno suitably for HeapKeyTest() and heap scans */
 		cache->cc_skey[i].sk_attno = cache->cc_key[i];
diff --git a/src/backend/utils/cache/fcache.c b/src/backend/utils/cache/fcache.c
index bb1ac36f3e..92cf46a036 100644
--- a/src/backend/utils/cache/fcache.c
+++ b/src/backend/utils/cache/fcache.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.40 2001/09/21 00:11:31 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/fcache.c,v 1.41 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,26 +23,22 @@
 FunctionCachePtr
 init_fcache(Oid foid, int nargs, MemoryContext fcacheCxt)
 {
-	MemoryContext oldcontext;
 	FunctionCachePtr retval;
 
 	/* Safety check (should never fail, as parser should check sooner) */
 	if (nargs > FUNC_MAX_ARGS)
 		elog(ERROR, "init_fcache: too many arguments");
 
-	/* Switch to a context long-lived enough for the fcache entry */
-	oldcontext = MemoryContextSwitchTo(fcacheCxt);
-
-	retval = (FunctionCachePtr) palloc(sizeof(FunctionCache));
+	/* Create fcache entry in the desired context */
+	retval = (FunctionCachePtr) MemoryContextAlloc(fcacheCxt,
+												   sizeof(FunctionCache));
 	MemSet(retval, 0, sizeof(FunctionCache));
 
 	/* Set up the primary fmgr lookup information */
-	fmgr_info(foid, &(retval->func));
+	fmgr_info_cxt(foid, &(retval->func), fcacheCxt);
 
 	/* Initialize additional info */
 	retval->setArgsValid = false;
 
-	MemoryContextSwitchTo(oldcontext);
-
 	return retval;
 }
diff --git a/src/backend/utils/cache/rel.c b/src/backend/utils/cache/rel.c
deleted file mode 100644
index 588566afc4..0000000000
--- a/src/backend/utils/cache/rel.c
+++ /dev/null
@@ -1,49 +0,0 @@
-/*-------------------------------------------------------------------------
- *
- * rel.c
- *	  POSTGRES relation descriptor code.
- *
- * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
- * Portions Copyright (c) 1994, Regents of the University of California
- *
- *
- * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/Attic/rel.c,v 1.9 2001/01/24 19:43:15 momjian Exp $
- *
- *-------------------------------------------------------------------------
- */
-
-#include "postgres.h"
-#include "access/istrat.h"
-
-
-/*
- *		RelationIsValid is now a macro in rel.h -cim 4/27/91
- *
- *		All of the RelationGet...() functions are now macros in rel.h
- *				-mer 3/2/92
- */
-
-/*
- * RelationSetIndexSupport
- *		Sets index strategy and support info for a relation.
- *
- *		This routine saves two pointers -- one to the IndexStrategy, and
- *		one to the RegProcs that support the indexed access method.
- *
- * Note:
- *		Assumes relation descriptor is valid.
- *		Assumes index strategy is valid.  Assumes support is valid if non-
- *		NULL.
- */
-void
-RelationSetIndexSupport(Relation relation,
-						IndexStrategy strategy,
-						RegProcedure *support)
-{
-	Assert(PointerIsValid(relation));
-	Assert(IndexStrategyIsValid(strategy));
-
-	relation->rd_istrat = strategy;
-	relation->rd_support = support;
-}
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index 8d85487139..c56d606076 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.145 2001/10/05 17:28:12 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.146 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -249,7 +249,6 @@ static void build_tupdesc_ind(RelationBuildDescInfo buildinfo,
 				  Relation relation);
 static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo,
 				  Relation oldrelation);
-static void IndexedAccessMethodInitialize(Relation relation);
 static void AttrDefaultFetch(Relation relation);
 static void RelCheckFetch(Relation relation);
 static List *insert_ordered_oid(List *list, Oid datum);
@@ -1044,7 +1043,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	 * initialize index strategy and support information for this relation
 	 */
 	if (OidIsValid(relam))
-		IndexedAccessMethodInitialize(relation);
+		RelationInitIndexAccessInfo(relation);
 
 	/*
 	 * initialize the relation lock manager information
@@ -1087,41 +1086,75 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	return relation;
 }
 
-static void
-IndexedAccessMethodInitialize(Relation relation)
+/*
+ * Initialize index-access-method support data for an index relation
+ */
+void
+RelationInitIndexAccessInfo(Relation relation)
 {
+	MemoryContext indexcxt;
 	IndexStrategy strategy;
 	RegProcedure *support;
+	FmgrInfo   *supportinfo;
 	int			natts;
-	Size		stratSize;
-	Size		supportSize;
 	uint16		amstrategies;
 	uint16		amsupport;
+	Size		stratSize;
 
 	natts = relation->rd_rel->relnatts;
 	amstrategies = relation->rd_am->amstrategies;
 	amsupport = relation->rd_am->amsupport;
 
+	/*
+	 * Make the private context to hold index access info.  The reason
+	 * we need a context, and not just a couple of pallocs, is so that
+	 * we won't leak any subsidiary info attached to fmgr lookup records.
+	 *
+	 * Context parameters are set on the assumption that it'll probably not
+	 * contain much data.
+	 */
+	indexcxt = AllocSetContextCreate(CacheMemoryContext,
+									 RelationGetRelationName(relation),
+									 0,			/* minsize */
+									 512,		/* initsize */
+									 1024);		/* maxsize */
+	relation->rd_indexcxt = indexcxt;
+
+	/*
+	 * Allocate arrays to hold data
+	 */
 	stratSize = AttributeNumberGetIndexStrategySize(natts, amstrategies);
-	strategy = (IndexStrategy) MemoryContextAlloc(CacheMemoryContext,
-												  stratSize);
+	strategy = (IndexStrategy) MemoryContextAlloc(indexcxt, stratSize);
 
 	if (amsupport > 0)
 	{
-		supportSize = natts * (amsupport * sizeof(RegProcedure));
-		support = (RegProcedure *) MemoryContextAlloc(CacheMemoryContext,
-													  supportSize);
+		int		nsupport = natts * amsupport;
+
+		support = (RegProcedure *)
+			MemoryContextAlloc(indexcxt, nsupport * sizeof(RegProcedure));
+		supportinfo = (FmgrInfo *)
+			MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo));
+		MemSet(supportinfo, 0, nsupport * sizeof(FmgrInfo));
 	}
 	else
-		support = (RegProcedure *) NULL;
+	{
+		support = NULL;
+		supportinfo = NULL;
+	}
 
+	/*
+	 * Fill the strategy map and the support RegProcedure arrays.
+	 * (supportinfo is left as zeroes, and is filled on-the-fly when used)
+	 */
 	IndexSupportInitialize(strategy, support,
 						   &relation->rd_uniqueindex,
 						   RelationGetRelid(relation),
 						   relation->rd_rel->relam,
 						   amstrategies, amsupport, natts);
 
-	RelationSetIndexSupport(relation, strategy, support);
+	relation->rd_istrat = strategy;
+	relation->rd_support = support;
+	relation->rd_supportinfo = supportinfo;
 }
 
 /*
@@ -1595,11 +1628,9 @@ RelationClearRelation(Relation relation, bool rebuildIt)
 		pfree(relation->rd_am);
 	if (relation->rd_rel)
 		pfree(relation->rd_rel);
-	if (relation->rd_istrat)
-		pfree(relation->rd_istrat);
-	if (relation->rd_support)
-		pfree(relation->rd_support);
 	freeList(relation->rd_indexlist);
+	if (relation->rd_indexcxt)
+		MemoryContextDelete(relation->rd_indexcxt);
 
 	/*
 	 * If we're really done with the relcache entry, blow it away. But if
@@ -2624,8 +2655,11 @@ init_irels(void)
 	Relation	ird;
 	Form_pg_am	am;
 	Form_pg_class relform;
+	MemoryContext indexcxt;
 	IndexStrategy strat;
 	RegProcedure *support;
+	int			nstrategies,
+				nsupport;
 	int			i;
 	int			relno;
 
@@ -2646,6 +2680,13 @@ init_irels(void)
 			return;
 		}
 
+		/* safety check for incompatible relcache layout */
+		if (len != sizeof(RelationData))
+		{
+			write_irels();
+			return;
+		}
+
 		ird = irel[relno] = (Relation) palloc(len);
 		MemSet(ird, 0, len);
 
@@ -2659,6 +2700,7 @@ init_irels(void)
 		/* reset transient fields */
 		ird->rd_targblock = InvalidBlockNumber;
 		ird->rd_fd = -1;
+		ird->rd_refcnt = 0;
 
 		ird->rd_node.tblNode = MyDatabaseId;
 
@@ -2716,6 +2758,17 @@ init_irels(void)
 			}
 		}
 
+		/*
+		 * prepare index info context --- parameters should match
+		 * RelationInitIndexAccessInfo
+		 */
+		indexcxt = AllocSetContextCreate(CacheMemoryContext,
+										 RelationGetRelationName(ird),
+										 0,			/* minsize */
+										 512,		/* initsize */
+										 1024);		/* maxsize */
+		ird->rd_indexcxt = indexcxt;
+
 		/* next, read the index strategy map */
 		if ((nread = FileRead(fd, (char *) &len, sizeof(len))) != sizeof(len))
 		{
@@ -2723,27 +2776,18 @@ init_irels(void)
 			return;
 		}
 
-		strat = (IndexStrategy) palloc(len);
+		strat = (IndexStrategy) MemoryContextAlloc(indexcxt, len);
 		if ((nread = FileRead(fd, (char *) strat, len)) != len)
 		{
 			write_irels();
 			return;
 		}
 
-		/* oh, for god's sake... */
-#define SMD(i)	strat->strategyMapData[i].entry[0]
+		/* have to invalidate any FmgrInfo data in the strategy maps */
+		nstrategies = am->amstrategies * relform->relnatts;
+		for (i = 0; i < nstrategies; i++)
+			strat->strategyMapData[i].entry[0].sk_func.fn_oid = InvalidOid;
 
-		/* have to reinit the function pointers in the strategy maps */
-		for (i = 0; i < am->amstrategies * relform->relnatts; i++)
-		{
-			fmgr_info(SMD(i).sk_procedure,
-					  &(SMD(i).sk_func));
-		}
-
-		/*
-		 * use a real field called rd_istrat instead of the bogosity of
-		 * hanging invisible fields off the end of a structure - jolly
-		 */
 		ird->rd_istrat = strat;
 
 		/* finally, read the vector of support procedures */
@@ -2753,7 +2797,7 @@ init_irels(void)
 			return;
 		}
 
-		support = (RegProcedure *) palloc(len);
+		support = (RegProcedure *) MemoryContextAlloc(indexcxt, len);
 		if ((nread = FileRead(fd, (char *) support, len)) != len)
 		{
 			write_irels();
@@ -2761,6 +2805,11 @@ init_irels(void)
 		}
 		ird->rd_support = support;
 
+		nsupport = relform->relnatts * am->amsupport;
+		ird->rd_supportinfo = (FmgrInfo *)
+			MemoryContextAlloc(indexcxt, nsupport * sizeof(FmgrInfo));
+		MemSet(ird->rd_supportinfo, 0, nsupport * sizeof(FmgrInfo));
+
 		RelationInitLockInfo(ird);
 
 		RelationCacheInsert(ird);
diff --git a/src/backend/utils/fmgr/dfmgr.c b/src/backend/utils/fmgr/dfmgr.c
index f46d40c5c4..3085187d8a 100644
--- a/src/backend/utils/fmgr/dfmgr.c
+++ b/src/backend/utils/fmgr/dfmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.52 2001/10/04 19:13:55 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/dfmgr.c,v 1.53 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,14 +55,20 @@ static char * substitute_libpath_macro(const char * name);
 
 /*
  * Load the specified dynamic-link library file, and look for a function
- * named funcname in it.  If the function is not found, we raise an error
- * if signalNotFound is true, else return (PGFunction) NULL.  Note that
- * errors in loading the library will provoke elog regardless of
- * signalNotFound.
- */
+ * named funcname in it.  (funcname can be NULL to just load the file.)
+ *
+ * If the function is not found, we raise an error if signalNotFound is true,
+ * else return (PGFunction) NULL.  Note that errors in loading the library
+ * will provoke elog regardless of signalNotFound.
+ *
+ * If filehandle is not NULL, then *filehandle will be set to a handle
+ * identifying the library file.  The filehandle can be used with
+ * lookup_external_function to lookup additional functions in the same file
+ * at less cost than repeating load_external_function.
+  */
 PGFunction
 load_external_function(char *filename, char *funcname,
-					   bool signalNotFound)
+					   bool signalNotFound, void **filehandle)
 {
 	DynamicFileList *file_scanner;
 	PGFunction	retval;
@@ -130,6 +136,10 @@ load_external_function(char *filename, char *funcname,
 		file_tail = file_scanner;
 	}
 
+	/* Return handle if caller wants it. */
+	if (filehandle)
+		*filehandle = file_scanner->handle;
+
 	/*
 	 * If funcname is NULL, we only wanted to load the file.
 	 */
@@ -201,11 +211,20 @@ load_file(char *filename)
 		}
 	}
 
-	load_external_function(fullname, (char *) NULL, false);
+	load_external_function(fullname, (char *) NULL, false, (void *) NULL);
 
 	pfree(fullname);
 }
 
+/*
+ * Lookup a function whose library file is already loaded.
+ * Return (PGFunction) NULL if not found.
+ */
+PGFunction
+lookup_external_function(void *filehandle, char *funcname)
+{
+	return pg_dlsym(filehandle, funcname);
+}
 
 
 static bool
@@ -305,7 +324,7 @@ substitute_libpath_macro(const char * name)
 
 	AssertArg(name != NULL);
 
-	if (strlen(name) == 0 || name[0] != '$')
+	if (name[0] != '$')
 		return pstrdup(name);
 
 	macroname_len = strcspn(name + 1, "/") + 1;
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 45ca532de2..5faa8a155c 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.54 2001/08/14 22:21:58 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/fmgr/fmgr.c,v 1.55 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,11 +121,21 @@ fmgr_lookupByName(const char *name)
  * will be allocated in that context.  The caller must ensure that this
  * context is at least as long-lived as the info struct itself.  This is
  * not a problem in typical cases where the info struct is on the stack or
- * in freshly-palloc'd space, but one must take extra care when the info
- * struct is in a long-lived table.
+ * in freshly-palloc'd space.  However, if one intends to store an info
+ * struct in a long-lived table, it's better to use fmgr_info_cxt.
  */
 void
 fmgr_info(Oid functionId, FmgrInfo *finfo)
+{
+	fmgr_info_cxt(functionId, finfo, CurrentMemoryContext);
+}
+
+/*
+ * Fill a FmgrInfo struct, specifying a memory context in which its
+ * subsidiary data should go.
+ */
+void
+fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
 {
 	const FmgrBuiltin *fbp;
 	HeapTuple	procedureTuple;
@@ -139,7 +149,7 @@ fmgr_info(Oid functionId, FmgrInfo *finfo)
 	 */
 	finfo->fn_oid = InvalidOid;
 	finfo->fn_extra = NULL;
-	finfo->fn_mcxt = CurrentMemoryContext;
+	finfo->fn_mcxt = mcxt;
 
 	if ((fbp = fmgr_isbuiltin(functionId)) != NULL)
 	{
@@ -228,6 +238,7 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 				probinattr;
 	char	   *prosrcstring,
 			   *probinstring;
+	void	   *libraryhandle;
 	PGFunction	user_fn;
 	Pg_finfo_record *inforec;
 	Oldstyle_fnextra *fnextra;
@@ -250,22 +261,19 @@ fmgr_info_C_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 	probinstring = DatumGetCString(DirectFunctionCall1(textout, probinattr));
 
 	/* Look up the function itself */
-	user_fn = load_external_function(probinstring, prosrcstring, true);
+	user_fn = load_external_function(probinstring, prosrcstring, true,
+									 &libraryhandle);
 
 	/* Get the function information record (real or default) */
-	inforec = fetch_finfo_record(probinstring, prosrcstring);
+	inforec = fetch_finfo_record(libraryhandle, prosrcstring);
 
 	switch (inforec->api_version)
 	{
 		case 0:
 			/* Old style: need to use a handler */
 			finfo->fn_addr = fmgr_oldstyle;
-
-			/*
-			 * OK to use palloc here because fn_mcxt is
-			 * CurrentMemoryContext
-			 */
-			fnextra = (Oldstyle_fnextra *) palloc(sizeof(Oldstyle_fnextra));
+			fnextra = (Oldstyle_fnextra *)
+				MemoryContextAlloc(finfo->fn_mcxt, sizeof(Oldstyle_fnextra));
 			finfo->fn_extra = (void *) fnextra;
 			MemSet(fnextra, 0, sizeof(Oldstyle_fnextra));
 			fnextra->func = (func_ptr) user_fn;
@@ -335,6 +343,8 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
 
 /*
  * Fetch and validate the information record for the given external function.
+ * The function is specified by a handle for the containing library
+ * (obtained from load_external_function) as well as the function name.
  *
  * If no info function exists for the given name, it is not an error.
  * Instead we return a default info record for a version-0 function.
@@ -346,7 +356,7 @@ fmgr_info_other_lang(Oid functionId, FmgrInfo *finfo, HeapTuple procedureTuple)
  * pg_proc.
  */
 Pg_finfo_record *
-fetch_finfo_record(char *filename, char *funcname)
+fetch_finfo_record(void *filehandle, char *funcname)
 {
 	char	   *infofuncname;
 	PGFInfoFunction infofunc;
@@ -355,12 +365,12 @@ fetch_finfo_record(char *filename, char *funcname)
 
 	/* Compute name of info func */
 	infofuncname = (char *) palloc(strlen(funcname) + 10);
-	sprintf(infofuncname, "pg_finfo_%s", funcname);
+	strcpy(infofuncname, "pg_finfo_");
+	strcat(infofuncname, funcname);
 
 	/* Try to look up the info function */
-	infofunc = (PGFInfoFunction) load_external_function(filename,
-														infofuncname,
-														false);
+	infofunc = (PGFInfoFunction) lookup_external_function(filehandle,
+														  infofuncname);
 	if (infofunc == (PGFInfoFunction) NULL)
 	{
 		/* Not found --- assume version 0 */
@@ -391,6 +401,34 @@ fetch_finfo_record(char *filename, char *funcname)
 }
 
 
+/*
+ * Copy an FmgrInfo struct
+ *
+ * This is inherently somewhat bogus since we can't reliably duplicate
+ * language-dependent subsidiary info.  We cheat by zeroing fn_extra,
+ * instead, meaning that subsidiary info will have to be recomputed.
+ */
+void
+fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
+			   MemoryContext destcxt)
+{
+	memcpy(dstinfo, srcinfo, sizeof(FmgrInfo));
+	dstinfo->fn_mcxt = destcxt;
+	if (dstinfo->fn_addr == fmgr_oldstyle)
+	{
+		/* For oldstyle functions we must copy fn_extra */
+		Oldstyle_fnextra *fnextra;
+
+		fnextra = (Oldstyle_fnextra *)
+			MemoryContextAlloc(destcxt, sizeof(Oldstyle_fnextra));
+		memcpy(fnextra, srcinfo->fn_extra, sizeof(Oldstyle_fnextra));
+		dstinfo->fn_extra = (void *) fnextra;
+	}
+	else
+		dstinfo->fn_extra = NULL;
+}
+
+
 /*
  * Specialized lookup routine for ProcedureCreate(): given the alleged name
  * of an internal function, return the OID of the function.
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index db6795c093..0a70691e77 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: genam.h,v 1.26 2001/07/15 22:48:18 tgl Exp $
+ * $Id: genam.h,v 1.27 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,6 +56,8 @@ extern IndexBulkDeleteResult *index_bulk_delete(Relation relation,
 extern RegProcedure index_cost_estimator(Relation relation);
 extern RegProcedure index_getprocid(Relation irel, AttrNumber attnum,
 				uint16 procnum);
+extern struct FmgrInfo *index_getprocinfo(Relation irel, AttrNumber attnum,
+										  uint16 procnum);
 
 /* in genam.c */
 extern IndexScanDesc RelationGetIndexScan(Relation relation, bool scanFromEnd,
diff --git a/src/include/access/skey.h b/src/include/access/skey.h
index 4e49f51afb..304d5e4a46 100644
--- a/src/include/access/skey.h
+++ b/src/include/access/skey.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: skey.h,v 1.16 2001/06/09 18:16:59 tgl Exp $
+ * $Id: skey.h,v 1.17 2001/10/06 23:21:44 tgl Exp $
  *
  * Note:
  *		Needs more accessor/assignment routines.
@@ -44,5 +44,8 @@ typedef ScanKeyData *ScanKey;
 extern void ScanKeyEntrySetIllegal(ScanKey entry);
 extern void ScanKeyEntryInitialize(ScanKey entry, bits16 flags,
 	 AttrNumber attributeNumber, RegProcedure procedure, Datum argument);
+extern void ScanKeyEntryInitializeWithInfo(ScanKey entry, bits16 flags,
+	 AttrNumber attributeNumber, FmgrInfo *finfo,
+	 MemoryContext mcxt, Datum argument);
 
 #endif	 /* SKEY_H */
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index d3e3bae704..52956f807b 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: index.h,v 1.39 2001/08/21 16:36:05 tgl Exp $
+ * $Id: index.h,v 1.40 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -30,10 +30,6 @@ typedef void (*IndexBuildCallback) (Relation index,
 extern Form_pg_am AccessMethodObjectIdGetForm(Oid accessMethodObjectId,
 							MemoryContext resultCxt);
 
-extern void InitIndexStrategy(int numatts,
-				  Relation indexRelation,
-				  Oid accessMethodObjectId);
-
 extern Oid index_create(char *heapRelationName,
 			 char *indexRelationName,
 			 IndexInfo *indexInfo,
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 44641bdcb1..0acb966f68 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -11,7 +11,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: fmgr.h,v 1.14 2001/05/17 17:44:18 petere Exp $
+ * $Id: fmgr.h,v 1.15 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -35,7 +35,7 @@ typedef Datum (*PGFunction) (FunctionCallInfo fcinfo);
  * to be called multiple times, the lookup need be done only once and the
  * info struct saved for re-use.
  */
-typedef struct
+typedef struct FmgrInfo
 {
 	PGFunction	fn_addr;		/* pointer to function or handler to be
 								 * called */
@@ -72,6 +72,20 @@ typedef struct FunctionCallInfoData
  */
 extern void fmgr_info(Oid functionId, FmgrInfo *finfo);
 
+/*
+ * Same, when the FmgrInfo struct is in a memory context longer-lived than
+ * CurrentMemoryContext.  The specified context will be set as fn_mcxt
+ * and used to hold all subsidiary data of finfo.
+ */
+extern void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo,
+						  MemoryContext mcxt);
+
+/*
+ * Copy an FmgrInfo struct
+ */
+extern void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo,
+						   MemoryContext destcxt);
+
 /*
  * This macro invokes a function given a filled-in FunctionCallInfoData
  * struct.	The macro result is the returned Datum --- but note that
@@ -341,17 +355,19 @@ extern Datum OidFunctionCall9(Oid functionId, Datum arg1, Datum arg2,
 /*
  * Routines in fmgr.c
  */
-extern Pg_finfo_record *fetch_finfo_record(char *filename, char *funcname);
+extern Pg_finfo_record *fetch_finfo_record(void *filehandle, char *funcname);
 extern Oid	fmgr_internal_function(const char *proname);
 
 /*
  * Routines in dfmgr.c
  */
-extern PGFunction load_external_function(char *filename, char *funcname,
-					   bool signalNotFound);
-extern void load_file(char *filename);
 extern char * Dynamic_library_path;
 
+extern PGFunction load_external_function(char *filename, char *funcname,
+					   bool signalNotFound, void **filehandle);
+extern PGFunction lookup_external_function(void *filehandle, char *funcname);
+extern void load_file(char *filename);
+
 
 /*
  * !!! OLD INTERFACE !!!
diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h
index ef74317fda..9cc7a2ecb4 100644
--- a/src/include/utils/rel.h
+++ b/src/include/utils/rel.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: rel.h,v 1.51 2001/06/27 23:31:40 tgl Exp $
+ * $Id: rel.h,v 1.52 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,8 +23,6 @@
 #include "storage/fd.h"
 #include "storage/relfilenode.h"
 
-/* added to prevent circular dependency.  bjm 1999/11/15 */
-extern char *get_temp_rel_by_physicalname(const char *relname);
 
 /*
  * LockRelId and LockInfo really belong to lmgr.h, but it's more convenient
@@ -115,7 +113,7 @@ typedef struct RelationData
 	bool		rd_isnailed;	/* rel is nailed in cache */
 	bool		rd_indexfound;	/* true if rd_indexlist is valid */
 	bool		rd_uniqueindex; /* true if rel is a UNIQUE index */
-	Form_pg_am	rd_am;			/* AM tuple */
+	Form_pg_am	rd_am;			/* AM tuple (if an index) */
 	Form_pg_class rd_rel;		/* RELATION tuple */
 	Oid			rd_id;			/* relation's object id */
 	List	   *rd_indexlist;	/* list of OIDs of indexes on relation */
@@ -123,10 +121,16 @@ typedef struct RelationData
 	TupleDesc	rd_att;			/* tuple descriptor */
 	RuleLock   *rd_rules;		/* rewrite rules */
 	MemoryContext rd_rulescxt;	/* private memory cxt for rd_rules, if any */
-	IndexStrategy rd_istrat;	/* info needed if rel is an index */
-	RegProcedure *rd_support;
 	TriggerDesc *trigdesc;		/* Trigger info, or NULL if rel has none */
 
+	/* index access support info (used only for an index relation) */
+	MemoryContext rd_indexcxt;	/* private memory cxt for this stuff */
+	IndexStrategy rd_istrat;	/* operator strategy map */
+	RegProcedure *rd_support;	/* OIDs of support procedures */
+	struct FmgrInfo *rd_supportinfo; /* lookup info for support procedures */
+	/* "struct FmgrInfo" avoids need to include fmgr.h here */
+
+	/* statistics collection area */
 	PgStat_Info	pgstat_info;
 } RelationData;
 
@@ -228,13 +232,6 @@ typedef Relation *RelationPtr;
  */
 #define RelationGetIndexStrategy(relation) ((relation)->rd_istrat)
 
-/*
- * Routines in utils/cache/rel.c
- */
-extern void RelationSetIndexSupport(Relation relation,
-						IndexStrategy strategy,
-						RegProcedure *support);
-
 /*
  * Handle temp relations
  */
@@ -279,5 +276,7 @@ extern void RelationSetIndexSupport(Relation relation,
 		RelationGetPhysicalRelationName(relation) \
 )
 
+/* added to prevent circular dependency.  bjm 1999/11/15 */
+extern char *get_temp_rel_by_physicalname(const char *relname);
 
 #endif	 /* REL_H */
diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h
index 160ee0f47c..861185cea9 100644
--- a/src/include/utils/relcache.h
+++ b/src/include/utils/relcache.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: relcache.h,v 1.25 2001/06/29 21:08:25 tgl Exp $
+ * $Id: relcache.h,v 1.26 2001/10/06 23:21:44 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,8 @@ extern void RelationClose(Relation relation);
  */
 extern List *RelationGetIndexList(Relation relation);
 
+extern void RelationInitIndexAccessInfo(Relation relation);
+
 /*
  * Routines for backend startup
  */
@@ -61,6 +63,7 @@ extern void RelationPurgeLocalRelation(bool xactComitted);
 extern void RelationCacheAbort(void);
 
 
+/* XLOG support */
 extern void CreateDummyCaches(void);
 extern void DestroyDummyCaches(void);
 
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index cb733d7970..b59486860e 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -33,7 +33,7 @@
  *	  ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.22 2001/06/18 21:40:06 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plperl/plperl.c,v 1.23 2001/10/06 23:21:44 tgl Exp $
  *
  **********************************************************************/
 
@@ -171,18 +171,14 @@ static void plperl_set_tuple_values(Tcl_Interp *interp, char *arrayname,
  * data structures such as fmgr info records therefore must live forever
  * as well.  A better implementation would store all this stuff in a per-
  * function memory context that could be reclaimed at need.  In the meantime,
- * fmgr_info must be called in TopMemoryContext so that whatever it might
- * allocate, and whatever the eventual function might allocate using fn_mcxt,
- * will live forever too.
+ * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
+ * it might allocate, and whatever the eventual function might allocate using
+ * fn_mcxt, will live forever too.
  */
 static void
 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 {
-	MemoryContext	oldcontext;
-
-	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	fmgr_info(functionId, finfo);
-	MemoryContextSwitchTo(oldcontext);
+	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
 }
 
 /**********************************************************************
diff --git a/src/pl/plpgsql/src/pl_comp.c b/src/pl/plpgsql/src/pl_comp.c
index 2ab6632e33..5c7e12ad19 100644
--- a/src/pl/plpgsql/src/pl_comp.c
+++ b/src/pl/plpgsql/src/pl_comp.c
@@ -3,7 +3,7 @@
  *			  procedural language
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.33 2001/07/12 17:42:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/plpgsql/src/pl_comp.c,v 1.34 2001/10/06 23:21:44 tgl Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -92,18 +92,14 @@ PLpgSQL_function *plpgsql_curr_compile;
  * data structures such as fmgr info records therefore must live forever
  * as well.  A better implementation would store all this stuff in a per-
  * function memory context that could be reclaimed at need.  In the meantime,
- * fmgr_info must be called in TopMemoryContext so that whatever it might
- * allocate, and whatever the eventual function might allocate using fn_mcxt,
- * will live forever too.
+ * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
+ * it might allocate, and whatever the eventual function might allocate using
+ * fn_mcxt, will live forever too.
  */
 static void
 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 {
-	MemoryContext	oldcontext;
-
-	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	fmgr_info(functionId, finfo);
-	MemoryContextSwitchTo(oldcontext);
+	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
 }
 
 
diff --git a/src/pl/plpython/plpython.c b/src/pl/plpython/plpython.c
index cd3486fa6d..8dcfb1c970 100644
--- a/src/pl/plpython/plpython.c
+++ b/src/pl/plpython/plpython.c
@@ -29,7 +29,7 @@
  * MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.7 2001/10/04 15:45:49 momjian Exp $
+ *	$Header: /cvsroot/pgsql/src/pl/plpython/plpython.c,v 1.8 2001/10/06 23:21:45 tgl Exp $
  *
  *********************************************************************
  */
@@ -308,18 +308,14 @@ volatile int func_leave_calls = 0;
  * data structures such as fmgr info records therefore must live forever
  * as well.  A better implementation would store all this stuff in a per-
  * function memory context that could be reclaimed at need.  In the meantime,
- * fmgr_info must be called in TopMemoryContext so that whatever it might
- * allocate, and whatever the eventual function might allocate using fn_mcxt,
- * will live forever too.
+ * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
+ * it might allocate, and whatever the eventual function might allocate using
+ * fn_mcxt, will live forever too.
  */
 static void
 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 {
-	MemoryContext	oldcontext;
-
-	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	fmgr_info(functionId, finfo);
-	MemoryContextSwitchTo(oldcontext);
+	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
 }
 
 
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 29d6559821..38d7d43450 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -31,7 +31,7 @@
  *	  ENHANCEMENTS, OR MODIFICATIONS.
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.42 2001/10/04 15:48:37 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/pl/tcl/pltcl.c,v 1.43 2001/10/06 23:21:45 tgl Exp $
  *
  **********************************************************************/
 
@@ -187,18 +187,14 @@ static int pltcl_SPI_lastoid(ClientData cdata, Tcl_Interp *interp,
  * data structures such as fmgr info records therefore must live forever
  * as well.  A better implementation would store all this stuff in a per-
  * function memory context that could be reclaimed at need.  In the meantime,
- * fmgr_info must be called in TopMemoryContext so that whatever it might
- * allocate, and whatever the eventual function might allocate using fn_mcxt,
- * will live forever too.
+ * fmgr_info_cxt must be called specifying TopMemoryContext so that whatever
+ * it might allocate, and whatever the eventual function might allocate using
+ * fn_mcxt, will live forever too.
  */
 static void
 perm_fmgr_info(Oid functionId, FmgrInfo *finfo)
 {
-	MemoryContext	oldcontext;
-
-	oldcontext = MemoryContextSwitchTo(TopMemoryContext);
-	fmgr_info(functionId, finfo);
-	MemoryContextSwitchTo(oldcontext);
+	fmgr_info_cxt(functionId, finfo, TopMemoryContext);
 }
 
 /**********************************************************************