Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit bfe21b7

Browse files
peteremarkdilger
andcommitted
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 c09e5a6), 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
1 parent 83ea6c5 commit bfe21b7

File tree

1 file changed

+23
-34
lines changed

1 file changed

+23
-34
lines changed

src/backend/commands/tablecmds.c

Lines changed: 23 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -10082,6 +10082,8 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1008210082
Oid amid;
1008310083
Oid opfamily;
1008410084
Oid opcintype;
10085+
bool for_overlaps;
10086+
CompareType cmptype;
1008510087
Oid pfeqop;
1008610088
Oid ppeqop;
1008710089
Oid ffeqop;
@@ -10098,40 +10100,27 @@ ATAddForeignKeyConstraint(List **wqueue, AlteredTableInfo *tab, Relation rel,
1009810100
opcintype = cla_tup->opcintype;
1009910101
ReleaseSysCache(cla_ht);
1010010102

10101-
if (with_period)
10102-
{
10103-
CompareType cmptype;
10104-
bool for_overlaps = with_period && i == numpks - 1;
10105-
10106-
cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
10107-
10108-
/*
10109-
* An index AM can use whatever strategy numbers it wants, so we
10110-
* ask it what number it actually uses.
10111-
*/
10112-
eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
10113-
if (eqstrategy == InvalidStrategy)
10114-
ereport(ERROR,
10115-
errcode(ERRCODE_UNDEFINED_OBJECT),
10116-
for_overlaps
10117-
? errmsg("could not identify an overlaps operator for foreign key")
10118-
: errmsg("could not identify an equality operator for foreign key"),
10119-
errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
10120-
cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
10121-
}
10122-
else
10123-
{
10124-
/*
10125-
* Check it's a btree; currently this can never fail since no
10126-
* other index AMs support unique indexes. If we ever did have
10127-
* other types of unique indexes, we'd need a way to determine
10128-
* which operator strategy number is equality. (We could use
10129-
* IndexAmTranslateCompareType.)
10130-
*/
10131-
if (amid != BTREE_AM_OID)
10132-
elog(ERROR, "only b-tree indexes are supported for foreign keys");
10133-
eqstrategy = BTEqualStrategyNumber;
10134-
}
10103+
/*
10104+
* Get strategy number from index AM.
10105+
*
10106+
* For a normal foreign-key constraint, this should not fail, since we
10107+
* already checked that the index is unique and should therefore have
10108+
* appropriate equal operators. For a period foreign key, this could
10109+
* fail if we selected a non-matching exclusion constraint earlier.
10110+
* (XXX Maybe we should do these lookups earlier so we don't end up
10111+
* doing that.)
10112+
*/
10113+
for_overlaps = with_period && i == numpks - 1;
10114+
cmptype = for_overlaps ? COMPARE_OVERLAP : COMPARE_EQ;
10115+
eqstrategy = IndexAmTranslateCompareType(cmptype, amid, opfamily, opcintype, true);
10116+
if (eqstrategy == InvalidStrategy)
10117+
ereport(ERROR,
10118+
errcode(ERRCODE_UNDEFINED_OBJECT),
10119+
for_overlaps
10120+
? errmsg("could not identify an overlaps operator for foreign key")
10121+
: errmsg("could not identify an equality operator for foreign key"),
10122+
errdetail("Could not translate compare type %d for operator family \"%s\", input type %s, access method \"%s\".",
10123+
cmptype, get_opfamily_name(opfamily, false), format_type_be(opcintype), get_am_name(amid)));
1013510124

1013610125
/*
1013710126
* There had better be a primary equality operator for the index.

0 commit comments

Comments
 (0)