Hi list,

The recent work that Michael has done about bringing SelectResults
functionality to Query made me think: what if that allowed me to do
what I've always wanted to have ever since I started using ORMs? The
thing I've wanted to do is to have one-to-many relations that you can
filter when you access them, and it generates the correct query behind
the scene without fetching too many rows from the DB.

So I dived into the code a bit deeper than I had up until now... In
the end, I didn't use the SelectResults stuff at all, but I've managed
to come up with a working patch to do what I wanted anyway. The most
interesting part of it is the addition of a DeferredInstrumentedList
which takes a callable as argument and actually call it only when the
list is accessed.

This allows to do stuff like that:

for address in user.addresses.filter(address_table.c.postcode == 5000):
     print address.street

The patch is quite experimental (I'm pretty sure I broke some stuff).
Also, it only includes a proof-of-concept filter method, but it should
be almost trivial to add things like: limit, offset, order_by,
distinct, list slicing and so on...

And anyway, I'm not sure it's the correct way to go. I _think_ the
best way to go would be if InstrumentedList would hold a
"preconfigured" query object, that you could alter the same way you
can alter the normal query objects, and which would only be executed
when one access the list elements. But to get to this point would need
a major refactoring of the code while what I've done is pretty simple.

I also attach an (Elixir-made) example demonstrating the thing.

Michael, if you are interested in this, I'll gladly translate the
example into a plain SQLAlchemy unittest. And more generally, if there
is anything I can do (within the limits of my knowledge of SQLAlchemy)
to get this done the "correct" way and included into the trunk, please
tell me. I'm so thrilled with this new toy, I hope it'll be possible
to include it ! :)

-- 
Gaƫtan de Menten
http://openhex.org

--~--~---------~--~----~------------~-------~--~----~
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 [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~----------~----~----~----~------~----~------~--~---

Attachment: deferred_list_relation.diff
Description: application/text

from elixir import * 

class A(Entity):
    has_field('name', String(30))
    has_many('b', of_kind='B')

class B(Entity):
    has_field('name', String(30))
    belongs_to('a', of_kind='A')
    has_field('extra', Integer)
    
metadata.connect('sqlite:///')
create_all()

a1 = A(name='a1')
a2 = A(name='a2')
b1 = B(name='b1', a=a1, extra=10)
b2 = B(name='b2', a=a2)
b3 = B(name='b3', a=a1, extra=5)

objectstore.flush()
objectstore.clear()

metadata.engine.echo = True
a = A.get_by(name='a1')
print [b.name for b in a.b.filter(B.c.extra < 6)]

Reply via email to