diff --git a/src/backend/access/gist/gistscan.c b/src/backend/access/gist/gistscan.c
index 9c1c92a880aa4e28bf329d73a2a7efe9474ed12a..8a23b9b115cd5cb4f506c87a7a660360a27bd398 100644
--- a/src/backend/access/gist/gistscan.c
+++ b/src/backend/access/gist/gistscan.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.43 2002/06/20 20:29:24 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/gist/gistscan.c,v 1.44 2003/03/23 23:01:02 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -78,28 +78,14 @@ gistrescan(PG_FUNCTION_ARGS)
 	ItemPointerSetInvalid(&s->currentItemData);
 	ItemPointerSetInvalid(&s->currentMarkData);
 
-	if (s->numberOfKeys > 0)
-	{
-		memmove(s->keyData,
-				key,
-				s->numberOfKeys * sizeof(ScanKeyData));
-	}
-
 	p = (GISTScanOpaque) s->opaque;
 	if (p != (GISTScanOpaque) NULL)
 	{
+		/* rescan an existing indexscan --- reset state */
 		gistfreestack(p->s_stack);
 		gistfreestack(p->s_markstk);
 		p->s_stack = p->s_markstk = (GISTSTACK *) NULL;
 		p->s_flags = 0x0;
-		for (i = 0; i < s->numberOfKeys; i++)
-		{
-			s->keyData[i].sk_procedure
-				= RelationGetGISTStrategy(s->indexRelation,
-										  s->keyData[i].sk_attno,
-										  s->keyData[i].sk_procedure);
-			s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
-		}
 	}
 	else
 	{
@@ -110,22 +96,28 @@ gistrescan(PG_FUNCTION_ARGS)
 		s->opaque = p;
 		p->giststate = (GISTSTATE *) palloc(sizeof(GISTSTATE));
 		initGISTstate(p->giststate, s->indexRelation);
-		if (s->numberOfKeys > 0)
-
-			/*
-			 * * Play games here with the scan key to use the Consistent *
-			 * function for all comparisons: * 1) the sk_procedure field
-			 * will now be used to hold the *	 strategy number * 2) the
-			 * sk_func field will point to the Consistent function
-			 */
-			for (i = 0; i < s->numberOfKeys; i++)
-			{
-				s->keyData[i].sk_procedure =
-					RelationGetGISTStrategy(s->indexRelation,
-											s->keyData[i].sk_attno,
-											s->keyData[i].sk_procedure);
-				s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
-			}
+	}
+
+	/* Update scan key, if a new one is given */
+	if (key && s->numberOfKeys > 0)
+	{
+		memmove(s->keyData,
+				key,
+				s->numberOfKeys * sizeof(ScanKeyData));
+		/*
+		 * Play games here with the scan key to use the Consistent
+		 * function for all comparisons: 1) the sk_procedure field
+		 * will now be used to hold the strategy number 2) the
+		 * sk_func field will point to the Consistent function
+		 */
+		for (i = 0; i < s->numberOfKeys; i++)
+		{
+			s->keyData[i].sk_procedure =
+				RelationGetGISTStrategy(s->indexRelation,
+										s->keyData[i].sk_attno,
+										s->keyData[i].sk_procedure);
+			s->keyData[i].sk_func = p->giststate->consistentFn[s->keyData[i].sk_attno - 1];
+		}
 	}
 
 	PG_RETURN_VOID();
diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c
index 705041f7d274e8e6ae4e6708d252b81763ae70d6..f3534d2e174144d847160ff95076f37516436ac9 100644
--- a/src/backend/access/hash/hash.c
+++ b/src/backend/access/hash/hash.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.62 2003/02/24 00:57:17 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/hash/hash.c,v 1.63 2003/03/23 23:01:03 tgl Exp $
  *
  * NOTES
  *	  This file contains only the public interface routines.
@@ -302,10 +302,8 @@ hashrescan(PG_FUNCTION_ARGS)
 {
 	IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0);
 	ScanKey		scankey = (ScanKey) PG_GETARG_POINTER(1);
+	HashScanOpaque so = (HashScanOpaque) scan->opaque;
 	ItemPointer iptr;
-	HashScanOpaque so;
-
-	so = (HashScanOpaque) scan->opaque;
 
 	/* we hold a read lock on the current page in the scan */
 	if (ItemPointerIsValid(iptr = &(scan->currentItemData)))
@@ -321,8 +319,8 @@ hashrescan(PG_FUNCTION_ARGS)
 		ItemPointerSetInvalid(iptr);
 	}
 
-	/* reset the scan key */
-	if (scan->numberOfKeys > 0)
+	/* Update scan key, if a new one is given */
+	if (scankey && scan->numberOfKeys > 0)
 	{
 		memmove(scan->keyData,
 				scankey,
diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c
index d045bafc1c86eaf2a1c235fd7fcb877e30673e87..2f0c6aac529f585af8a649903f4e18e04b0aeb72 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.64 2003/02/22 00:45:03 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/index/indexam.c,v 1.65 2003/03/23 23:01:03 tgl Exp $
  *
  * INTERFACE ROUTINES
  *		index_open		- open an index relation by relation OID
@@ -294,8 +294,12 @@ index_beginscan(Relation heapRelation,
  *		index_rescan  - (re)start a scan of an index
  *
  * The caller may specify a new set of scankeys (but the number of keys
- * cannot change).	Note that this is also called when first starting
- * an indexscan; see RelationGetIndexScan.
+ * cannot change).  To restart the scan without changing keys, pass NULL
+ * for the key array.
+ *
+ * Note that this is also called when first starting an indexscan;
+ * see RelationGetIndexScan.  Keys *must* be passed in that case,
+ * unless scan->numberOfKeys is zero.
  * ----------------
  */
 void
diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c
index b1722244e6d9e7d78f0b6ef961adf0cf5e79f53d..a35901b47c6bfefa37fa9df63f1a6bec04bb122f 100644
--- a/src/backend/access/nbtree/nbtree.c
+++ b/src/backend/access/nbtree/nbtree.c
@@ -12,7 +12,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.101 2003/03/04 21:51:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtree.c,v 1.102 2003/03/23 23:01:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -396,6 +396,7 @@ btrescan(PG_FUNCTION_ARGS)
 			so->keyData = (ScanKey) palloc(scan->numberOfKeys * sizeof(ScanKeyData));
 		else
 			so->keyData = (ScanKey) NULL;
+		so->numberOfKeys = scan->numberOfKeys;
 		scan->opaque = so;
 	}
 
@@ -420,12 +421,12 @@ btrescan(PG_FUNCTION_ARGS)
 	 * Reset the scan keys. Note that keys ordering stuff moved to
 	 * _bt_first.	   - vadim 05/05/97
 	 */
-	so->numberOfKeys = scan->numberOfKeys;
-	if (scan->numberOfKeys > 0)
+	if (scankey && scan->numberOfKeys > 0)
 	{
 		memmove(scan->keyData,
 				scankey,
 				scan->numberOfKeys * sizeof(ScanKeyData));
+		so->numberOfKeys = scan->numberOfKeys;
 		memmove(so->keyData,
 				scankey,
 				so->numberOfKeys * sizeof(ScanKeyData));
diff --git a/src/backend/access/rtree/rtscan.c b/src/backend/access/rtree/rtscan.c
index 52aedeae2b8882ed5ba05c91d0143f9a53c813b4..a0b9883cfe80db31b290292bbf8d55928edec9e7 100644
--- a/src/backend/access/rtree/rtscan.c
+++ b/src/backend/access/rtree/rtscan.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.42 2002/06/20 20:29:25 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/rtree/Attic/rtscan.c,v 1.43 2003/03/23 23:01:03 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -80,22 +80,14 @@ rtrescan(PG_FUNCTION_ARGS)
 	ItemPointerSetInvalid(&s->currentItemData);
 	ItemPointerSetInvalid(&s->currentMarkData);
 
-	if (s->numberOfKeys > 0)
-	{
-		memmove(s->keyData,
-				key,
-				s->numberOfKeys * sizeof(ScanKeyData));
-	}
-
 	p = (RTreeScanOpaque) s->opaque;
 	if (p != (RTreeScanOpaque) NULL)
 	{
+		/* rescan an existing indexscan --- reset state */
 		freestack(p->s_stack);
 		freestack(p->s_markstk);
 		p->s_stack = p->s_markstk = (RTSTACK *) NULL;
 		p->s_flags = 0x0;
-		for (i = 0; i < s->numberOfKeys; i++)
-			p->s_internalKey[i].sk_argument = s->keyData[i].sk_argument;
 	}
 	else
 	{
@@ -106,28 +98,32 @@ rtrescan(PG_FUNCTION_ARGS)
 		p->s_flags = 0x0;
 		s->opaque = p;
 		if (s->numberOfKeys > 0)
-		{
 			p->s_internalKey = (ScanKey) palloc(sizeof(ScanKeyData) * s->numberOfKeys);
+	}
 
-			/*
-			 * Scans on internal pages use different operators than they
-			 * do on leaf pages.  For example, if the user wants all boxes
-			 * that exactly match (x1,y1,x2,y2), then on internal pages we
-			 * need to find all boxes that contain (x1,y1,x2,y2).
-			 */
+	/* Update scan key, if a new one is given */
+	if (key && s->numberOfKeys > 0)
+	{
+		memmove(s->keyData,
+				key,
+				s->numberOfKeys * sizeof(ScanKeyData));
 
-			for (i = 0; i < s->numberOfKeys; i++)
-			{
-				p->s_internalKey[i].sk_argument = s->keyData[i].sk_argument;
-				internal_proc = RTMapOperator(s->indexRelation,
-											  s->keyData[i].sk_attno,
-											  s->keyData[i].sk_procedure);
-				ScanKeyEntryInitialize(&(p->s_internalKey[i]),
-									   s->keyData[i].sk_flags,
-									   s->keyData[i].sk_attno,
-									   internal_proc,
-									   s->keyData[i].sk_argument);
-			}
+		/*
+		 * Scans on internal pages use different operators than they
+		 * do on leaf pages.  For example, if the user wants all boxes
+		 * that exactly match (x1,y1,x2,y2), then on internal pages we
+		 * need to find all boxes that contain (x1,y1,x2,y2).
+		 */
+		for (i = 0; i < s->numberOfKeys; i++)
+		{
+			internal_proc = RTMapOperator(s->indexRelation,
+										  s->keyData[i].sk_attno,
+										  s->keyData[i].sk_procedure);
+			ScanKeyEntryInitialize(&(p->s_internalKey[i]),
+								   s->keyData[i].sk_flags,
+								   s->keyData[i].sk_attno,
+								   internal_proc,
+								   s->keyData[i].sk_argument);
 		}
 	}