*   a set of equality conditions, because the conditions constrain all
  *   columns of some unique index.
  *
- * The conditions are provided as a list of RestrictInfo nodes, where the
- * caller has already determined that each condition is a mergejoinable
- * equality with an expression in this relation on one side, and an
- * expression not involving this relation on the other.  The transient
- * outer_is_left flag is used to identify which side we should look at:
- * left side if outer_is_left is false, right side if it is true.
+ * The conditions can be represented in either or both of two ways:
+ * 1. A list of RestrictInfo nodes, where the caller has already determined
+ * that each condition is a mergejoinable equality with an expression in
+ * this relation on one side, and an expression not involving this relation
+ * on the other.  The transient outer_is_left flag is used to identify which
+ * side we should look at: left side if outer_is_left is false, right side
+ * if it is true.
+ * 2. A list of expressions in this relation, and a corresponding list of
+ * equality operators. The caller must have already checked that the operators
+ * represent equality.  (Note: the operators could be cross-type; the
+ * expressions should correspond to their RHS inputs.)
+ *
+ * The caller need only supply equality conditions arising from joins;
+ * this routine automatically adds in any usable baserestrictinfo clauses.
+ * (Note that the passed-in restrictlist will be destructively modified!)
  */
 bool
 relation_has_unique_index_for(PlannerInfo *root, RelOptInfo *rel,
-                             List *restrictlist)
+                             List *restrictlist,
+                             List *exprlist, List *oprlist)
 {
    ListCell   *ic;
 
+   Assert(list_length(exprlist) == list_length(oprlist));
+
+   /* Short-circuit if no indexes... */
+   if (rel->indexlist == NIL)
+       return false;
+
+   /*
+    * Examine the rel's restriction clauses for usable var = const clauses
+    * that we can add to the restrictlist.
+    */
+   foreach(ic, rel->baserestrictinfo)
+   {
+       RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(ic);
+
+       /*
+        * Note: can_join won't be set for a restriction clause, but
+        * mergeopfamilies will be if it has a mergejoinable operator and
+        * doesn't contain volatile functions.
+        */
+       if (restrictinfo->mergeopfamilies == NIL)
+           continue;           /* not mergejoinable */
+
+       /*
+        * The clause certainly doesn't refer to anything but the given rel.
+        * If either side is pseudoconstant then we can use it.
+        */
+       if (bms_is_empty(restrictinfo->left_relids))
+       {
+           /* righthand side is inner */
+           restrictinfo->outer_is_left = true;
+       }
+       else if (bms_is_empty(restrictinfo->right_relids))
+       {
+           /* lefthand side is inner */
+           restrictinfo->outer_is_left = false;
+       }
+       else
+           continue;
+
+       /* OK, add to list */
+       restrictlist = lappend(restrictlist, restrictinfo);
+   }
+
    /* Short-circuit the easy case */
-   if (restrictlist == NIL)
+   if (restrictlist == NIL && exprlist == NIL)
        return false;
 
    /* Examine each index of the relation ... */
            continue;
 
        /*
-        * Try to find each index column in the list of conditions.  This is
-        * O(n^2) or worse, but we expect all the lists to be short.
+        * Try to find each index column in the lists of conditions.  This is
+        * O(N^2) or worse, but we expect all the lists to be short.
         */
        for (c = 0; c < ind->ncolumns; c++)
        {
+           bool        matched = false;
            ListCell   *lc;
+           ListCell   *lc2;
 
            foreach(lc, restrictlist)
            {
                    rexpr = get_leftop(rinfo->clause);
 
                if (match_index_to_operand(rexpr, c, ind))
-                   break;      /* found a match; column is unique */
+               {
+                   matched = true;     /* column is unique */
+                   break;
+               }
+           }
+
+           if (matched)
+               continue;
+
+           forboth(lc, exprlist, lc2, oprlist)
+           {
+               Node       *expr = (Node *) lfirst(lc);
+               Oid         opr = lfirst_oid(lc2);
+
+               /* See if the expression matches the index key */
+               if (!match_index_to_operand(expr, c, ind))
+                   continue;
+
+               /*
+                * The equality operator must be a member of the index
+                * opfamily, else it is not asserting the right kind of
+                * equality behavior for this index.  We assume the caller
+                * determined it is an equality operator, so we don't need to
+                * check any more tightly than this.
+                */
+               if (!op_in_opfamily(opr, ind->opfamily[c]))
+                   continue;
+
+               /*
+                * XXX at some point we may need to check collations here too.
+                * For the moment we assume all collations reduce to the same
+                * notion of equality.
+                */
+
+               matched = true;     /* column is unique */
+               break;
            }
 
-           if (lc == NULL)
+           if (!matched)
                break;          /* no match; this index doesn't help us */
        }
 
 
        clause_list = lappend(clause_list, restrictinfo);
    }
 
-   /* Now examine the rel's restriction clauses for var = const clauses */
-   foreach(l, innerrel->baserestrictinfo)
-   {
-       RestrictInfo *restrictinfo = (RestrictInfo *) lfirst(l);
-
-       /*
-        * Note: can_join won't be set for a restriction clause, but
-        * mergeopfamilies will be if it has a mergejoinable operator and
-        * doesn't contain volatile functions.
-        */
-       if (restrictinfo->mergeopfamilies == NIL)
-           continue;           /* not mergejoinable */
-
-       /*
-        * The clause certainly doesn't refer to anything but the given rel.
-        * If either side is pseudoconstant then we can use it.
-        */
-       if (bms_is_empty(restrictinfo->left_relids))
-       {
-           /* righthand side is inner */
-           restrictinfo->outer_is_left = true;
-       }
-       else if (bms_is_empty(restrictinfo->right_relids))
-       {
-           /* lefthand side is inner */
-           restrictinfo->outer_is_left = false;
-       }
-       else
-           continue;
-
-       /* OK, add to list */
-       clause_list = lappend(clause_list, restrictinfo);
-   }
+   /*
+    * relation_has_unique_index_for automatically adds any usable restriction
+    * clauses for the innerrel, so we needn't do that here.
+    */
 
    /* Now examine the indexes to see if we have a matching unique index */
-   if (relation_has_unique_index_for(root, innerrel, clause_list))
+   if (relation_has_unique_index_for(root, innerrel, clause_list, NIL, NIL))
        return true;
 
    /*
 
    pathnode->path.parent = rel;
 
    /*
-    * Treat the output as always unsorted, since we don't necessarily have
-    * pathkeys to represent it.
+    * Assume the output is unsorted, since we don't necessarily have pathkeys
+    * to represent it.  (This might get overridden below.)
     */
    pathnode->path.pathkeys = NIL;
 
    pathnode->in_operators = in_operators;
    pathnode->uniq_exprs = uniq_exprs;
 
+   /*
+    * If the input is a relation and it has a unique index that proves the
+    * uniq_exprs are unique, then we don't need to do anything.  Note that
+    * relation_has_unique_index_for automatically considers restriction
+    * clauses for the rel, as well.
+    */
+   if (rel->rtekind == RTE_RELATION && all_btree &&
+       relation_has_unique_index_for(root, rel, NIL,
+                                     uniq_exprs, in_operators))
+   {
+       pathnode->umethod = UNIQUE_PATH_NOOP;
+       pathnode->rows = rel->rows;
+       pathnode->path.startup_cost = subpath->startup_cost;
+       pathnode->path.total_cost = subpath->total_cost;
+       pathnode->path.pathkeys = subpath->pathkeys;
+
+       rel->cheapest_unique_path = (Path *) pathnode;
+
+       MemoryContextSwitchTo(oldcontext);
+
+       return pathnode;
+   }
+
    /*
     * If the input is a subquery whose output must be unique already, then we
     * don't need to do anything.  The test for uniqueness has to consider