diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c
index c1971133ce13e64dd385fdfe0b5d465da8e2bdc9..5eb0d78faccbdd852b4e6d5ea65214d485e63ba9 100644
--- a/src/backend/access/index/genam.c
+++ b/src/backend/access/index/genam.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.21 1999/07/17 20:16:40 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/genam.c,v 1.22 1999/12/30 05:04:50 tgl Exp $
  *
  * NOTES
  *	  many of the old access method routines have been turned into
@@ -39,7 +39,7 @@
  * All other states cannot occur.
  *
  * Note:
- *It would be possible to cache the status of the previous and
+ *		It would be possible to cache the status of the previous and
  *		next item pointer using the flags.
  * ----------------------------------------------------------------
  */
@@ -55,9 +55,19 @@
  *		We don't know how the various AMs do locking, however, so we don't
  *		do anything about that here.
  *
- *		The intent is that an AM implementor will define a front-end routine
- *		that calls this one, to fill in the scan, and then does whatever kind
- *		of locking he wants.
+ *		The intent is that an AM implementor will define a beginscan routine
+ *		that calls RelationGetIndexScan, to fill in the scan, and then does
+ *		whatever kind of locking he wants.
+ *
+ *		At the end of a scan, the AM's endscan routine undoes the locking,
+ *		but does *not* call IndexScanEnd --- the higher-level index_endscan
+ *		routine does that.  (We can't do it in the AM because index_endscan
+ *		still needs to touch the IndexScanDesc after calling the AM.)
+ *
+ *		Because of this, the AM does not have a choice whether to call
+ *		RelationGetIndexScan or not; its beginscan routine must return an
+ *		object made by RelationGetIndexScan.  This is kinda ugly but not
+ *		worth cleaning up now.
  * ----------------------------------------------------------------
  */
 
@@ -72,16 +82,11 @@
  *				relation -- index relation for scan.
  *				scanFromEnd -- if true, begin scan at one of the index's
  *							   endpoints.
- *				numberOfKeys -- count of scan keys (more than one won't
- *								necessarily do anything useful, yet).
+ *				numberOfKeys -- count of scan keys.
  *				key -- the ScanKey for the starting position of the scan.
  *
  *		Returns:
  *				An initialized IndexScanDesc.
- *
- *		Side Effects:
- *				Bumps the ref count on the relation to keep it in the cache.
- *
  * ----------------
  */
 IndexScanDesc
@@ -118,6 +123,30 @@ RelationGetIndexScan(Relation relation,
 	return scan;
 }
 
+/* ----------------
+ *	IndexScanEnd -- End an index scan.
+ *
+ *		This routine just releases the storage acquired by
+ *		RelationGetIndexScan().  Any AM-level resources are
+ *		assumed to already have been released by the AM's
+ *		endscan routine.
+ *
+ *	Returns:
+ *		None.
+ * ----------------
+ */
+void
+IndexScanEnd(IndexScanDesc scan)
+{
+	if (!IndexScanIsValid(scan))
+		elog(ERROR, "IndexScanEnd: invalid scan");
+
+	if (scan->keyData != NULL)
+		pfree(scan->keyData);
+
+	pfree(scan);
+}
+
 #ifdef NOT_USED
 /* ----------------
  *	IndexScanRestart -- Restart an index scan.
@@ -159,29 +188,6 @@ IndexScanRestart(IndexScanDesc scan,
 				scan->numberOfKeys * sizeof(ScanKeyData));
 }
 
-/* ----------------
- *	IndexScanEnd -- End and index scan.
- *
- *		This routine is not used by any existing access method, but is
- *		suitable for use if you don't want to do sophisticated locking.
- *
- *	Returns:
- *		None.
- *
- *	Side Effects:
- *		None.
- * ----------------
- */
-void
-IndexScanEnd(IndexScanDesc scan)
-{
-	if (!IndexScanIsValid(scan))
-		elog(ERROR, "IndexScanEnd: invalid scan");
-
-	pfree(scan);
-}
-
-
 /* ----------------
  *	IndexScanMarkPosition -- Mark current position in a scan.
  *
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index 1a7ee4d3771dfc3d8b386b523f0729397a93ce63..dc08d10bc313df0bd28564c6bb4b02bb7c7fded6 100644
--- a/src/backend/access/index/indexam.c
+++ b/src/backend/access/index/indexam.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.37 1999/11/07 23:07:54 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.38 1999/12/30 05:04:50 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relationId
@@ -298,6 +298,9 @@ index_endscan(IndexScanDesc scan)
 	UnlockRelation(scan->relation, AccessShareLock);
 
 	RelationDecrementReferenceCount(scan->relation);
+
+	/* Release the scan data structure itself */
+	IndexScanEnd(scan);
 }
 
 /* ----------------
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 7918fbd6a7359ba482646505d39f74224cea0d6d..d7baec4eaeb194322b8512d5bfaa422ecf5fa713 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.54 1999/12/16 22:19:39 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.55 1999/12/30 05:04:55 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -266,7 +266,7 @@ CatalogIndexFetchTuple(Relation heapRelation,
 	}
 
 	index_endscan(sd);
-	pfree(sd);
+
 	return result;
 }
 
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 2615ea43ccea658497c79f1f0895ffbb885638d0..40159db834f881df003c2cb59d5f69296dce8891 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -513,7 +513,6 @@ RelationBuildTriggers(Relation relation)
 			 NAMEDATALEN, RelationGetRelationName(relation));
 
 	index_endscan(sd);
-	pfree(sd);
 	index_close(irel);
 	heap_close(tgrel, AccessShareLock);
 
@@ -1562,7 +1561,6 @@ DeferredTriggerSetState(ConstraintsSetStmt *stmt)
 			elog(ERROR, "Constraint '%s' does not exist", (char *)lfirst(l));
 
 		index_endscan(sd);
-
 	}
 	index_close(irel);
 	heap_close(tgrel, AccessShareLock);
diff --git a/src/backend/storage/large_object/inv_api.c b/src/backend/storage/large_object/inv_api.c
index f066d418e76da16a114538690c79ebb963df7ba5..5a2862946dc0885f38b4872d50396cfd797de1d8 100644
--- a/src/backend/storage/large_object/inv_api.c
+++ b/src/backend/storage/large_object/inv_api.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.63 1999/12/16 22:19:51 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/large_object/inv_api.c,v 1.64 1999/12/30 05:05:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -258,7 +258,6 @@ inv_close(LargeObjectDesc *obj_desc)
 	if (obj_desc->iscan != (IndexScanDesc) NULL)
 	{
 		index_endscan(obj_desc->iscan);
-		pfree(obj_desc->iscan);
 		obj_desc->iscan = NULL;
 	}
 
@@ -583,7 +582,6 @@ inv_cleanindex(LargeObjectDesc *obj_desc)
 		return;
 
 	index_endscan(obj_desc->iscan);
-	pfree(obj_desc->iscan);
 	obj_desc->iscan = (IndexScanDesc) NULL;
 
 	ItemPointerSetInvalid(&(obj_desc->htid));
@@ -1255,7 +1253,6 @@ _inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)
 		if (res == (RetrieveIndexResult) NULL)
 		{
 			index_endscan(iscan);
-			pfree(iscan);
 			return 0;
 		}
 
@@ -1271,7 +1268,6 @@ _inv_getsize(Relation hreln, TupleDesc hdesc, Relation ireln)
 
 	/* don't need the index scan anymore */
 	index_endscan(iscan);
-	pfree(iscan);
 
 	/* get olastbyte attribute */
 	d = heap_getattr(&tuple, 1, hdesc, &isNull);
diff --git a/src/backend/utils/adt/regproc.c b/src/backend/utils/adt/regproc.c
index e346639994f65b0a8384e4fc20801136dec765aa..dffedd5f7f194e0f574485bdaac67b6e9a3107e9 100644
--- a/src/backend/utils/adt/regproc.c
+++ b/src/backend/utils/adt/regproc.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.46 1999/12/16 22:19:52 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/regproc.c,v 1.47 1999/12/30 05:05:07 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -102,7 +102,6 @@ regprocin(char *pro_name_or_oid)
 			}
 
 			index_endscan(sd);
-			pfree(sd);
 			index_close(idesc);
 			heap_close(hdesc, AccessShareLock);
 
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index ffdc3cfa9dc0895d458c2353389292ec20b763ce..7eec36ddb0f2bd77d18ec388c75c688a978f5dab 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.83 1999/12/28 13:40:49 wieck Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.84 1999/12/30 05:05:11 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -378,31 +378,27 @@ static Relation
 AllocateRelationDesc(Relation relation, u_int natts,
 					 Form_pg_class relp)
 {
-	Size		len;
 	Form_pg_class relationForm;
 
 	/* ----------------
 	 *	allocate space for the relation tuple form
 	 * ----------------
 	 */
-	relationForm = (Form_pg_class)
-		palloc((Size) (sizeof(FormData_pg_class)));
+	relationForm = (Form_pg_class) palloc(sizeof(FormData_pg_class));
 
-	memmove((char *) relationForm, (char *) relp, CLASS_TUPLE_SIZE);
+	memcpy((char *) relationForm, (char *) relp, CLASS_TUPLE_SIZE);
 
 	/* ----------------
 	 *	allocate space for new relation descriptor, if needed
 	 */
-	len = sizeof(RelationData);
-
 	if (relation == NULL)
-		relation = (Relation) palloc(len);
+		relation = (Relation) palloc(sizeof(RelationData));
 
 	/* ----------------
 	 *	clear new reldesc
 	 * ----------------
 	 */
-	MemSet((char *) relation, 0, len);
+	MemSet((char *) relation, 0, sizeof(RelationData));
 
 	/* make sure relation is marked as having no open file yet */
 	relation->rd_fd = -1;
@@ -745,14 +741,10 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	u_int		natts;
 	Oid			relid;
 	Oid			relam;
+	HeapTuple	pg_class_tuple;
 	Form_pg_class relp;
-
 	MemoryContext oldcxt;
 
-	HeapTuple	pg_class_tuple;
-
-	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
-
 	/* ----------------
 	 *	find the tuple in pg_class corresponding to the given relation id
 	 * ----------------
@@ -764,11 +756,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	 * ----------------
 	 */
 	if (!HeapTupleIsValid(pg_class_tuple))
-	{
-		MemoryContextSwitchTo(oldcxt);
-
 		return NULL;
-	}
 
 	/* ----------------
 	 *	get information from the pg_class_tuple
@@ -781,8 +769,10 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	/* ----------------
 	 *	allocate storage for the relation descriptor,
 	 *	initialize relation->rd_rel and get the access method id.
+	 *	The storage is allocated in memory context CacheCxt.
 	 * ----------------
 	 */
+	oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt);
 	relation = AllocateRelationDesc(oldrelation, natts, relp);
 	relam = relation->rd_rel->relam;
 
@@ -866,6 +856,8 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	 */
 	RelationCacheInsert(relation);
 
+	MemoryContextSwitchTo(oldcxt);
+
 	/* -------------------
 	 *	free the memory allocated for pg_class_tuple
 	 *	and for lock data pointed to by pg_class_tuple
@@ -873,8 +865,6 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo,
 	 */
 	heap_freetuple(pg_class_tuple);
 
-	MemoryContextSwitchTo(oldcxt);
-
 	return relation;
 }
 
@@ -1764,7 +1754,6 @@ AttrDefaultFetch(Relation relation)
 			 ndef - found, RelationGetRelationName(relation));
 
 	index_endscan(sd);
-	pfree(sd);
 	index_close(irel);
 	heap_close(adrel, AccessShareLock);
 }
@@ -1837,7 +1826,6 @@ RelCheckFetch(Relation relation)
 			 ncheck - found, RelationGetRelationName(relation));
 
 	index_endscan(sd);
-	pfree(sd);
 	index_close(irel);
 	heap_close(rcrel, AccessShareLock);
 }
diff --git a/src/include/access/genam.h b/src/include/access/genam.h
index fb98694b18c33ad2b0928c269bc9331131c597fe..76200f215e2dbf2d8f6390ea679d5805c18be264 100644
--- a/src/include/access/genam.h
+++ b/src/include/access/genam.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: genam.h,v 1.20 1999/07/16 17:07:25 momjian Exp $
+ * $Id: genam.h,v 1.21 1999/12/30 05:05:13 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -47,5 +47,6 @@ extern Datum GetIndexValue(HeapTuple tuple, TupleDesc hTupDesc,
 /* in genam.c */
 extern IndexScanDesc RelationGetIndexScan(Relation relation, bool scanFromEnd,
 					 uint16 numberOfKeys, ScanKey key);
+extern void IndexScanEnd(IndexScanDesc scan);
 
 #endif	 /* GENAM_H */