On 03.02.25 12:08, Peter Eisentraut wrote:
Yeah, actually this turned out to be unnecessary, because you can easily obtain the AM OID from the passed-in opclass ID.  So I have fixed it that way.  I have committed this whole patch set now with the mentioned adjustments.  I'll post a rebased version of the main patch set soon.

I picked off two more patches from the full patch series that can be dealt with easily. These are

- Support non-btree indexes for foreign keys
- Allow non-btree speculative insertion indexes

(v19-0012 and v19-0013)

The version of these patches that were posted in the v19 bundle replaced the hardcoded comparison with BTREE_AM_OID by a check against (indirectly) amcanunique. But I think that is not necessary, because at that point we already know that we are dealing with a unique index. The reason for the check against BTREE_AM_OID was that we didn't have a way to get the right strategy number for other index methods. But now we have, so we can use the strategy translation functions and we don't need to check for btree-ness anymore.

See attached patches.
From aa813425fbef10801bdd9582da09fc3eeaec9bb4 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 4 Feb 2025 11:33:23 +0100
Subject: [PATCH v19.3 1/2] Support non-btree indexes for foreign keys

Previously, only btrees were supported as the referenced unique index
for foreign keys because there was no way to get the equality strategy
number for other index methods.  We have this now (commit
c09e5a6a016), so we can support this.  In fact, this is now just a
special case of the existing generalized "period" foreign key
support, since that already knows how to lookup equality strategy
numbers.

Note that this does not change the requirement that the referenced
index needs to be unique, and at the moment, only btree supports that,
so this does not change anything in practice, but it would allow
another index method that has amcanunique to be supported.
---
 src/backend/commands/tablecmds.c | 57 +++++++++++++-------------------
 1 file changed, 23 insertions(+), 34 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 18f64db6e39..5ea0b77400b 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -9981,6 +9981,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo 
*tab, Relation rel,
                Oid                     amid;
                Oid                     opfamily;
                Oid                     opcintype;
+               bool            for_overlaps;
+               CompareType cmptype;
                Oid                     pfeqop;
                Oid                     ppeqop;
                Oid                     ffeqop;
@@ -9997,40 +9999,27 @@ ATAddForeignKeyConstraint(List **wqueue, 
AlteredTableInfo *tab, Relation rel,
                opcintype = cla_tup->opcintype;
                ReleaseSysCache(cla_ht);
 
-               if (with_period)
-               {
-                       CompareType cmptype;
-                       bool            for_overlaps = with_period && i == 
numpks - 1;
-
-                       cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
-
-                       /*
-                        * An index AM can use whatever strategy numbers it 
wants, so we
-                        * ask it what number it actually uses.
-                        */
-                       eqstrategy = IndexAmTranslateCompareType(cmptype, amid, 
opfamily, opcintype, true);
-                       if (eqstrategy == InvalidStrategy)
-                               ereport(ERROR,
-                                               
errcode(ERRCODE_UNDEFINED_OBJECT),
-                                               for_overlaps
-                                               ? errmsg("could not identify an 
overlaps operator for foreign key")
-                                               : errmsg("could not identify an 
equality operator for foreign key"),
-                                               errdetail("Could not translate 
compare type %d for operator family \"%s\", input type %s, access method 
\"%s\".",
-                                                                 cmptype, 
get_opfamily_name(opfamily, false), format_type_be(opcintype), 
get_am_name(amid)));
-               }
-               else
-               {
-                       /*
-                        * Check it's a btree; currently this can never fail 
since no
-                        * other index AMs support unique indexes.  If we ever 
did have
-                        * other types of unique indexes, we'd need a way to 
determine
-                        * which operator strategy number is equality.  (We 
could use
-                        * IndexAmTranslateCompareType.)
-                        */
-                       if (amid != BTREE_AM_OID)
-                               elog(ERROR, "only b-tree indexes are supported 
for foreign keys");
-                       eqstrategy = BTEqualStrategyNumber;
-               }
+               /*
+                * Get strategy number from index AM.
+                *
+                * For a normal foreign-key constraint, this should not fail, 
since we
+                * already checked that the index is unique and should 
therefore have
+                * appropriate equal operators.  For a period foreign key, this 
could
+                * fail if we selected a non-matching exclusion constraint 
earlier.
+                * (XXX Maybe we should do these lookups earlier so we don't 
end up
+                * doing that.)
+                */
+               for_overlaps = with_period && i == numpks - 1;
+               cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
+               eqstrategy = IndexAmTranslateCompareType(cmptype, amid, 
opfamily, opcintype, true);
+               if (eqstrategy == InvalidStrategy)
+                       ereport(ERROR,
+                                       errcode(ERRCODE_UNDEFINED_OBJECT),
+                                       for_overlaps
+                                       ? errmsg("could not identify an 
overlaps operator for foreign key")
+                                       : errmsg("could not identify an 
equality operator for foreign key"),
+                                       errdetail("Could not translate compare 
type %d for operator family \"%s\", input type %s, access method \"%s\".",
+                                                         cmptype, 
get_opfamily_name(opfamily, false), format_type_be(opcintype), 
get_am_name(amid)));
 
                /*
                 * There had better be a primary equality operator for the 
index.
-- 
2.48.1

From 61352aee28236c64ae1225caf0ef10bce9d58c12 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut <pe...@eisentraut.org>
Date: Tue, 4 Feb 2025 13:54:03 +0100
Subject: [PATCH v19.3 2/2] Allow non-btree speculative insertion indexes

Previously, only btrees were supported as the arbiter index for
speculative insertion because there was no way to get the equality
strategy number for other index methods.  We have this now (commit
c09e5a6a016), so we can support this.

At the moment, only btree supports unique indexes, so this does not
change anything in practice, but it would allow another index method
that has amcanunique to be supported.
---
 src/backend/catalog/index.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 7377912b41e..cdabf780244 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -2677,9 +2677,6 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
         */
        Assert(ii->ii_Unique);
 
-       if (index->rd_rel->relam != BTREE_AM_OID)
-               elog(ERROR, "unexpected non-btree speculative unique index");
-
        ii->ii_UniqueOps = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
        ii->ii_UniqueProcs = (Oid *) palloc(sizeof(Oid) * indnkeyatts);
        ii->ii_UniqueStrats = (uint16 *) palloc(sizeof(uint16) * indnkeyatts);
@@ -2691,7 +2688,12 @@ BuildSpeculativeIndexInfo(Relation index, IndexInfo *ii)
        /* We need the func OIDs and strategy numbers too */
        for (i = 0; i < indnkeyatts; i++)
        {
-               ii->ii_UniqueStrats[i] = BTEqualStrategyNumber;
+               ii->ii_UniqueStrats[i] =
+                       IndexAmTranslateCompareType(COMPARE_EQ,
+                                                                               
index->rd_rel->relam,
+                                                                               
index->rd_opfamily[i],
+                                                                               
index->rd_opcintype[i],
+                                                                               
false);
                ii->ii_UniqueOps[i] =
                        get_opfamily_member(index->rd_opfamily[i],
                                                                
index->rd_opcintype[i],
-- 
2.48.1

Reply via email to