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

Commit 9f28ac0

Browse files
committed
Fix new RI operator selection code to do the right thing when working with
an opclass for a generic type such as ANYARRAY. The original coding failed to check that PK and FK columns were of the same array type. Per discussion with Tom Dunstan. Also, make the code a shade more readable by not trying to economize on variables.
1 parent 1d722cf commit 9f28ac0

File tree

1 file changed

+40
-19
lines changed

1 file changed

+40
-19
lines changed

src/backend/commands/tablecmds.c

Lines changed: 40 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.214 2007/02/14 01:58:56 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.215 2007/02/16 22:04:02 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -3943,11 +3943,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
39433943
/*
39443944
* Look up the equality operators to use in the constraint.
39453945
*
3946-
* Note that we look for operator(s) with the PK type on the left; when
3947-
* the types are different this is the right choice because the PK index
3948-
* will need operators with the indexkey on the left. Also, we take the
3949-
* PK type as being the declared input type of the opclass, which might be
3950-
* binary-compatible but not identical to the PK column type.
3946+
* Note that we have to be careful about the difference between the actual
3947+
* PK column type and the opclass' declared input type, which might be
3948+
* only binary-compatible with it. The declared opcintype is the right
3949+
* thing to probe pg_amop with.
39513950
*/
39523951
if (numfks != numpks)
39533952
ereport(ERROR,
@@ -3956,12 +3955,14 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
39563955

39573956
for (i = 0; i < numpks; i++)
39583957
{
3958+
Oid pktype = pktypoid[i];
3959+
Oid fktype = fktypoid[i];
3960+
Oid fktyped;
39593961
HeapTuple cla_ht;
39603962
Form_pg_opclass cla_tup;
39613963
Oid amid;
39623964
Oid opfamily;
3963-
Oid pktype;
3964-
Oid fktype;
3965+
Oid opcintype;
39653966
Oid pfeqop;
39663967
Oid ppeqop;
39673968
Oid ffeqop;
@@ -3976,7 +3977,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
39763977
cla_tup = (Form_pg_opclass) GETSTRUCT(cla_ht);
39773978
amid = cla_tup->opcmethod;
39783979
opfamily = cla_tup->opcfamily;
3979-
pktype = cla_tup->opcintype;
3980+
opcintype = cla_tup->opcintype;
39803981
ReleaseSysCache(cla_ht);
39813982

39823983
/*
@@ -3991,30 +3992,50 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
39913992
eqstrategy = BTEqualStrategyNumber;
39923993

39933994
/*
3994-
* There had better be a PK = PK operator for the index.
3995+
* There had better be a primary equality operator for the index.
3996+
* We'll use it for PK = PK comparisons.
39953997
*/
3996-
ppeqop = get_opfamily_member(opfamily, pktype, pktype, eqstrategy);
3998+
ppeqop = get_opfamily_member(opfamily, opcintype, opcintype,
3999+
eqstrategy);
39974000

39984001
if (!OidIsValid(ppeqop))
39994002
elog(ERROR, "missing operator %d(%u,%u) in opfamily %u",
4000-
eqstrategy, pktype, pktype, opfamily);
4003+
eqstrategy, opcintype, opcintype, opfamily);
40014004

40024005
/*
40034006
* Are there equality operators that take exactly the FK type?
40044007
* Assume we should look through any domain here.
40054008
*/
4006-
fktype = getBaseType(fktypoid[i]);
4009+
fktyped = getBaseType(fktype);
40074010

4008-
pfeqop = get_opfamily_member(opfamily, pktype, fktype, eqstrategy);
4009-
ffeqop = get_opfamily_member(opfamily, fktype, fktype, eqstrategy);
4011+
pfeqop = get_opfamily_member(opfamily, opcintype, fktyped,
4012+
eqstrategy);
4013+
if (OidIsValid(pfeqop))
4014+
ffeqop = get_opfamily_member(opfamily, fktyped, fktyped,
4015+
eqstrategy);
4016+
else
4017+
ffeqop = InvalidOid; /* keep compiler quiet */
40104018

40114019
if (!(OidIsValid(pfeqop) && OidIsValid(ffeqop)))
40124020
{
40134021
/*
40144022
* Otherwise, look for an implicit cast from the FK type to
4015-
* the PK type, and if found, use the PK type's equality operator.
4023+
* the opcintype, and if found, use the primary equality operator.
4024+
* This is a bit tricky because opcintype might be a generic type
4025+
* such as ANYARRAY, and so what we have to test is whether the
4026+
* two actual column types can be concurrently cast to that type.
4027+
* (Otherwise, we'd fail to reject combinations such as int[] and
4028+
* point[].)
40164029
*/
4017-
if (can_coerce_type(1, &fktype, &pktype, COERCION_IMPLICIT))
4030+
Oid input_typeids[2];
4031+
Oid target_typeids[2];
4032+
4033+
input_typeids[0] = pktype;
4034+
input_typeids[1] = fktype;
4035+
target_typeids[0] = opcintype;
4036+
target_typeids[1] = opcintype;
4037+
if (can_coerce_type(2, input_typeids, target_typeids,
4038+
COERCION_IMPLICIT))
40184039
pfeqop = ffeqop = ppeqop;
40194040
}
40204041

@@ -4028,8 +4049,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
40284049
"are of incompatible types: %s and %s.",
40294050
strVal(list_nth(fkconstraint->fk_attrs, i)),
40304051
strVal(list_nth(fkconstraint->pk_attrs, i)),
4031-
format_type_be(fktypoid[i]),
4032-
format_type_be(pktypoid[i]))));
4052+
format_type_be(fktype),
4053+
format_type_be(pktype))));
40334054

40344055
pfeqoperators[i] = pfeqop;
40354056
ppeqoperators[i] = ppeqop;

0 commit comments

Comments
 (0)