8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -3943,11 +3943,10 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
3943
3943
/*
3944
3944
* Look up the equality operators to use in the constraint.
3945
3945
*
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.
3951
3950
*/
3952
3951
if (numfks != numpks )
3953
3952
ereport (ERROR ,
@@ -3956,12 +3955,14 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
3956
3955
3957
3956
for (i = 0 ; i < numpks ; i ++ )
3958
3957
{
3958
+ Oid pktype = pktypoid [i ];
3959
+ Oid fktype = fktypoid [i ];
3960
+ Oid fktyped ;
3959
3961
HeapTuple cla_ht ;
3960
3962
Form_pg_opclass cla_tup ;
3961
3963
Oid amid ;
3962
3964
Oid opfamily ;
3963
- Oid pktype ;
3964
- Oid fktype ;
3965
+ Oid opcintype ;
3965
3966
Oid pfeqop ;
3966
3967
Oid ppeqop ;
3967
3968
Oid ffeqop ;
@@ -3976,7 +3977,7 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
3976
3977
cla_tup = (Form_pg_opclass ) GETSTRUCT (cla_ht );
3977
3978
amid = cla_tup -> opcmethod ;
3978
3979
opfamily = cla_tup -> opcfamily ;
3979
- pktype = cla_tup -> opcintype ;
3980
+ opcintype = cla_tup -> opcintype ;
3980
3981
ReleaseSysCache (cla_ht );
3981
3982
3982
3983
/*
@@ -3991,30 +3992,50 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
3991
3992
eqstrategy = BTEqualStrategyNumber ;
3992
3993
3993
3994
/*
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.
3995
3997
*/
3996
- ppeqop = get_opfamily_member (opfamily , pktype , pktype , eqstrategy );
3998
+ ppeqop = get_opfamily_member (opfamily , opcintype , opcintype ,
3999
+ eqstrategy );
3997
4000
3998
4001
if (!OidIsValid (ppeqop ))
3999
4002
elog (ERROR , "missing operator %d(%u,%u) in opfamily %u" ,
4000
- eqstrategy , pktype , pktype , opfamily );
4003
+ eqstrategy , opcintype , opcintype , opfamily );
4001
4004
4002
4005
/*
4003
4006
* Are there equality operators that take exactly the FK type?
4004
4007
* Assume we should look through any domain here.
4005
4008
*/
4006
- fktype = getBaseType (fktypoid [ i ] );
4009
+ fktyped = getBaseType (fktype );
4007
4010
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 */
4010
4018
4011
4019
if (!(OidIsValid (pfeqop ) && OidIsValid (ffeqop )))
4012
4020
{
4013
4021
/*
4014
4022
* 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[].)
4016
4029
*/
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 ))
4018
4039
pfeqop = ffeqop = ppeqop ;
4019
4040
}
4020
4041
@@ -4028,8 +4049,8 @@ ATAddForeignKeyConstraint(AlteredTableInfo *tab, Relation rel,
4028
4049
"are of incompatible types: %s and %s." ,
4029
4050
strVal (list_nth (fkconstraint -> fk_attrs , i )),
4030
4051
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 ))));
4033
4054
4034
4055
pfeqoperators [i ] = pfeqop ;
4035
4056
ppeqoperators [i ] = ppeqop ;
0 commit comments