diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c
index 593a5453bc5e47033a4fa3533df67cf6508fc3c0..1ea080abd721638aad7da2cbbe2db0c59aff0107 100644
--- a/src/backend/access/nbtree/nbtsearch.c
+++ b/src/backend/access/nbtree/nbtsearch.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.42 1999/03/28 20:31:58 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.43 1999/04/13 17:18:28 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -733,7 +733,8 @@ _bt_next(IndexScanDesc scan, ScanDirection dir)
 			return res;
 		}
 
-	} while (keysok >= so->numberOfFirstKeys);
+	} while (keysok >= so->numberOfFirstKeys || 
+		 (keysok == -1 && ScanDirectionIsBackward(dir)));
 
 	ItemPointerSetInvalid(current);
 	so->btso_curbuf = InvalidBuffer;
@@ -775,6 +776,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	BTScanOpaque so;
 	ScanKeyData skdata;
 	Size		keysok;
+	int		i;
+	int		nKeyIndex = -1;
 
 	rel = scan->relation;
 	so = (BTScanOpaque) scan->opaque;
@@ -790,11 +793,34 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 	{
 		_bt_orderkeys(rel, so);
 
-		strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
+		if (ScanDirectionIsBackward(dir))
+		{
+			for (i=0; i<so->numberOfKeys; i++)
+			{
+				if (so->keyData[i].sk_attno != 1)
+					break;
+				strat = _bt_getstrat(rel, so->keyData[i].sk_attno, 
+					so->keyData[i].sk_procedure);
+				if (strat == BTLessStrategyNumber ||
+				    strat == BTLessEqualStrategyNumber||
+				    strat == BTEqualStrategyNumber)
+				{
+					nKeyIndex = i;
+					break;
+				}
+			}
+		}
+		else 
+		{
+			strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
 
-		/* NOTE: it assumes ForwardScanDirection */
-		if (strat == BTLessStrategyNumber ||
-			strat == BTLessEqualStrategyNumber)
+			if (strat == BTLessStrategyNumber ||
+			    strat == BTLessEqualStrategyNumber)
+				;
+			else
+				nKeyIndex = 0;
+		}
+		if (nKeyIndex < 0)
 			scan->scanFromEnd = true;
 	}
 	else
@@ -823,8 +849,8 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 		return (RetrieveIndexResult) NULL;
 	}
 	proc = index_getprocid(rel, 1, BTORDER_PROC);
-	ScanKeyEntryInitialize(&skdata, so->keyData[0].sk_flags, 1, proc,
-						   so->keyData[0].sk_argument);
+	ScanKeyEntryInitialize(&skdata, so->keyData[nKeyIndex].sk_flags,
+				1, proc, so->keyData[nKeyIndex].sk_argument);
 
 	stack = _bt_search(rel, 1, &skdata, &buf);
 	_bt_freestack(stack);
@@ -897,7 +923,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 
 	/* it's yet other place to add some code latter for is(not)null */
 
-	strat = _bt_getstrat(rel, 1, so->keyData[0].sk_procedure);
+	strat = _bt_getstrat(rel, 1, so->keyData[nKeyIndex].sk_procedure);
 
 	switch (strat)
 	{
@@ -914,9 +940,6 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 					result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
 				} while (result <= 0);
 
-				/* if this is true, the key we just looked at is gone */
-				if (result > 0)
-					_bt_twostep(scan, &buf, ForwardScanDirection);
 			}
 			break;
 
@@ -946,6 +969,21 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 				ItemPointerSetInvalid(&(scan->currentItemData));
 				return (RetrieveIndexResult) NULL;
 			}
+			else if (ScanDirectionIsBackward(dir))
+			{
+				do
+				{
+					if (!_bt_twostep(scan, &buf, ForwardScanDirection))
+						break;
+
+					offnum = ItemPointerGetOffsetNumber(current);
+					page = BufferGetPage(buf);
+					result = _bt_compare(rel, itupdesc, page, 1, &skdata, offnum);
+				} while (result == 0);
+
+				if (result < 0)
+					_bt_twostep(scan, &buf, BackwardScanDirection);
+			}
 			break;
 
 		case BTGreaterEqualStrategyNumber:
@@ -1026,6 +1064,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
 		so->btso_curbuf = buf;
 		return _bt_next(scan, dir);
 	}
+	else if (keysok == -1 && ScanDirectionIsBackward(dir))
+	{
+		so->btso_curbuf = buf;
+		return _bt_next(scan, dir);
+	}
 	else
 	{
 		ItemPointerSetInvalid(current);
@@ -1495,6 +1538,11 @@ _bt_endpoint(IndexScanDesc scan, ScanDirection dir)
 		so->btso_curbuf = buf;
 		return _bt_next(scan, dir);
 	}
+	else if (keysok == -1 && ScanDirectionIsBackward(dir))
+	{
+		so->btso_curbuf = buf;
+		return _bt_next(scan, dir);
+	}
 	else
 	{
 		ItemPointerSetInvalid(current);
diff --git a/src/backend/access/nbtree/nbtutils.c b/src/backend/access/nbtree/nbtutils.c
index 193a2f7e714e544c17c9101d92b034753060d08f..39a722bb074f129986eb8e1fe7396b536470c417 100644
--- a/src/backend/access/nbtree/nbtutils.c
+++ b/src/backend/access/nbtree/nbtutils.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.25 1999/02/13 23:14:37 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtutils.c,v 1.26 1999/04/13 17:18:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -367,8 +367,14 @@ _bt_checkkeys(IndexScanDesc scan, IndexTuple tuple, Size *keysok)
 							  &isNull);
 
 		/* btree doesn't support 'A is null' clauses, yet */
-		if (isNull || key[0].sk_flags & SK_ISNULL)
+		if (key[0].sk_flags & SK_ISNULL)
 			return false;
+		if (isNull)
+		{
+			if (*keysok < so->numberOfFirstKeys)
+				*keysok = -1;
+			return false;
+		}
 
 		if (key[0].sk_flags & SK_COMMUTE)
 		{
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index cdf13c5e19e0a10286fa3a7162aa27737e5334f8..16bb4f23b410158450986460d021bf9a2e0d1cd0 100644
--- a/src/backend/executor/nodeIndexscan.c
+++ b/src/backend/executor/nodeIndexscan.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.33 1999/02/21 03:48:40 scrappy Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.34 1999/04/13 17:18:29 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -96,6 +96,8 @@ IndexNext(IndexScan *node)
 	Buffer		buffer = InvalidBuffer;
 	int			numIndices;
 
+ 	bool		bBackward;
+ 	int		indexNumber;
 	/* ----------------
 	 *	extract necessary information from index scan node
 	 * ----------------
@@ -151,8 +153,26 @@ IndexNext(IndexScan *node)
 	 *	appropriate heap tuple.. else return NULL.
 	 * ----------------
 	 */
-	while (indexstate->iss_IndexPtr < numIndices)
-	{
+ 	bBackward = ScanDirectionIsBackward(direction);
+ 	if (bBackward)
+  	{
+ 		indexNumber = numIndices - indexstate->iss_IndexPtr - 1;
+ 		if (indexNumber < 0)
+ 		{
+ 			indexNumber = 0;
+ 			indexstate->iss_IndexPtr = numIndices - 1;
+ 		}
+ 	}
+ 	else
+ 	{
+ 		if ((indexNumber = indexstate->iss_IndexPtr) < 0)
+ 		{
+ 			indexNumber = 0;
+ 			indexstate->iss_IndexPtr = 0;
+ 		}
+ 	}
+ 	while (indexNumber < numIndices)
+ 	{
 		scandesc = scanDescs[indexstate->iss_IndexPtr];
 		while ((result = index_getnext(scandesc, direction)) != NULL)
 		{
@@ -204,8 +224,14 @@ IndexNext(IndexScan *node)
 			if (BufferIsValid(buffer))
 				ReleaseBuffer(buffer);
 		}
-		if (indexstate->iss_IndexPtr < numIndices)
-			indexstate->iss_IndexPtr++;
+ 		if (indexNumber < numIndices)
+ 		{
+ 			indexNumber++;
+ 			if (bBackward)
+ 				indexstate->iss_IndexPtr--;
+ 			else
+ 				indexstate->iss_IndexPtr++;
+ 		}
 	}
 	/* ----------------
 	 *	if we get here it means the index scan failed so we
@@ -294,7 +320,7 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
 	indxqual = node->indxqual;
 	numScanKeys = indexstate->iss_NumScanKeys;
-	indexstate->iss_IndexPtr = 0;
+	indexstate->iss_IndexPtr = -1;
 
 	/* If this is re-scanning of PlanQual ... */
 	if (estate->es_evTuple != NULL && 
@@ -611,7 +637,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	  */
 	indexstate = makeNode(IndexScanState);
 	indexstate->iss_NumIndices = 0;
-	indexstate->iss_IndexPtr = 0;
+	indexstate->iss_IndexPtr = -1;
 	indexstate->iss_ScanKeys = NULL;
 	indexstate->iss_NumScanKeys = NULL;
 	indexstate->iss_RuntimeKeyInfo = NULL;
@@ -635,7 +661,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	indxid = node->indxid;
 	indxqual = node->indxqual;
 	numIndices = length(indxid);
-	indexPtr = 0;
+	indexPtr = -1;
 
 	CXT1_printf("ExecInitIndexScan: context is %d\n", CurrentMemoryContext);