On Feb 13, 2014, at 12:16 PM, Michael Hipp <[email protected]> wrote:

> On 2/13/2014 11:04 AM, Michael Bayer wrote:
>> On Feb 13, 2014, at 11:53 AM, Michael Hipp <[email protected]> wrote:
>> 
>> I don't see a "first_owner" relationship defined above, so the above example 
>> is not complete. The approach using "foreign_keys" is the correct approach 
>> to resolving ambiguity in join conditions, however. If the documented 
>> approach is not working you'd need to provide a succinct self-contained 
>> example I can run. 
> 
> Sorry, it was tripping over a different error, here's the code with extras 
> removed (I think!):
> 
> class Animal(Base):
>    __tablename__ = 'animals'
>    id_ = Column(Integer, primary_key=True)
> 
>    sire_id = Column(Integer, ForeignKey('animals.id_'))
>    dam_id = Column(Integer, ForeignKey('animals.id_'))
> 
>    sire = relationship('Animal', foreign_keys=[sire_id])
>    dam = relationship('Animal', foreign_keys=[dam_id])
>    children = relationship('Animal', foreign_keys=[sire_id, dam_id])
> 
> Gives:
> sqlalchemy.exc.AmbiguousForeignKeysError: Could not determine join condition 
> between parent/child tables on relationship Animal.children - there are 
> multiple foreign key paths linking the tables. Specify the 'foreign_keys' 
> argument, providing a list of those columns which should be counted as 
> containing a foreign key reference to the parent table.

OK so there’s more subtlety here.  When SQLA makes a “join condition” between 
two tables (or the same table), it looks for essentially a single 
ForeignKeyConstraint object (note that this is distinct from the ForeignKey 
construct used above) with which to create that join.  It never uses multiple 
FKC’s to do so.

So above, each individual ForeignKey() results in the implicit creation of a 
ForeignKeyConstraint object on the “animals” table.  In other cases (not this 
one), multiple columns might be bundled into a single ForeignKeyConstraint, 
when the construct is used explicitly, this is called a composite foreign key 
constraint.    

The “foreign_keys” argument essentially provides a hint to this which says, 
“use the foreign key constraint associated with this column”, but at the moment 
the limitation for “only one FKC can be selected” still applies there (this is 
an odd case).

So for “children” above you need to spell out primaryjoin completely which is 
primaryjoin=“and_(Animal.sire_id == Animal.id_, Animal.dam_id == Animal.id)”.

Attachment: signature.asc
Description: Message signed with OpenPGP using GPGMail

Reply via email to