@@ -712,11 +712,6 @@ DefineIndex(Oid relationId,
712712 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
713713 errmsg ("cannot create index on partitioned table \"%s\" concurrently" ,
714714 RelationGetRelationName (rel ))));
715- if (stmt -> excludeOpNames )
716- ereport (ERROR ,
717- (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
718- errmsg ("cannot create exclusion constraints on partitioned table \"%s\"" ,
719- RelationGetRelationName (rel ))));
720715 }
721716
722717 /*
@@ -923,15 +918,16 @@ DefineIndex(Oid relationId,
923918 index_check_primary_key (rel , indexInfo , is_alter_table , stmt );
924919
925920 /*
926- * If this table is partitioned and we're creating a unique index or a
927- * primary key, make sure that the partition key is a subset of the
928- * index's columns. Otherwise it would be possible to violate uniqueness
929- * by putting values that ought to be unique in different partitions.
921+ * If this table is partitioned and we're creating a unique index, primary
922+ * key, or exclusion constraint, make sure that the partition key is a
923+ * subset of the index's columns. Otherwise it would be possible to
924+ * violate uniqueness by putting values that ought to be unique in
925+ * different partitions.
930926 *
931927 * We could lift this limitation if we had global indexes, but those have
932928 * their own problems, so this is a useful feature combination.
933929 */
934- if (partitioned && (stmt -> unique || stmt -> primary ))
930+ if (partitioned && (stmt -> unique || stmt -> excludeOpNames ))
935931 {
936932 PartitionKey key = RelationGetPartitionKey (rel );
937933 const char * constraint_type ;
@@ -941,7 +937,7 @@ DefineIndex(Oid relationId,
941937 constraint_type = "PRIMARY KEY" ;
942938 else if (stmt -> unique )
943939 constraint_type = "UNIQUE" ;
944- else if (stmt -> excludeOpNames != NIL )
940+ else if (stmt -> excludeOpNames )
945941 constraint_type = "EXCLUDE" ;
946942 else
947943 {
@@ -984,11 +980,11 @@ DefineIndex(Oid relationId,
984980 * We'll need to be able to identify the equality operators
985981 * associated with index columns, too. We know what to do with
986982 * btree opclasses; if there are ever any other index types that
987- * support unique indexes, this logic will need extension.
983+ * support unique indexes, this logic will need extension. But if
984+ * we have an exclusion constraint, it already knows the
985+ * operators, so we don't have to infer them.
988986 */
989- if (accessMethodId == BTREE_AM_OID )
990- eq_strategy = BTEqualStrategyNumber ;
991- else
987+ if (stmt -> unique && accessMethodId != BTREE_AM_OID )
992988 ereport (ERROR ,
993989 (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
994990 errmsg ("cannot match partition key to an index using access method \"%s\"" ,
@@ -1019,17 +1015,38 @@ DefineIndex(Oid relationId,
10191015 & idx_opfamily ,
10201016 & idx_opcintype ))
10211017 {
1022- Oid idx_eqop ;
1018+ Oid idx_eqop = InvalidOid ;
1019+
1020+ if (stmt -> unique )
1021+ idx_eqop = get_opfamily_member (idx_opfamily ,
1022+ idx_opcintype ,
1023+ idx_opcintype ,
1024+ BTEqualStrategyNumber );
1025+ else if (stmt -> excludeOpNames )
1026+ idx_eqop = indexInfo -> ii_ExclusionOps [j ];
1027+ Assert (idx_eqop );
10231028
1024- idx_eqop = get_opfamily_member (idx_opfamily ,
1025- idx_opcintype ,
1026- idx_opcintype ,
1027- eq_strategy );
10281029 if (ptkey_eqop == idx_eqop )
10291030 {
10301031 found = true;
10311032 break ;
10321033 }
1034+ else if (stmt -> excludeOpNames )
1035+ {
1036+ /*
1037+ * We found a match, but it's not an equality
1038+ * operator. Instead of failing below with an
1039+ * error message about a missing column, fail now
1040+ * and explain that the operator is wrong.
1041+ */
1042+ Form_pg_attribute att = TupleDescAttr (RelationGetDescr (rel ), key -> partattrs [i ] - 1 );
1043+
1044+ ereport (ERROR ,
1045+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
1046+ errmsg ("cannot match partition key to index on column \"%s\" using non-equal operator \"%s\"" ,
1047+ NameStr (att -> attname ),
1048+ get_opname (indexInfo -> ii_ExclusionOps [j ]))));
1049+ }
10331050 }
10341051 }
10351052 }
@@ -1101,7 +1118,7 @@ DefineIndex(Oid relationId,
11011118 constraint_type = "PRIMARY KEY" ;
11021119 else if (stmt -> unique )
11031120 constraint_type = "UNIQUE" ;
1104- else if (stmt -> excludeOpNames != NIL )
1121+ else if (stmt -> excludeOpNames )
11051122 constraint_type = "EXCLUDE" ;
11061123 else
11071124 {
0 commit comments