1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

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
c09e5a6a01), 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.

Co-authored-by: Mark Dilger <mark.dilger@enterprisedb.com>
Discussion: https://www.postgresql.org/message-id/flat/E72EAA49-354D-4C2E-8EB9-255197F55330@enterprisedb.com
This commit is contained in:
Peter Eisentraut
2025-02-07 11:17:25 +01:00
parent 83ea6c5402
commit bfe21b760e

View File

@ -10082,6 +10082,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
Oid amid; Oid amid;
Oid opfamily; Oid opfamily;
Oid opcintype; Oid opcintype;
bool for_overlaps;
CompareType cmptype;
Oid pfeqop; Oid pfeqop;
Oid ppeqop; Oid ppeqop;
Oid ffeqop; Oid ffeqop;
@ -10098,40 +10100,27 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
opcintype = cla_tup->opcintype; opcintype = cla_tup->opcintype;
ReleaseSysCache(cla_ht); ReleaseSysCache(cla_ht);
if (with_period) /*
{ * Get strategy number from index AM.
CompareType cmptype; *
bool for_overlaps = with_period && i == numpks - 1; * For a normal foreign-key constraint, this should not fail, since we
* already checked that the index is unique and should therefore have
cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ; * 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
* An index AM can use whatever strategy numbers it wants, so we * doing that.)
* ask it what number it actually uses. */
*/ for_overlaps = with_period && i == numpks - 1;
eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true); cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
if (eqstrategy == InvalidStrategy) eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
ereport(ERROR, if (eqstrategy == InvalidStrategy)
errcode(ERRCODE_UNDEFINED_OBJECT), ereport(ERROR,
for_overlaps errcode(ERRCODE_UNDEFINED_OBJECT),
? errmsg("could not identify an overlaps operator for foreign key") for_overlaps
: errmsg("could not identify an equality operator for foreign key"), ? errmsg("could not identify an overlaps operator for foreign key")
errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".", : errmsg("could not identify an equality operator for foreign key"),
cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid))); 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;
}
/* /*
* There had better be a primary equality operator for the index. * There had better be a primary equality operator for the index.