diff --git a/src/backend/optimizer/path/indxpath.c b/src/backend/optimizer/path/indxpath.c
index 525304f5cb313e76a7a81a5721f03f4a4c8bb049..be684094119c5b7f7588502edbb1ab86c187e07a 100644
--- a/src/backend/optimizer/path/indxpath.c
+++ b/src/backend/optimizer/path/indxpath.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.184 2005/06/13 23:14:48 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/optimizer/path/indxpath.c,v 1.185 2005/06/14 04:04:30 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -65,6 +65,17 @@ static bool matches_any_index(RestrictInfo *rinfo, RelOptInfo *rel,
 							  Relids outer_relids);
 static List *find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
 								   Relids outer_relids, bool isouterjoin);
+static bool match_variant_ordering(PlannerInfo *root,
+								   IndexOptInfo *index,
+								   List *restrictclauses,
+								   ScanDirection *indexscandir);
+static List *identify_ignorable_ordering_cols(PlannerInfo *root,
+											  IndexOptInfo *index,
+											  List *restrictclauses);
+static bool match_index_to_query_keys(PlannerInfo *root,
+									  IndexOptInfo *index,
+									  ScanDirection indexscandir,
+									  List *ignorables);
 static bool match_boolean_index_clause(Node *clause, int indexcol,
 									   IndexOptInfo *index);
 static bool match_special_index_operator(Expr *clause, Oid opclass,
@@ -315,22 +326,24 @@ find_usable_indexes(PlannerInfo *root, RelOptInfo *rel,
 		}
 
 		/*
-		 * 4. If the index is ordered, a backwards scan might be
-		 * interesting. Currently this is only possible for a DESC query
-		 * result ordering.
+		 * 4. If the index is ordered, and there is a requested query
+		 * ordering that we failed to match, consider variant ways of
+		 * achieving the ordering.  Again, this is only interesting
+		 * at top level.
 		 */
-		if (istoplevel && index_is_ordered && !isjoininner)
+		if (istoplevel && index_is_ordered && !isjoininner &&
+			root->query_pathkeys != NIL &&
+			pathkeys_useful_for_ordering(root, useful_pathkeys) == 0)
 		{
-			index_pathkeys = build_index_pathkeys(root, index,
-												  BackwardScanDirection);
-			useful_pathkeys = truncate_useless_pathkeys(root, rel,
-														index_pathkeys);
-			if (useful_pathkeys != NIL)
+			ScanDirection	indexscandir;
+
+			if (match_variant_ordering(root, index, restrictclauses,
+									   &indexscandir))
 			{
 				ipath = create_index_path(root, index,
 										  restrictclauses,
-										  useful_pathkeys,
-										  BackwardScanDirection,
+										  root->query_pathkeys,
+										  indexscandir,
 										  false);
 				result = lappend(result, ipath);
 			}
@@ -1220,6 +1233,255 @@ find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
 	return clause_list;
 }
 
+/****************************************************************************
+ *				----  ROUTINES TO HANDLE PATHKEYS  ----
+ ****************************************************************************/
+
+/*
+ * match_variant_ordering
+ *		Try to match an index's ordering to the query's requested ordering
+ *
+ * This is used when the index is ordered but a naive comparison fails to
+ * match its ordering (pathkeys) to root->query_pathkeys.  It may be that
+ * we need to scan the index backwards.  Also, a less naive comparison can
+ * help for both forward and backward indexscans.  Columns of the index
+ * that have an equality restriction clause can be ignored in the match;
+ * that is, an index on (x,y) can be considered to match the ordering of
+ *		... WHERE x = 42 ORDER BY y;
+ *
+ * Note: it would be possible to similarly ignore useless ORDER BY items;
+ * that is, an index on just y could be considered to match the ordering of
+ *		... WHERE x = 42 ORDER BY x, y;
+ * But proving that this is safe would require finding a btree opclass
+ * containing both the = operator and the < or > operator in the ORDER BY
+ * item.  That's significantly more expensive than what we do here, since
+ * we'd have to look at restriction clauses unrelated to the current index
+ * and search for opclasses without any hint from the index.  The practical
+ * use-cases seem to be mostly covered by ignoring index columns, so that's
+ * all we do for now.
+ *
+ * Inputs:
+ * 'index' is the index of interest.
+ * 'restrictclauses' is the list of sublists of restriction clauses
+ *		matching the columns of the index (NIL if none)
+ *
+ * Returns TRUE if able to match the requested query pathkeys, FALSE if not.
+ * In the TRUE case, sets '*indexscandir' to either ForwardScanDirection or
+ * BackwardScanDirection to indicate the proper scan direction.
+ */
+static bool
+match_variant_ordering(PlannerInfo *root,
+					   IndexOptInfo *index,
+					   List *restrictclauses,
+					   ScanDirection *indexscandir)
+{
+	List	   *ignorables;
+
+	/*
+	 * Forget the whole thing if not a btree index; our check for ignorable
+	 * columns assumes we are dealing with btree opclasses.  (It'd be possible
+	 * to factor out just the try for backwards indexscan, but considering
+	 * that we presently have no orderable indexes except btrees anyway,
+	 * it's hardly worth contorting this code for that case.)
+	 *
+	 * Note: if you remove this, you probably need to put in a check on
+	 * amoptionalkey to prevent possible clauseless scan on an index that
+	 * won't cope.
+	 */
+	if (index->relam != BTREE_AM_OID)
+		return false;
+	/*
+	 * Figure out which index columns can be optionally ignored because
+	 * they have an equality constraint.  This is the same set for either
+	 * forward or backward scan, so we do it just once.
+	 */
+	ignorables = identify_ignorable_ordering_cols(root, index,
+												  restrictclauses);
+	/*
+	 * Try to match to forward scan, then backward scan.  However, we can
+	 * skip the forward-scan case if there are no ignorable columns,
+	 * because find_usable_indexes() would have found the match already.
+	 */
+	if (ignorables &&
+		match_index_to_query_keys(root, index, ForwardScanDirection,
+								  ignorables))
+	{
+		*indexscandir = ForwardScanDirection;
+		return true;
+	}
+	if (match_index_to_query_keys(root, index, BackwardScanDirection,
+								  ignorables))
+	{
+		*indexscandir = BackwardScanDirection;
+		return true;
+	}
+	return false;
+}
+
+/*
+ * identify_ignorable_ordering_cols
+ *		Determine which index columns can be ignored for ordering purposes
+ *
+ * Returns an integer List of column numbers (1-based) of ignorable
+ * columns.  The ignorable columns are those that have equality constraints
+ * against pseudoconstants.
+ */
+static List *
+identify_ignorable_ordering_cols(PlannerInfo *root,
+								 IndexOptInfo *index,
+								 List *restrictclauses)
+{
+	List	   *result = NIL;
+	int			indexcol = 0;			/* note this is 0-based */
+	ListCell   *l;
+
+	/* restrictclauses is either NIL or has a sublist per column */
+	foreach(l, restrictclauses)
+	{
+		List   *sublist = (List *) lfirst(l);
+		Oid		opclass = index->classlist[indexcol];
+		ListCell *l2;
+
+		foreach(l2, sublist)
+		{
+			RestrictInfo *rinfo = (RestrictInfo *) lfirst(l2);
+			OpExpr	   *clause = (OpExpr *) rinfo->clause;
+			Oid		clause_op;
+			int		op_strategy;
+			bool	varonleft;
+			bool	ispc;
+
+			/* We know this clause passed match_clause_to_indexcol */
+
+			/* First check for boolean-index cases. */
+			if (IsBooleanOpclass(opclass))
+			{
+				if (match_boolean_index_clause((Node *) clause, indexcol,
+											   index))
+				{
+					/*
+					 * The clause means either col = TRUE or col = FALSE;
+					 * we do not care which, it's an equality constraint
+					 * either way.
+					 */
+					result = lappend_int(result, indexcol+1);
+					break;
+				}
+			}
+
+			/* Else clause must be a binary opclause. */
+			Assert(IsA(clause, OpExpr));
+
+			/* Determine left/right sides and check the operator */
+			clause_op = clause->opno;
+			if (match_index_to_operand(linitial(clause->args), indexcol,
+									   index))
+			{
+				/* clause_op is correct */
+				varonleft = true;
+			}
+			else
+			{
+				Assert(match_index_to_operand(lsecond(clause->args), indexcol,
+											  index));
+				/* Must flip operator to get the opclass member */
+				clause_op = get_commutator(clause_op);
+				varonleft = false;
+			}
+			if (!OidIsValid(clause_op))
+				continue;		/* ignore non match, per next comment */
+			op_strategy = get_op_opclass_strategy(clause_op, opclass);
+
+			/*
+			 * You might expect to see Assert(op_strategy != 0) here,
+			 * but you won't: the clause might contain a special indexable
+			 * operator rather than an ordinary opclass member.  Currently
+			 * none of the special operators are very likely to expand to
+			 * an equality operator; we do not bother to check, but just
+			 * assume no match.
+			 */
+			if (op_strategy != BTEqualStrategyNumber)
+				continue;
+
+			/* Now check that other side is pseudoconstant */
+			if (varonleft)
+				ispc = is_pseudo_constant_clause_relids(lsecond(clause->args),
+														rinfo->right_relids);
+			else
+				ispc = is_pseudo_constant_clause_relids(linitial(clause->args),
+														rinfo->left_relids);
+			if (ispc)
+			{
+				result = lappend_int(result, indexcol+1);
+				break;
+			}
+		}
+		indexcol++;
+	}
+	return result;
+}
+
+/*
+ * match_index_to_query_keys
+ *		Check a single scan direction for "intelligent" match to query keys
+ *
+ * 'index' is the index of interest.
+ * 'indexscandir' is the scan direction to consider
+ * 'ignorables' is an integer list of indexes of ignorable index columns
+ *
+ * Returns TRUE on successful match (ie, the query_pathkeys can be considered
+ * to match this index).
+ */
+static bool
+match_index_to_query_keys(PlannerInfo *root,
+						  IndexOptInfo *index,
+						  ScanDirection indexscandir,
+						  List *ignorables)
+{
+	List	   *index_pathkeys;
+	ListCell   *index_cell;
+	int			index_col;
+	ListCell   *r;
+
+	/* Get the pathkeys that exactly describe the index */
+	index_pathkeys = build_index_pathkeys(root, index, indexscandir);
+
+	/*
+	 * Can we match to the query's requested pathkeys?  The inner loop
+	 * skips over ignorable index columns while trying to match.
+	 */
+	index_cell = list_head(index_pathkeys);
+	index_col = 0;
+
+	foreach(r, root->query_pathkeys)
+	{
+		List	   *rsubkey = (List *) lfirst(r);
+
+		for (;;)
+		{
+			List   *isubkey;
+
+			if (index_cell == NULL)
+				return false;
+			isubkey = (List *) lfirst(index_cell);
+			index_cell = lnext(index_cell);
+			index_col++;		/* index_col is now 1-based */
+			/*
+			 * Since we are dealing with canonicalized pathkeys, pointer
+			 * comparison is sufficient to determine a match.
+			 */
+			if (rsubkey == isubkey)
+				break;			/* matched current query pathkey */
+
+			if (!list_member_int(ignorables, index_col))
+				return false;	/* definite failure to match */
+			/* otherwise loop around and try to match to next index col */
+		}
+	}
+
+	return true;
+}
+
 /****************************************************************************
  *				----  PATH CREATION UTILITIES  ----
  ****************************************************************************/
@@ -1230,7 +1492,8 @@ find_clauses_for_join(PlannerInfo *root, RelOptInfo *rel,
  *	  of RestrictInfos.
  *
  * This is used to flatten out the result of group_clauses_by_indexkey()
- * to produce an indexclauses list.
+ * to produce an indexclauses list.  The original list structure mustn't
+ * be altered, but it's OK to share copies of the underlying RestrictInfos.
  */
 List *
 flatten_clausegroups_list(List *clausegroups)