Update.
Te unwrap version works only if the original result of q.all() is kept around:
def test_access(self):
q = self.session.query(Foo, Bar).with_labels()
q = q.filter(Foo.bar_id == Bar.id)
# Only this combination works:
_rows = q.all()
rows = unwrap(_rows)
assert len(rows) > 0
with self.assert_no_sql_while():
for each in rows:
each.bar.data
I have also rewritten unwrap to:
def unwrap(items):
def f(each):
if isinstance(each, tuple) and len(each) > 0:
return each[0]
else:
return each
return map(f, items)
because it is now completely useless as a generator.
I am completely lost now. Does this have to do something with weak references
and too eager garbage collection? I would expect that if a query fetches some
objects, session will keep them all until explicitly removed from it to
eliminate successive SQL queries.
Ladislav Lenart
On 27.9.2012 20:31, Ladislav Lenart wrote:
> Hello.
>
>> not sure, is "each.bar" a typo and you meant "_each_bar" ?
>
> No, I mean each.bar.
>
>
>> or are you trying to fetch a relationship along Foo-> Bar ? if its a
> relationship and the linkage is not a simple many-to-one, then it emits SQL.
>
> Yes, I am trying to fetch Foo -> Bar relationship. It is a one-way many-to-one
> relationship: Foo has bar_id FK to bar (id).
>
>
> I still don't understand what I see, but I figured out the cause.
>
> This works:
>
> def test_access_ok(self):
> q = self.session.query(Foo, Bar).with_labels()
> q = q.filter(Foo.bar_id == Bar.id)
> rows = q.all() # IMPORTANT LINE
> assert len(rows) > 0
> with self.assert_no_sql_while():
> for (each_foo, _each_bar) in rows:
> each.bar.data
>
> This does not:
>
> def test_access_ko(self):
> q = self.session.query(Foo, Bar).with_labels()
> q = q.filter(Foo.bar_id == Bar.id)
> rows = list(unwrap(q)) # IMPORTANT LINE
> assert len(rows) > 0
> with self.assert_no_sql_while():
> for each in rows:
> each.bar.data # <-- FAILS HERE
>
> unwrap is defined as
>
> def unwrap(query):
> for each in query:
> if isinstance(each, tuple) and len(each) > 0:
> yield each[0]
> else:
> yield each
>
> I wanted to use unwrap to minimize the impact of the queries I have to modify
> slightly to overcome SA 0.7 limitation of of_type() in combination with a
> table
> inheritance (we spoke about this in another thread). To make SA fetch
> everything
> I need, the query must return more results (tuples of instances instead of the
> instances directly), so I can joinedload from them too. With unwrap in place,
> the rest of the query processing can remain intact.
>
> Do you have any idea why the unwrap version does not work?
>
> Thank you,
>
> Ladislav Lenart
>
>
> On 27.9.2012 20:06, Michael Bayer wrote:
>>
>> On Sep 27, 2012, at 1:55 PM, Ladislav Lenart wrote:
>>
>>> Hello again.
>>>
>>> I have the following test query:
>>>
>>> def test_slot_access_after_query(self):
>>> q = self.session.query(Foo, Bar).with_labels()
>>> q = q.filter(Foo.bar_id == Bar.id)
>>> rows = q.all()
>>> assert len(rows) > 0
>>> with self.assert_no_sql_while():
>>> for (each_foo, _each_bar) in rows:
>>> each.bar.data # <-- FAILS HERE
>>>
>>> SQLAlchemy emits SQL to fetch each.bar's data. I do not understand why. I
>>> expected that:
>>> * Bar is already cached in the session.
>>> * each.bar first checks if a bar with the appropriate id is present in the
>>> session and if so, return it.
>>>
>>> What am I doing wrong?
>>
>> not sure, is "each.bar" a typo and you meant "_each_bar" ? or are you
>> trying to fetch a relationship along Foo-> Bar ? if its a relationship and
>> the linkage is not a simple many-to-one, then it emits SQL.
>>
>>
>
>
--
You received this message because you are subscribed to the Google Groups
"sqlalchemy" group.
To post to this group, send email to [email protected].
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.