- changed milestone to 0.5.0
eagerload creates a redundant join when the loaded relation is already joined
Issue #863
resolved
(original reporter: ants) Given an Parent has many Child type of schema, there should be a way to query Child, eagerload its parent and filter by the parents attributes without joining the parent table twice. By doing
session.query(Child).options(eagerload('parent')).join('parent').filter_by(name='xyz')
we get SQL like:
SELECT child.id AS child_id, child.parent_id AS child_parent_id, child.name AS child_name, parent_1.id AS parent_1_id, parent_1.name AS parent_1_name
FROM child JOIN parent ON parent.id = child.parent_id LEFT OUTER JOIN parent AS parent_1 ON parent_1.id = child.parent_id
WHERE parent.name = ? ORDER BY child.oid, parent_1.oid
It would be preferrable to have this:
SELECT child.id AS child_id, child.parent_id AS child_parent_id, child.name AS child_name, parent.id AS parent_id, parent.name AS parent_name
FROM child JOIN parent ON parent.id = child.parent_id
WHERE parent.name = ? ORDER BY child.oid, parent.oid
That is, reuse the regular joins that follow exclusively to-one relation paths for eagerloads.
Comments (3)
-
repo owner -
repo owner - changed status to resolved
This use case can be exactly met right now, in both the current 0.4 as well as 0.5, by using the
contains_eager()
option instead of theeagerload()
option. Its an optimization (or even a change the collections actually loaded) that the end user can control completely. -
repo owner - removed milestone
Removing milestone: 0.5.0 (automated comment)
- Log in to comment
I love that you're actually paying attention to these. this one would might be very tricky, as eagerloading would have to carefully look at what the query criterion already includes and perform various second-guessing about it, if it is indeed the same join criterion as what the eager load would use, if theres some aliasing it needs to be aware of, etc. ...the rules for this to work in all cases may be pretty involved. im not inclined to rush into this one too quickly right now :).