> > Thanks a lot for the tips on how to approach this problem. That's
> > exactly what I needed.
>
> in 0.4 you'd get it off the impl (0.5 too, this is just uglier API):

Excellent! Here's what I came up with as an initial solution:

def poly_load(parent, collection, path):
    def itersiblings(parent, path):
        def iteritems(items, attr):
            for item in items:
                for child in getattr(item, attr):
                    yield child
        items = [parent]
        while path:
            items = iteritems(items, path.pop(0))
        return items
    path = path.split(".")
    assert len(path) % 2 == 0, "path must contain an even number of
elements"
    mid = len(path) / 2
    gparent = parent
    for attr in path[:mid]:
        gparent = getattr(gparent, attr)
    session = sqlalchemy.orm.session.object_session(parent)
    backref = getattr(type(parent), collection).property.backref.key
    itemclass = getattr(type(parent),
collection).property.mapper.class_
    qry = session.query(itemclass) \
        .join([backref] + path[:mid]) \
        .filter(type(gparent).table.c.id == gparent.id)
    groups = defaultdict(list)
    for item in qry:
        groups[getattr(item, backref).id].append(item)
    impl = getattr(type(parent), collection).impl
    for sibling in itersiblings(gparent, path[mid:]):
        if sibling.id in groups:
            impl.set_committed_value(sibling._state, groups.get
(sibling.id))

Example usage:

# prepare for takeoff
order = session.get(Order, 123)
item = order.items[0] # triggers lazy load

# sit back and watch the fireworks!

poly_load(item, "attributes", "order.items")
# BOOM loaded all attributes of all items

poly_load(item, "tags", "order.items")
# BOOM loaded all tags of all items

poly_load(item.tags[0], "bars", "item.order.items.tags")
# BOOOM loaded all bars of all tags of all items

Some assumptions I was able to make that kept it simple:
- All mapped classes in my model have a 'table' attribute
- All entities in my model have an 'id' attribute, which is the
primary key.
- Relationships traversed by this loader are configured with the
necessary backrefs to make it work.

Initial tests seem to show a DRAMATIC performance improvement. Thanks
a lot for your help Mike.

Next up, roll this into a loader strategy so I can configure it on the
mapper and have it all happen automatically.

~ Daniel
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to 
sqlalchemy+unsubscr...@googlegroups.com
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to