diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index 31e2791eabebfbe7bc7e333921c6e0f51a1d019b..55a16f53b2f3c4e16f8b066f2042663b4bf214a1 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.33 1998/06/15 19:28:19 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/execQual.c,v 1.34 1998/08/01 22:12:02 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1349,8 +1349,6 @@ ExecQual(List *qual, ExprContext *econtext)
 
 	foreach(clause, qual)
 	{
-	 
-	  
 		result = ExecQualClause((Node *) lfirst(clause), econtext);
 		if (result == true)
 			break;
diff --git a/src/backend/executor/nodeIndexscan.c b/src/backend/executor/nodeIndexscan.c
index 51308d4101409e7114b93887e3e8d7c078ecc418..0f9be0a129d85097b1a451b78c4cc25927c0c7c5 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.19 1998/07/27 19:37:57 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/executor/nodeIndexscan.c,v 1.20 1998/08/01 22:12:04 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -87,7 +87,6 @@ IndexNext(IndexScan *node)
 	IndexScanState *indexstate;
 	ScanDirection	direction;
 	Snapshot		snapshot;
-	int			indexPtr;
 	IndexScanDescPtr scanDescs;
 	IndexScanDesc scandesc;
 	Relation	heapRelation;
@@ -95,7 +94,8 @@ IndexNext(IndexScan *node)
 	HeapTuple	tuple;
 	TupleTableSlot *slot;
 	Buffer		buffer = InvalidBuffer;
-
+	int			numIndices;
+	
 	/* ----------------
 	 *	extract necessary information from index scan node
 	 * ----------------
@@ -105,54 +105,66 @@ IndexNext(IndexScan *node)
 	snapshot = estate->es_snapshot;
 	scanstate = node->scan.scanstate;
 	indexstate = node->indxstate;
-	indexPtr = indexstate->iss_IndexPtr;
 	scanDescs = indexstate->iss_ScanDescs;
-	scandesc = scanDescs[indexPtr];
 	heapRelation = scanstate->css_currentRelation;
-
+	numIndices = indexstate->iss_NumIndices;
 	slot = scanstate->css_ScanTupleSlot;
 
 	/* ----------------
 	 *	ok, now that we have what we need, fetch an index tuple.
-	 * ----------------
-	 */
-
-	/* ----------------
 	 *	if scanning this index succeeded then return the
 	 *	appropriate heap tuple.. else return NULL.
 	 * ----------------
 	 */
-	while ((result = index_getnext(scandesc, direction)) != NULL)
+	while (indexstate->iss_IndexPtr < numIndices)
 	{
-		tuple = heap_fetch(heapRelation, snapshot, 
-							&result->heap_iptr, &buffer);
-		/* be tidy */
-		pfree(result);
-
-		if (tuple != NULL)
-		{
-			/* ----------------
-		 	 *	store the scanned tuple in the scan tuple slot of
-		 	 *	the scan state.  Eventually we will only do this and not
-		 	 *	return a tuple.  Note: we pass 'false' because tuples
-		 	 *	returned by amgetnext are pointers onto disk pages and
-		 	 *	were not created with palloc() and so should not be pfree()'d.
-		 	 * ----------------
-		 	 */
-			ExecStoreTuple(tuple,		/* tuple to store */
-							slot,		/* slot to store in */
-							buffer,		/* buffer associated with tuple  */
-							false);		/* don't pfree */
-	
-			return slot;
-		}
-		else
+		scandesc = scanDescs[indexstate->iss_IndexPtr];
+		while ((result = index_getnext(scandesc, direction)) != NULL)
 		{
+			tuple = heap_fetch(heapRelation, snapshot,
+								&result->heap_iptr, &buffer);
+			/* be tidy */
+			pfree(result);
+
+			if (tuple != NULL)
+			{
+				bool		prev_matches = false;
+				int			prev_index;
+
+				/* ----------------
+			 	 *	store the scanned tuple in the scan tuple slot of
+			 	 *	the scan state.  Eventually we will only do this and not
+			 	 *	return a tuple.  Note: we pass 'false' because tuples
+			 	 *	returned by amgetnext are pointers onto disk pages and
+			 	 *	were not created with palloc() and so should not be pfree()'d.
+			 	 * ----------------
+			 	 */
+				ExecStoreTuple(tuple,		/* tuple to store */
+								slot,		/* slot to store in */
+								buffer,		/* buffer associated with tuple  */
+								false);		/* don't pfree */
+ 
+				for (prev_index = 0; prev_index < indexstate->iss_IndexPtr;
+																prev_index++)
+				{
+					if (ExecQual(nth(prev_index, node->indxqual),
+						scanstate->cstate.cs_ExprContext))
+					{
+						prev_matches = true;
+						break;
+					}
+				}
+				if (!prev_matches)
+					return slot;
+				else
+					ExecClearTuple(slot);
+			}
 			if (BufferIsValid(buffer))
 				ReleaseBuffer(buffer);
 		}
+		if (indexstate->iss_IndexPtr < numIndices)
+			indexstate->iss_IndexPtr++;
 	}
-
 	/* ----------------
 	 *	if we get here it means the index scan failed so we
 	 *	are at the end of the scan..
@@ -218,7 +230,6 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	int			i;
 
 	Pointer    *runtimeKeyInfo;
-	int			indexPtr;
 	int		   *numScanKeys;
 	List	   *indxqual;
 	List	   *qual;
@@ -238,69 +249,62 @@ ExecIndexReScan(IndexScan *node, ExprContext *exprCtxt, Plan *parent)
 	numIndices = indexstate->iss_NumIndices;
 	scanDescs = indexstate->iss_ScanDescs;
 	scanKeys = indexstate->iss_ScanKeys;
-
 	runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+	indxqual = node->indxqual;
+	numScanKeys = indexstate->iss_NumScanKeys;
+	indexstate->iss_IndexPtr = 0;
+	
+	/* it's possible in subselects */
+	if (exprCtxt == NULL)
+		exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
 
-	if (runtimeKeyInfo != NULL)
-	{
-
-		/*
-		 * get the index qualifications and recalculate the appropriate
-		 * values
-		 */
-		indexPtr = indexstate->iss_IndexPtr;
-		indxqual = node->indxqual;
-		qual = nth(indexPtr, indxqual);
-		numScanKeys = indexstate->iss_NumScanKeys;
-		n_keys = numScanKeys[indexPtr];
-		run_keys = (int *) runtimeKeyInfo[indexPtr];
-		scan_keys = (ScanKey) scanKeys[indexPtr];
+	if (exprCtxt != NULL)
+		node->scan.scanstate->cstate.cs_ExprContext->ecxt_outertuple =
+			exprCtxt->ecxt_outertuple;
 		
-		/* it's possible in subselects */
-		if (exprCtxt == NULL)
-			exprCtxt = node->scan.scanstate->cstate.cs_ExprContext;
-		
-		for (j = 0; j < n_keys; j++)
+	/*
+	 * get the index qualifications and recalculate the appropriate
+	 * values
+	 */
+	for (i = 0; i < numIndices; i++)
+	{
+		if (runtimeKeyInfo && runtimeKeyInfo[i] != NULL)
 		{
-
-			/*
-			 * If we have a run-time key, then extract the run-time
-			 * expression and evaluate it with respect to the current
-			 * outer tuple.  We then stick the result into the scan key.
-			 */
-			if (run_keys[j] != NO_OP)
+			qual = nth(i, indxqual);
+			n_keys = numScanKeys[i];
+			run_keys = (int *) runtimeKeyInfo[i];
+			scan_keys = (ScanKey) scanKeys[i];
+		
+			for (j = 0; j < n_keys; j++)
 			{
-				clause = nth(j, qual);
-				scanexpr = (run_keys[j] == RIGHT_OP) ?
-					(Node *) get_rightop(clause) : (Node *) get_leftop(clause);
-
 				/*
-				 * pass in isDone but ignore it.  We don't iterate in
-				 * quals
+				 * If we have a run-time key, then extract the run-time
+				 * expression and evaluate it with respect to the current
+				 * outer tuple.  We then stick the result into the scan key.
 				 */
-				scanvalue = (Datum)
-					ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
-				scan_keys[j].sk_argument = scanvalue;
-				if (isNull)
-					scan_keys[j].sk_flags |= SK_ISNULL;
-				else
-					scan_keys[j].sk_flags &= ~SK_ISNULL;
+				if (run_keys[j] != NO_OP)
+				{
+					clause = nth(j, qual);
+					scanexpr = (run_keys[j] == RIGHT_OP) ?
+						(Node *) get_rightop(clause) : (Node *) get_leftop(clause);
+	
+					/*
+					 * pass in isDone but ignore it.  We don't iterate in
+					 * quals
+					 */
+					scanvalue = (Datum)
+						ExecEvalExpr(scanexpr, exprCtxt, &isNull, &isDone);
+					scan_keys[j].sk_argument = scanvalue;
+					if (isNull)
+						scan_keys[j].sk_flags |= SK_ISNULL;
+					else
+						scan_keys[j].sk_flags &= ~SK_ISNULL;
+				}
 			}
+			sdesc = scanDescs[i];
+			skey = scanKeys[i];
+			index_rescan(sdesc, direction, skey);
 		}
-	}
-
-	/*
-	 * rescans all indices
-	 *
-	 * note: AMrescan assumes only one scan key.  This may have to change if
-	 * we ever decide to support multiple keys.
-	 */
-	for (i = 0; i < numIndices; i++)
-	{
-		sdesc = scanDescs[i];
-		skey = scanKeys[i];
-		index_rescan(sdesc, direction, skey);
-	}
 
 	/* ----------------
 	 *	perhaps return something meaningful
@@ -322,19 +326,23 @@ ExecEndIndexScan(IndexScan *node)
 {
 	CommonScanState *scanstate;
 	IndexScanState *indexstate;
+	Pointer    *runtimeKeyInfo;
 	ScanKey    *scanKeys;
+	int		   *numScanKeys;
 	int			numIndices;
 	int			i;
 
 	scanstate = node->scan.scanstate;
 	indexstate = node->indxstate;
-
+	runtimeKeyInfo = (Pointer *) indexstate->iss_RuntimeKeyInfo;
+	
 	/* ----------------
 	 *	extract information from the node
 	 * ----------------
 	 */
 	numIndices = indexstate->iss_NumIndices;
 	scanKeys = indexstate->iss_ScanKeys;
+	numScanKeys = indexstate->iss_NumScanKeys;
 
 	/* ----------------
 	 *	Free the projection info and the scan attribute info
@@ -362,7 +370,24 @@ ExecEndIndexScan(IndexScan *node)
 		if (scanKeys[i] != NULL)
 			pfree(scanKeys[i]);
 	}
+	pfree(scanKeys);
+	pfree(numScanKeys);
+
+	if (runtimeKeyInfo)
+	{	
+		for (i = 0; i < numIndices; i++)
+		{
+			List	   *qual;
+			int			n_keys;
 
+			qual = nth(i, indxqual);
+			n_keys = length(qual);
+			if (n_keys > 0)
+				pfree(runtimeKeyInfo[i]);
+		}
+		pfree(runtimeKeyInfo);
+	}
+	
 	/* ----------------
 	 *	clear out tuple table slots
 	 * ----------------
@@ -430,7 +455,7 @@ ExecIndexRestrPos(IndexScan *node)
 
 /* ----------------------------------------------------------------
  *		ExecInitIndexScan
- *
+  *
  *		Initializes the index scan's state information, creates
  *		scan keys, and opens the base and index relations.
  *
@@ -886,20 +911,7 @@ ExecInitIndexScan(IndexScan *node, EState *estate, Plan *parent)
 	if (have_runtime_keys)
 		indexstate->iss_RuntimeKeyInfo = (Pointer) runtimeKeyInfo;
 	else
-	{
 		indexstate->iss_RuntimeKeyInfo = NULL;
-		for (i = 0; i < numIndices; i++)
-		{
-			List	   *qual;
-			int			n_keys;
-
-			qual = nth(i, indxqual);
-			n_keys = length(qual);
-			if (n_keys > 0)
-				pfree(runtimeKeyInfo[i]);
-		}
-		pfree(runtimeKeyInfo);
-	}
 
 	/* ----------------
 	 *	get the range table and direction information
@@ -991,6 +1003,5 @@ int
 ExecCountSlotsIndexScan(IndexScan *node)
 {
 	return ExecCountSlotsNode(outerPlan((Plan *) node)) +
-	ExecCountSlotsNode(innerPlan((Plan *) node)) +
-	INDEXSCAN_NSLOTS;
+		   ExecCountSlotsNode(innerPlan((Plan *) node)) + INDEXSCAN_NSLOTS;
 }
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 518b6f553da12d7de6f3ef91ef017047c36dcbeb..fbaa1298c3661aed8b99c7cea9f8c3e672369cb3 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -1,4 +1,4 @@
-/*-------------------------------------------------------------------------
+ /*-------------------------------------------------------------------------
  *
  * copyfuncs.c--
  *	  Copy functions for Postgres tree nodes.
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.44 1998/07/18 04:22:25 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.45 1998/08/01 22:12:05 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -990,16 +990,16 @@ _copyArrayRef(ArrayRef *from)
  */
 
 /* ----------------
- *		_copyRel
+ *		_copyRelOptInfo
  * ----------------
  */
 /*
- ** when you change this, also make sure to fix up xfunc_copyRel in
+ ** when you change this, also make sure to fix up xfunc_copyRelOptInfo in
  ** planner/path/xfunc.c accordingly!!!
  **			-- JMH, 8/2/93
  */
 static RelOptInfo *
-_copyRel(RelOptInfo *from)
+_copyRelOptInfo(RelOptInfo *from)
 {
 	RelOptInfo		   *newnode = makeNode(RelOptInfo);
 	int			i,
@@ -1735,7 +1735,7 @@ copyObject(void *from)
 			 * RELATION NODES
 			 */
 		case T_RelOptInfo:
-			retval = _copyRel(from);
+			retval = _copyRelOptInfo(from);
 			break;
 		case T_Path:
 			retval = _copyPath(from);
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 3c6bbe4d306e33743443991ea0b424f26b1757c3..675cb856bc6adf4ba0ee447d2287bbb00cac8ecb 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.16 1998/02/26 04:32:07 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.17 1998/08/01 22:12:07 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -302,6 +302,19 @@ _equalCInfo(CInfo *a, CInfo *b)
 				  (b->indexids)));
 }
 
+/*
+ * RelOptInfo is a subclass of Node.
+ */
+static bool
+_equalRelOptInfo(RelOptInfo *a, RelOptInfo *b)
+{
+	Assert(IsA(a, RelOptInfo));
+	Assert(IsA(b, RelOptInfo));
+
+	return (equal((a->relids),
+				  (b->relids)));
+}
+
 static bool
 _equalJoinMethod(JoinMethod *a, JoinMethod *b)
 {
@@ -663,6 +676,9 @@ equal(void *a, void *b)
 		case T_CInfo:
 			retval = _equalCInfo(a, b);
 			break;
+		case T_RelOptInfo:
+			retval = _equalRelOptInfo(a, b);
+			break;
 		case T_JoinMethod:
 			retval = _equalJoinMethod(a, b);
 			break;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index aaa726740ff1302823c3cfb23df731b4edea8d66..693039405abe9a94275f099dc925a158389f341f 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.41 1998/07/18 04:22:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.42 1998/08/01 22:12:08 momjian Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -990,7 +990,7 @@ _outEState(StringInfo str, EState *node)
  *	Stuff from relation.h
  */
 static void
-_outRel(StringInfo str, RelOptInfo *node)
+_outRelOptInfo(StringInfo str, RelOptInfo *node)
 {
 	char		buf[500];
 
@@ -1788,7 +1788,7 @@ _outNode(StringInfo str, void *obj)
 				_outEState(str, obj);
 				break;
 			case T_RelOptInfo:
-				_outRel(str, obj);
+				_outRelOptInfo(str, obj);
 				break;
 			case T_TargetEntry:
 				_outTargetEntry(str, obj);
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index 39201e2613e1f767c947fb6035c9e282eee78750..61032aaaa502b59795a096eb929f5b5f5dd9459e 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.33 1998/07/18 04:22:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.34 1998/08/01 22:12:09 momjian Exp $
  *
  * NOTES
  *	  Most of the read functions for plan nodes are tested. (In fact, they
@@ -1218,11 +1218,11 @@ _readEState()
  */
 
 /* ----------------
- *		_readRel
+ *		_readRelOptInfo
  * ----------------
  */
 static RelOptInfo *
-_readRel()
+_readRelOptInfo()
 {
 	RelOptInfo		   *local_node;
 	char	   *token;
@@ -1991,7 +1991,7 @@ parsePlanString(void)
 	else if (!strncmp(token, "ESTATE", length))
 		return_value = _readEState();
 	else if (!strncmp(token, "RELOPTINFO", length))
-		return_value = _readRel();
+		return_value = _readRelOptInfo();
 	else if (!strncmp(token, "TARGETENTRY", length))
 		return_value = _readTargetEntry();
 	else if (!strncmp(token, "RTE", length))
diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c
index c372b6ce64447a9bb142fd42008976e9921b9001..5f495d92a7ffd2d2486154514ad6242dd7ae1939 100644
--- a/src/backend/optimizer/path/clausesel.c
+++ b/src/backend/optimizer/path/clausesel.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.9 1998/07/18 04:22:30 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.10 1998/08/01 22:12:11 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -159,19 +159,8 @@ set_rest_selec(Query *root, List *clauseinfo_list)
 Cost
 compute_clause_selec(Query *root, Node *clause, List *or_selectivities)
 {
-	if (!is_opclause(clause))
-	{
-
-		/*
-		 * if it's not an operator clause, then it is a boolean clause
-		 * -jolly
-		 */
-
-		/*
-		 * Boolean variables get a selectivity of 1/2.
-		 */
-		return (0.1);
-	}
+    if (is_opclause (clause))
+	    return compute_selec(root, lcons(clause,NIL), or_selectivities);
 	else if (not_clause(clause))
 	{
 
diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 3722688a21b4aa908fbb7a78edde5a2de53c16c0..b557d9d59b34d2a7b3bdbbd8ce4fdcde0b7f8739 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.19 1998/07/31 15:10:40 vadim Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/indxpath.c,v 1.20 1998/08/01 22:12:12 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "access/nbtree.h"
 #include "catalog/catname.h"
 #include "catalog/pg_amop.h"
+#include "catalog/pg_type.h"
 #include "executor/executor.h"
 #include "fmgr.h"
 #include "nodes/makefuncs.h"
@@ -77,10 +78,7 @@ create_index_paths(Query *root, RelOptInfo *rel, RelOptInfo *index,
 				   List *clausegroup_list, bool join);
 static List *add_index_paths(List *indexpaths, List *new_indexpaths);
 static bool function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index);
-static bool SingleAttributeIndex(RelOptInfo *index);
 
-/* If Spyros can use a constant PRS2_BOOL_TYPEID, I can use this */
-#define BOOL_TYPEID ((Oid) 16)
 
 /*
  * find-index-paths--
@@ -121,91 +119,82 @@ find_index_paths(Query *root,
 	List	   *joinclausegroups = NIL;
 	List	   *joinpaths = NIL;
 	List	   *retval = NIL;
-
-	if (indices == NIL)
-		return (NULL);
-
-	index = (RelOptInfo *) lfirst(indices);
-
-	retval = find_index_paths(root,
-							  rel,
-							  lnext(indices),
-							  clauseinfo_list,
-							  joininfo_list);
-
-	/* If this is a partial index, return if it fails the predicate test */
-	if (index->indpred != NIL)
-		if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
-			return retval;
-
-	/*
-	 * 1. If this index has only one key, try matching it against
-	 * subclauses of an 'or' clause.  The fields of the clauseinfo nodes
-	 * are marked with lists of the matching indices no path are actually
-	 * created.
-	 *
-	 * XXX NOTE:  Currently btrees dos not support indices with > 1 key, so
-	 * the following test will always be true for now but we have decided
-	 * not to support index-scans on disjunction . -- lp
-	 */
-	if (SingleAttributeIndex(index))
+	List	   *ilist;
+	
+	foreach(ilist, indices)
 	{
+		index = (RelOptInfo *) lfirst(ilist);
+	
+		/* If this is a partial index, return if it fails the predicate test */
+		if (index->indpred != NIL)
+			if (!pred_test(index->indpred, clauseinfo_list, joininfo_list))
+				continue;
+	
+		/*
+		 * 1. Try matching the index against subclauses of an 'or' clause.
+		 * The fields of the clauseinfo nodes are marked with lists of the
+		 * matching indices.  No path are actually created.  We currently
+		 * only look to match the first key.  We don't find multi-key index
+		 * cases where an AND matches the first key, and the OR matches the
+		 * second key.
+		 */
 		match_index_orclauses(rel,
-							  index,
-							  index->indexkeys[0],
-							  index->classlist[0],
-							  clauseinfo_list);
-	}
-
-	/*
-	 * 2. If the keys of this index match any of the available restriction
-	 * clauses, then create pathnodes corresponding to each group of
-	 * usable clauses.
-	 */
-	scanclausegroups = group_clauses_by_indexkey(rel,
-												 index,
-												 index->indexkeys,
-												 index->classlist,
-												 clauseinfo_list);
-
-	scanpaths = NIL;
-	if (scanclausegroups != NIL)
-		scanpaths = create_index_paths(root,
-									   rel,
-									   index,
-									   scanclausegroups,
-									   false);
-
-	/*
-	 * 3. If this index can be used with any join clause, then create
-	 * pathnodes for each group of usable clauses.	An index can be used
-	 * with a join clause if its ordering is useful for a mergejoin, or if
-	 * the index can possibly be used for scanning the inner relation of a
-	 * nestloop join.
-	 */
-	joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
-	joinpaths = NIL;
-
-	if (joinclausegroups != NIL)
-	{
-		List	   *new_join_paths = create_index_paths(root, rel,
-														index,
-														joinclausegroups,
-														true);
-		List	   *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
-
-		rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
-		joinpaths = new_join_paths;
+								  index,
+								  index->indexkeys[0],
+								  index->classlist[0],
+								  clauseinfo_list);
+		}
+	
+		/*
+		 * 2. If the keys of this index match any of the available restriction
+		 * clauses, then create pathnodes corresponding to each group of
+		 * usable clauses.
+		 */
+		scanclausegroups = group_clauses_by_indexkey(rel,
+													 index,
+													 index->indexkeys,
+													 index->classlist,
+													 clauseinfo_list);
+	
+		scanpaths = NIL;
+		if (scanclausegroups != NIL)
+			scanpaths = create_index_paths(root,
+										   rel,
+										   index,
+										   scanclausegroups,
+										   false);
+	
+		/*
+		 * 3. If this index can be used with any join clause, then create
+		 * pathnodes for each group of usable clauses.	An index can be used
+		 * with a join clause if its ordering is useful for a mergejoin, or if
+		 * the index can possibly be used for scanning the inner relation of a
+		 * nestloop join.
+		 */
+		joinclausegroups = indexable_joinclauses(rel, index, joininfo_list, clauseinfo_list);
+		joinpaths = NIL;
+	
+		if (joinclausegroups != NIL)
+		{
+			List	   *new_join_paths = create_index_paths(root, rel,
+															index,
+															joinclausegroups,
+															true);
+			List	   *innerjoin_paths = index_innerjoin(root, rel, joinclausegroups, index);
+	
+			rel->innerjoin = nconc(rel->innerjoin, innerjoin_paths);
+			joinpaths = new_join_paths;
+		}
+	
+		/*
+		 * Some sanity checks to make sure that the indexpath is valid.
+		 */
+		if (joinpaths != NULL)
+			retval = add_index_paths(joinpaths, retval);
+		if (scanpaths != NULL)
+			retval = add_index_paths(scanpaths, retval);
 	}
-
-	/*
-	 * Some sanity checks to make sure that the indexpath is valid.
-	 */
-	if (joinpaths != NULL)
-		retval = add_index_paths(joinpaths, retval);
-	if (scanpaths != NULL)
-		retval = add_index_paths(scanpaths, retval);
-
+	
 	return retval;
 
 }
@@ -297,7 +286,7 @@ match_index_to_operand(int indexkey,
  *	  (1) the operator within the subclause can be used with one
  *				of the index's operator classes, and
  *	  (2) there is a usable key that matches the variable within a
- *				sargable clause.
+ *				searchable clause.
  *
  * 'or-clauses' are the remaining subclauses within the 'or' clause
  * 'other-matching-indices' is the list of information on other indices
@@ -322,30 +311,31 @@ match_index_orclause(RelOptInfo *rel,
 	List	   *matched_indices = other_matching_indices;
 	List	   *index_list = NIL;
 	List	   *clist;
-	List	   *ind;
-
-	if (!matched_indices)
-		matched_indices = lcons(NIL, NIL);
 
-	for (clist = or_clauses, ind = matched_indices;
-		 clist;
-		 clist = lnext(clist), ind = lnext(ind))
+	foreach(clist, or_clauses)
 	{
 		clause = lfirst(clist);
 		if (is_opclause(clause) &&
 			op_class(((Oper *) ((Expr *) clause)->oper)->opno,
 					 xclass, index->relam) &&
-			match_index_to_operand(indexkey,
+			((match_index_to_operand(indexkey,
+								   (Expr *) get_leftop((Expr *) clause),
+								   rel,
+								   index) &&
+			  IsA(get_rightop((Expr *) clause), Const)) ||
+			 (match_index_to_operand(indexkey,
 								   (Expr *) get_leftop((Expr *) clause),
 								   rel,
 								   index) &&
-			IsA(get_rightop((Expr *) clause), Const))
+			 IsA(get_rightop((Expr *) clause), Const))))
 		{
-
 			matched_indices = lcons(index, matched_indices);
-			index_list = lappend(index_list,
-								 matched_indices);
 		}
+		index_list = lappend(index_list, matched_indices);
+
+		/* for the first index, we are creating the indexids list */
+		if (matched_indices)
+			matched_indices = lnext(matched_indices);
 	}
 	return (index_list);
 
@@ -1061,7 +1051,7 @@ clause_pred_clause_test(Expr *predicate, Node *clause)
 	 */
 	test_oper = makeOper(test_op,		/* opno */
 						 InvalidOid,	/* opid */
-						 BOOL_TYPEID,	/* opresulttype */
+						 BOOLOID,	/* opresulttype */
 						 0,		/* opsize */
 						 NULL); /* op_fcache */
 	replace_opid(test_oper);
@@ -1176,7 +1166,8 @@ extract_restrict_clauses(List *clausegroup)
  *
  */
 static List *
-index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list, RelOptInfo *index)
+index_innerjoin(Query *root, RelOptInfo *rel, List *clausegroup_list,
+				RelOptInfo *index)
 {
 	List	   *clausegroup = NIL;
 	List	   *cg_list = NIL;
@@ -1366,29 +1357,3 @@ function_index_operand(Expr *funcOpnd, RelOptInfo *rel, RelOptInfo *index)
 
 	return true;
 }
-
-static bool
-SingleAttributeIndex(RelOptInfo *index)
-{
-
-	/*
-	 * return false for now as I don't know if we support index scans on
-	 * disjunction and the code doesn't work
-	 */
-	return (false);
-
-#if 0
-
-	/*
-	 * Non-functional indices.
-	 */
-	if (index->indproc == InvalidOid)
-		return (index->indexkeys[0] != 0 &&
-				index->indexkeys[1] == 0);
-
-	/*
-	 * We have a functional index which is a single attr index
-	 */
-	return true;
-#endif
-}
diff --git a/src/backend/optimizer/path/orindxpath.c b/src/backend/optimizer/path/orindxpath.c
index c697078e1b20986f417959d85d057ee7749b217e..7f220fc54bae2af6b1805a2b4fe8791e833705de 100644
--- a/src/backend/optimizer/path/orindxpath.c
+++ b/src/backend/optimizer/path/orindxpath.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.7 1998/07/18 04:22:33 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/optimizer/path/orindxpath.c,v 1.8 1998/08/01 22:12:13 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -55,10 +55,11 @@ create_or_index_paths(Query *root,
 					  RelOptInfo *rel, List *clauses)
 {
 	List	   *t_list = NIL;
+	List	   *clist;
 
-	if (clauses != NIL)
+	foreach(clist, clauses)
 	{
-		CInfo	   *clausenode = (CInfo *) (lfirst(clauses));
+		CInfo	   *clausenode = (CInfo *) (lfirst(clist));
 
 		/*
 		 * Check to see if this clause is an 'or' clause, and, if so,
@@ -77,8 +78,11 @@ create_or_index_paths(Query *root,
 			index_list = clausenode->indexids;
 			foreach(temp, index_list)
 			{
-				if (!temp)
+				if (!lfirst(temp))
+				{
 					index_flag = false;
+					break;
+				}
 			}
 			if (index_flag)
 			{					/* used to be a lisp every function */
@@ -100,8 +104,7 @@ create_or_index_paths(Query *root,
 
 				pathnode->path.pathtype = T_IndexScan;
 				pathnode->path.parent = rel;
-				pathnode->indexqual =
-					lcons(clausenode, NIL);
+				pathnode->indexqual = lcons(clausenode, NIL);
 				pathnode->indexid = indexids;
 				pathnode->path.path_cost = cost;
 
@@ -110,9 +113,8 @@ create_or_index_paths(Query *root,
 				 * processing	 -- JMH, 7/7/92
 				 */
 				pathnode->path.locclauseinfo =
-					set_difference(clauses,
-								   copyObject((Node *)
-											  rel->clauseinfo));
+					set_difference(copyObject((Node *)rel->clauseinfo),
+								   lcons(clausenode,NIL));
 
 #if 0							/* fix xfunc */
 				/* add in cost for expensive functions!  -- JMH, 7/7/92 */
@@ -123,12 +125,8 @@ create_or_index_paths(Query *root,
 				}
 #endif
 				clausenode->selectivity = (Cost) floatVal(selecs);
-				t_list =
-					lcons(pathnode,
-					   create_or_index_paths(root, rel, lnext(clauses)));
+				t_list = lappend(t_list, pathnode);
 			}
-			else
-				t_list = create_or_index_paths(root, rel, lnext(clauses));
 		}
 	}
 
@@ -167,32 +165,28 @@ best_or_subclause_indices(Query *root,
 						  Cost *cost,	/* return value */
 						  List **selecs)		/* return value */
 {
-	if (subclauses == NIL)
-	{
-		*indexids = nreverse(examined_indexids);
-		*cost = subcost;
-		*selecs = nreverse(selectivities);
-	}
-	else
+	List *slist;
+	
+	foreach (slist, subclauses)
 	{
 		int			best_indexid;
 		Cost		best_cost;
 		Cost		best_selec;
 
-		best_or_subclause_index(root, rel, lfirst(subclauses), lfirst(indices),
+		best_or_subclause_index(root, rel, lfirst(slist), lfirst(indices),
 								&best_indexid, &best_cost, &best_selec);
+								
+		examined_indexids = lappendi(examined_indexids, best_indexid);
+		subcost += best_cost;
+		selectivities = lappend(selectivities, makeFloat(best_selec));
 
-		best_or_subclause_indices(root,
-								  rel,
-								  lnext(subclauses),
-								  lnext(indices),
-								  lconsi(best_indexid, examined_indexids),
-								  subcost + best_cost,
-							 lcons(makeFloat(best_selec), selectivities),
-								  indexids,
-								  cost,
-								  selecs);
+		indices = lnext(indices);
 	}
+
+	*indexids = examined_indexids;
+	*cost = subcost;
+	*selecs = selectivities;
+
 	return;
 }
 
@@ -219,20 +213,21 @@ best_or_subclause_index(Query *root,
 						Cost *retCost,	/* return value */
 						Cost *retSelec) /* return value */
 {
-	if (indices != NIL)
+	List *ilist;
+	bool first_run = true;
+	
+	foreach (ilist, indices)
 	{
+		RelOptInfo		   *index = (RelOptInfo *) lfirst(ilist);
+		
 		Datum		value;
 		int			flag = 0;
 		Cost		subcost;
-		RelOptInfo		   *index = (RelOptInfo *) lfirst(indices);
 		AttrNumber	attno = (get_leftop(subclause))->varattno;
 		Oid			opno = ((Oper *) subclause->oper)->opno;
 		bool		constant_on_right = non_null((Expr *) get_rightop(subclause));
 		float		npages,
 					selec;
-		int			subclause_indexid;
-		Cost		subclause_cost;
-		Cost		subclause_selec;
 
 		if (constant_on_right)
 			value = ((Const *) get_rightop(subclause))->constvalue;
@@ -242,6 +237,7 @@ best_or_subclause_index(Query *root,
 			flag = (_SELEC_IS_CONSTANT_ || _SELEC_CONSTANT_RIGHT_);
 		else
 			flag = _SELEC_CONSTANT_RIGHT_;
+
 		index_selectivity(lfirsti(index->relids),
 						  index->classlist,
 						  lconsi(opno, NIL),
@@ -262,26 +258,22 @@ best_or_subclause_index(Query *root,
 							 index->pages,
 							 index->tuples,
 							 false);
-		best_or_subclause_index(root,
-								rel,
-								subclause,
-								lnext(indices),
-								&subclause_indexid,
-								&subclause_cost,
-								&subclause_selec);
 
-		if (subclause_indexid == 0 || subcost < subclause_cost)
+		if (first_run || subcost < *retCost)
 		{
 			*retIndexid = lfirsti(index->relids);
 			*retCost = subcost;
 			*retSelec = selec;
+			first_run = false;
 		}
-		else
-		{
-			*retIndexid = 0;
-			*retCost = 0.0;
-			*retSelec = 0.0;
-		}
+	}
+
+	/* we didn't get any indexes, so zero return values */
+	if (first_run)
+	{
+		*retIndexid = 0;
+		*retCost = 0.0;
+		*retSelec = 0.0;
 	}
 	return;
 }