Allow non-btree unique indexes for matviews
authorPeter Eisentraut <peter@eisentraut.org>
Tue, 18 Mar 2025 10:29:15 +0000 (11:29 +0100)
committerPeter Eisentraut <peter@eisentraut.org>
Tue, 18 Mar 2025 10:29:15 +0000 (11:29 +0100)
We were rejecting non-btree indexes in some cases owing to the
inability to determine the equality operators for other index AMs;
that problem no longer exists, because we can look up the equality
operator using COMPARE_EQ.

Stop rejecting these indexes, but instead rely on all unique indexes
having equality operators.  Unique indexes must have equality
operators.

Author: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com

src/backend/commands/matview.c

index 0bfbc5ca6dc82cc67c92e0caecb02686ebb49ac1..e7854add17825b41bd56c8e7a421d1e968488f93 100644 (file)
@@ -774,16 +774,14 @@ refresh_by_match_merge(Oid matviewOid, Oid tempOid, Oid relowner,
                if (!HeapTupleIsValid(cla_ht))
                    elog(ERROR, "cache lookup failed for opclass %u", opclass);
                cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht);
-               Assert(cla_tup->opcmethod == BTREE_AM_OID);
                opfamily = cla_tup->opcfamily;
                opcintype = cla_tup->opcintype;
                ReleaseSysCache(cla_ht);
 
-               op = get_opfamily_member(opfamily, opcintype, opcintype,
-                                        BTEqualStrategyNumber);
+               op = get_opfamily_member_for_cmptype(opfamily, opcintype, opcintype, COMPARE_EQ);
                if (!OidIsValid(op))
-                   elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
-                        BTEqualStrategyNumber, opcintype, opcintype, opfamily);
+                   elog(ERROR, "missing equality operator for (%u,%u) in opfamily %u",
+                        opcintype, opcintype, opfamily);
 
                /*
                 * If we find the same column with the same equality semantics
@@ -920,15 +918,10 @@ is_usable_unique_index(Relation indexRel)
 
    /*
     * Must be unique, valid, immediate, non-partial, and be defined over
-    * plain user columns (not expressions).  We also require it to be a
-    * btree.  Even if we had any other unique index kinds, we'd not know how
-    * to identify the corresponding equality operator, nor could we be sure
-    * that the planner could implement the required FULL JOIN with non-btree
-    * operators.
+    * plain user columns (not expressions).
     */
    if (indexStruct->indisunique &&
        indexStruct->indimmediate &&
-       indexRel->rd_rel->relam == BTREE_AM_OID &&
        indexStruct->indisvalid &&
        RelationGetIndexPredicate(indexRel) == NIL &&
        indexStruct->indnatts > 0)