Opened 15 years ago

Closed 15 years ago

Last modified 13 years ago

#13432 closed (fixed)

OneToOneField between two databases fails

Reported by: Benjamin Wohlwend Owned by: nobody
Component: Database layer (models, ORM) Version: dev
Severity: Keywords: multidb
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

When model A is in the default database and model B is in another database, and there is a OneToOne relation between the two models, the lookup fails (raising a DoesNotExist, or if the tables aren't in both databases, a ProgrammingError). Writing works, only reading fails. I have no idea of the ORM internals, so I might be completely wrong, but I think the cause is a simple copy&paste error. Fix and test is in the patch.

Attachments (1)

one_to_one_multidb.diff (2.4 KB ) - added by Benjamin Wohlwend 15 years ago.

Download all attachments as: .zip

Change History (4)

by Benjamin Wohlwend, 15 years ago

Attachment: one_to_one_multidb.diff added

comment:1 by Russell Keith-Magee, 15 years ago

Triage Stage: UnreviewedAccepted

This is a case of being technically correct, for the wrong reason.

You are correct that self.related.model is technically the right argument to pass in. However, it doesn't make a huge difference in practice, because self.related.model and instance.class must route to compatible databases (i.e., you must be able to find objects of both types on the same database). If there is a relationship between the two objects, they must be on databases that allow joins.

In the example you give, the two models are on different databases - which would be prohibited on any database that honors referential integrity. Your example should have an "allows_join" method that prohibits cross-database joins, which would prohibit the creation of the UserProfile instance in the first place.

There are cases where you will be able to get away with the type of router you describe - if you use MySQL/MyISAM or SQLite, and you don't ever issue a User.objects.filter(userprofile__flavor='foo') query, for instance; but in general I would advise against this unless you have really thought through the consequences.

There is an edge case where model-based load balancing behavior might cause this issue to be observed, but only in the sense that queries would be directed to the wrong slave (answers wouldn't be wrong, just served by the wrong database), so the problem is still worth solving. I'll also use this as an opportunity to add some tests for o2o relations, which weren't fully tested previously.

comment:2 by Russell Keith-Magee, 15 years ago

Resolution: fixed
Status: newclosed

(In [13037]) Fixed #13432 -- Corrected the logic for router use on OneToOne? fields; also added a bunch of tests for OneToOneField? queries. Thanks to piquadrat for the report.

comment:3 by Jacob, 13 years ago

milestone: 1.2

Milestone 1.2 deleted

Note: See TracTickets for help on using tickets.
Back to Top