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 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