On Tuesday, June 28, 2016 at 2:57:08 PM UTC+1, Mike Bayer wrote:
>
>
>
> On 06/28/2016 05:28 AM, mic...@healx3.com <javascript:> wrote: 
> > Hello! I sometimes find it more convenient to create to construct a 
> > query without a session, and then to add the session at the end using 
> > `with_session`. In particular, when constructing non-trivial queries, 
> > not having to pass the session around means one less argument to manage. 
> > However, this doesn't seem to work when using subquery loading, 
> > resulting in the error `AssertionError: Subquery session doesn't refer 
> > to that of our context. Are there broken context caching schemes being 
> > used?`. 
> > 
> > Is there a sensible way to get the subqueries to use the same session, 
> > or is the answer just to always construct queries with the session? 
>
>
> that assertion only applies to when the internal QueryContext is being 
> re-used, as is the case with baked query loading.  The QueryContext 
> itself created during the _compile_context() phase will contain 
> references to the Session within the subquery eager loaders.   As long 
> as you don't do anything with your original query other than call 
> with_session(), there's no error I can reproduce, e.g.: 
>
> from sqlalchemy import * 
> from sqlalchemy.orm import * 
> from sqlalchemy.ext.declarative import declarative_base 
>
> Base = declarative_base() 
>
>
> class A(Base): 
>      __tablename__ = 'a' 
>      id = Column(Integer, primary_key=True) 
>      bs = relationship("B") 
>
> class B(Base): 
>      __tablename__ = 'b' 
>      id = Column(Integer, primary_key=True) 
>      a_id = Column(ForeignKey('a.id')) 
>
> e = create_engine("sqlite://", echo=True) 
> Base.metadata.create_all(e) 
>
> s = Session(e) 
> s.add_all([A(bs=[B(), B()]), A(bs=[B(), B()])]) 
> s.commit() 
>
> q1 = Session().query(A).options(subqueryload(A.bs)) 
>
> for sess in [Session(e), Session(e), Session(e)]: 
>      for a in q1.with_session(sess): 
>          print a, a.bs 
>
>
>
> Please work up an example showing how you're getting that result, thanks! 
>
>
Thanks for the quick reply, and apologies for not providing an example in 
the first place. I think I worked out the issue: we've wrapped up the 
session:

class TransactionalSession(object):
    def __init__(self, session):
        self._session = session

    def __enter__(self):
        return self

    def __exit__(self, exception_type, exception, traceback):
        if exception is None:
            self._session.commit()
        else:
            self._session.rollback()
        self._session.close()

    def __getattr__(self, key):
        return getattr(self._session, key)

so when we try running the queries with subquery loading (for instance, as 
in your example, but with `TransactionalSession(Session(e))`), the session 
on `subq` is the underlying session, while the session on `context` is our 
own wrapped session. So, presumably the saner way of doing this would be 
either to use the underlying session directly, or to subclass `Session`?

 

>
>
> > 
> > Thanks 
> > 
> > Michael 
> > 
> > -- 
> > You received this message because you are subscribed to the Google 
> > Groups "sqlalchemy" group. 
> > To unsubscribe from this group and stop receiving emails from it, send 
> > an email to sqlalchemy+...@googlegroups.com <javascript:> 
> > <mailto:sqlalchemy+unsubscr...@googlegroups.com <javascript:>>. 
> > To post to this group, send email to sqlal...@googlegroups.com 
> <javascript:> 
> > <mailto:sqlal...@googlegroups.com <javascript:>>. 
> > Visit this group at https://groups.google.com/group/sqlalchemy. 
> > For more options, visit https://groups.google.com/d/optout. 
>

-- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to sqlalchemy+unsubscr...@googlegroups.com.
To post to this group, send email to sqlalchemy@googlegroups.com.
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to