/*
      * If this table is partitioned and we're creating a unique index or a
 -    * primary key, make sure that the indexed columns are part of the
 -    * partition key.  Otherwise it would be possible to violate uniqueness by
 -    * putting values that ought to be unique in different partitions.
 +    * primary key, make sure that the partition key is a subset of the
 +    * index's columns.  Otherwise it would be possible to violate uniqueness
 +    * by putting values that ought to be unique in different partitions.
      *
      * We could lift this limitation if we had global indexes, but those have
      * their own problems, so this is a useful feature combination.
      if (partitioned && (stmt->unique || stmt->primary))
     {
         PartitionKey key = RelationGetPartitionKey(rel);
 +       const char *constraint_type;
         int         i;
  
 +       if (stmt->primary)
 +           constraint_type = "PRIMARY KEY";
 +       else if (stmt->unique)
 +           constraint_type = "UNIQUE";
 +       else if (stmt->excludeOpNames != NIL)
 +           constraint_type = "EXCLUDE";
 +       else
 +       {
 +           elog(ERROR, "unknown constraint type");
 +           constraint_type = NULL; /* keep compiler quiet */
 +       }
 +
         /*
 -        * A partitioned table can have unique indexes, as long as all the
 -        * columns in the partition key appear in the unique key.  A
 -        * partition-local index can enforce global uniqueness iff the PK
 -        * value completely determines the partition that a row is in.
 -        *
 -        * Thus, verify that all the columns in the partition key appear in
 -        * the unique key definition.
 +        * Verify that all the columns in the partition key appear in the
 +        * unique key definition, with the same notion of equality.
          */
         for (i = 0; i < key->partnatts; i++)
         {
             bool        found = false;
 +           int         eq_strategy;
 +           Oid         ptkey_eqop;
             int         j;
 -           const char *constraint_type;
 -
 -           if (stmt->primary)
 -               constraint_type = "PRIMARY KEY";
 -           else if (stmt->unique)
 -               constraint_type = "UNIQUE";
 -           else if (stmt->excludeOpNames != NIL)
 -               constraint_type = "EXCLUDE";
 +
 +           /*
 +            * Identify the equality operator associated with this partkey
 +            * column.  For list and range partitioning, partkeys use btree
 +            * operator classes; hash partitioning uses hash operator classes.
 +            * (Keep this in sync with ComputePartitionAttrs!)
 +            */
 +           if (key->strategy == PARTITION_STRATEGY_HASH)
 +               eq_strategy = HTEqualStrategyNumber;
             else
 -           {
 -               elog(ERROR, "unknown constraint type");
 -               constraint_type = NULL; /* keep compiler quiet */
 -           }
 +               eq_strategy = BTEqualStrategyNumber;
 +
 +           ptkey_eqop = get_opfamily_member(key->partopfamily[i],
 +                                            key->partopcintype[i],
 +                                            key->partopcintype[i],
 +                                            eq_strategy);
 +           if (!OidIsValid(ptkey_eqop))
 +               elog(ERROR, "missing operator %d(%u,%u) in partition opfamily %u",
 +                    eq_strategy, key->partopcintype[i], key->partopcintype[i],
 +                    key->partopfamily[i]);
 +
 +           /*
 +            * We'll need to be able to identify the equality operators
 +            * associated with index columns, too.  We know what to do with
 +            * btree opclasses; if there are ever any other index types that
 +            * support unique indexes, this logic will need extension.
 +            */
 +           if (accessMethodId == BTREE_AM_OID)
 +               eq_strategy = BTEqualStrategyNumber;
 +           else
 +               ereport(ERROR,
 +                       (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
 +                        errmsg("cannot match partition key to an index using access method \"%s\"",
 +                               accessMethodName)));
  
             /*
              * It may be possible to support UNIQUE constraints when partition
                           errdetail("%s constraints cannot be used when partition keys include expressions.",
                                    constraint_type)));
  
 +           /* Search the index column(s) for a match */
             for (j = 0; j < indexInfo->ii_NumIndexKeyAttrs; j++)
             {
                 if (key->partattrs[i] == indexInfo->ii_IndexAttrNumbers[j])
                 {
 -                   found = true;
 -                   break;
 +                   /* Matched the column, now what about the equality op? */
 +                   Oid         idx_opfamily;
 +                   Oid         idx_opcintype;
 +
 +                   if (get_opclass_opfamily_and_input_type(classObjectId[j],
 +                                                           &idx_opfamily,
 +                                                           &idx_opcintype))
 +                   {
 +                       Oid         idx_eqop;
 +
 +                       idx_eqop = get_opfamily_member(idx_opfamily,
 +                                                      idx_opcintype,
 +                                                      idx_opcintype,
 +                                                      eq_strategy);
 +                       if (ptkey_eqop == idx_eqop)
 +                       {
 +                           found = true;
 +                           break;
 +                       }
 +                   }
                 }
             }
 +
             if (!found)
             {
                 Form_pg_attribute att;
  
 -               att = TupleDescAttr(RelationGetDescr(rel), key->partattrs[i] - 1);
 +               att = TupleDescAttr(RelationGetDescr(rel),
 +                                   key->partattrs[i] - 1);
                 ereport(ERROR,
                         (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
                          errmsg("insufficient columns in %s constraint definition",