The Versioned mixin described in 
http://docs.sqlalchemy.org/en/rel_0_8/orm/examples.html#versioned-objects 
(which I renamed VersionedMixin, but is otherwise the same) has what I 
would consider an unintuitive and undesirable interaction with backref: if 
C references A with a backref, adding a new C object referencing a 
particular A object will cause the version number of the target A object to 
increment, even though there are no changes to the A table. If the relation 
has no backref (as in the relationship from C to B below), then the target 
object version number is not incremented, as I would expect. It seems that 
the code is effectively using session.is_modified(a) to determine whether 
to increment the version number, whereas I would have thought 
session.is_modified(a, 
include_collections=False) would be more appropriate. Is there some use 
case I'm not considering that favors the current behavior?

Thanks,

Seth

from sqlalchemy import Column, Integer, String, ForeignKey, create_engine
from sqlalchemy.ext.declarative.api import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session, relationship, 
backref
from history_meta import VersionedMixin, versioned_session

Base = declarative_base(object)
metadata = Base.metadata

class A(VersionedMixin, Base):
    __tablename__ = 'a'
    __table_args__ = {}
    id = Column(Integer, primary_key=True)
    name = Column(String(3))
    def __repr__(self):
        return "A(id=%d,name='%s',version=%d,cs=%s)" % (self.id, self.name, 
self.version, [c.name for c in self.cs])

class B(VersionedMixin, Base):
    __tablename__ = 'b'
    __table_args__ = {}
    id = Column(Integer, primary_key=True)
    name = Column(String(3))
    def __repr__(self):
        return "B(id=%d,name='%s',version=%d)" % (self.id, self.name, 
self.version)

class C(VersionedMixin, Base):
    __tablename__ = 'c'
    __table_args__ = {}
    id = Column(Integer, primary_key=True)
    name = Column(String(3))
    a_id = Column(Integer, ForeignKey('a.id'))
    a_re = relationship(A, backref='cs')
    b_id = Column(Integer, ForeignKey('b.id'))
    b_re = relationship(B)

if __name__ == '__main__':
    engine = create_engine('sqlite:///:memory:', echo=False)
    metadata.create_all(bind=engine)
    Session = scoped_session(sessionmaker(bind=engine))
    versioned_session(Session)
    session = Session()

    # populate tables with a single entry in each table
    a = A(name='a')
    b = B(name='b')
    c1 = C(name='c1', a_re=a, b_re=b)
    session.add_all([a, b, c1])
    session.commit()
    print '\nAfter initial commit'
    print 'a=%s; is_modified(a)=%s; is_modified(a, 
include_collections=False)=%s' % (a, session.is_modified(a), 
session.is_modified(a, include_collections=False))
    print 'b=%s; is_modified(b)=%s; is_modified(b, 
include_collections=False)=%s' % (b, session.is_modified(b), 
session.is_modified(b, include_collections=False))
    # add another entry in b that points to a
    c2 = C(name='c2', a_re=a, b_re=b)
    session.add(c2)
    print "\nAfter adding C(name='c2', a_re=a, b_re=b), but before 
committing:"
    print 'a=%s; is_modified(a)=%s; is_modified(a, 
include_collections=False)=%s' % (a, session.is_modified(a), 
session.is_modified(a, include_collections=False))
    print 'b=%s; is_modified(b)=%s; is_modified(b, 
include_collections=False)=%s' % (b, session.is_modified(b), 
session.is_modified(b, include_collections=False))
    session.commit()
    print '\nAfter final commit:'
    print 'a=%s; is_modified(a)=%s; is_modified(a, 
include_collections=False)=%s' % (a, session.is_modified(a), 
session.is_modified(a, include_collections=False))
    print 'b=%s; is_modified(b)=%s; is_modified(b, 
include_collections=False)=%s' % (b, session.is_modified(b), 
session.is_modified(b, include_collections=False))

-- 
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 http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/groups/opt_out.


Reply via email to