Michael Bayer ha scritto: > > On Jan 29, 2007, at 11:30 AM, Manlio Perillo wrote: > >> >> The problem is that sometimes (at random, but I'm not sure), >> SQLAlchemy >> wants to use the lazy loader for comments, when I do session.load >> (Derived). >> > > thats sometimes due to an "eager degrade". eager loading will > generally not issue its LEFT OUTER JOIN if constructing the query > means it will loop back to the originating table in one query...it > will stop at the point before it gets there. this kind of thing > actually happens a lot. this can occur when using backrefs...if you > have A and B with eager refs to each other, and you load an A with > its B's, hitting the "A" collection on each "B" will incur as a lazy > load...since the eager loader isnt going to eager load A->B->A->B->A... > > but im not sure if thats whats happening here. maybe something up > with load(), id guess if the instance is already in the session > maybe. it would help if you could show me more fully what youre doing. > from sqlalchemy import *
Here is (after a month!) the code that reproduces the problem: db = create_engine('postgres://manlio:[EMAIL PROTECTED]/test', echo=True) metadata = BoundMetaData(db) base = Table( 'base', metadata, Column('uid', String, primary_key=True), Column('x', String) ) derived = Table( 'derived', metadata, Column('uid', String, ForeignKey(base.c.uid), primary_key=True), Column('y', String) ) derivedII = Table( 'derivedII', metadata, Column('uid', String, ForeignKey(base.c.uid), primary_key=True), Column('x', String) ) comments = Table( 'comments', metadata, Column('id', Integer, primary_key=True), Column('uid', String, ForeignKey(base.c.uid)), Column('comment', String) ) class Base(object): def __init__(self, uid, x): self.uid = uid self.x = x class Derived(Base): def __init__(self, uid, x, y): self.uid = uid self.x = x self.y = y class DerivedII(Base): def __init__(self, uid, x, z): self.uid = uid self.x = x self.z = z class Comment(object): def __init__(self, uid, comment): self.uid = uid self.comment = comment commentMapper = mapper(Comment, comments) baseMapper = mapper( Base, base, properties={ 'comments': relation( Comment, lazy=False, cascade='all, delete-orphan' ) } ) derivedMapper = mapper(Derived, derived, inherits=baseMapper) derivedIIMapper = mapper(DerivedII, derivedII, inherits=baseMapper) def transact(f): def _wrap(*args, **kwargs): def _job(conn, *args, **kwargs): sess = create_session(bind_to=db) try: ret = f(conn, sess, *args, **kwargs) sess.flush() sess.close() return ret except: sess.close() raise return db.transaction(_job, None, *args, **kwargs) _wrap.__name__ = f.__name__ return _wrap @transact def create(conn, sess, klass, id, *args): o = klass(id, *args) o.comments = [Comment(id, 'comment')] sess.save(o) @transact def load(conn, sess, klass, id): return sess.load(klass, id) @transact def view(conn, sess, o): print o.x print [c.comment for c in o.comments] metadata.create_all() try: create(Derived, 1, 'x', 'y') create(DerivedII, 2, 'xx', 'z') o = load(Derived, 1) view(o) o = load(DerivedII, 2) view(o) finally: metadata.drop_all() The problem is with the access to the comments attribute from two separate mapper that inherits from a common base mapper. P.S. Just to know: is the transact decorator implementation the best way to run a session inside a transaction? Thanks and regards Manlio Perillo --~--~---------~--~----~------------~-------~--~----~ 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 -~----------~----~----~----~------~----~------~--~---