When begin_nested() is called, a flush() is unconditionally issued (regardless of the autoflush setting). This is so that when a rollback() occurs, the full state of the session is expired, thus causing all subsequent attribute/instance access to reference the full state of the Session right before begin_nested()was called.
from sqlalchemy import Column, Integer, Booleanfrom sqlalchemy import create_enginefrom sqlalchemy.ext.declarative import declarative_basefrom sqlalchemy.orm import sessionmakerBase = declarative_base()class Test(Base):__tablename__ = 'test'id = Column(Integer, primary_key=True)value = Column(Boolean)engine = create_engine('sqlite:///sqlalchemy_example.db')Base.metadata.create_all(engine)DBSession = sessionmaker(bind=engine)session = DBSession(autocommit=True)session.begin()test_data = Test(value=False)session.add(test_data)session.commit()print test_data.value, "in the beginning"try:with session.begin():# with session.begin_nested():test_data.value = Trueprint test_data.value, "before rollback"raise ValueError("force a rollback")except ValueError as e:print "ValueError caught: {}".format(e)print test_data.value, "after rollback"
False in the beginning
True before rollback
ValueError caught: force a rollback
False after rollback
CREATE TABLE test (id SERIAL NOT NULL PRIMARY KEY, value BOOLEAN);GRANT ALL ON TABLE test TO standard;GRANT ALL ON TABLE test_id_seq TO standard;
try:with session.begin():try:with session.begin_nested():test_data.value = Trueprint test_data.value, "after nested commit, before nested rollback"raise ValueError("force a rollback")except ValueError as e:print "ValueError caught: {}".format(e)print test_data.value, "after nested rollback"assert not test_data.value, "should have been rolled back"assert session.transaction is not Noneraise ValueError("force a rollback")except ValueError as e:print "ValueError caught: {}".format(e)print test_data.value, "after outer rollback"
try:with session.begin():try:with session.begin_nested():with session.begin_nested():test_data.value = Trueprint test_data.value, "after nested commit, before nested rollback"raise ValueError("force a rollback")except ValueError as e:print "ValueError caught: {}".format(e)print test_data.value, "after nested rollback"# assert not test_data.value, "should have been rolled back; this assertion fails if enabled"assert session.transaction is not Noneraise ValueError("force a rollback")except ValueError as e:print "ValueError caught: {}".format(e)print test_data.value, "after outer rollback"assert session.transaction is None
False in the beginning
True after nested commit, before nested rollback
ValueError caught: force a rollback
True after nested rollback
ValueError caught: force a rollback
False after outer rollback
--
Thanks, Chris.
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.
To post to this group, send email to sqlal...@googlegroups.com.
Visit this group at http://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.
it's a bug, and I've captured the origin, diagnosis and probable solution here: https://bitbucket.org/zzzeek/sqlalchemy/issue/3352/nested-begin_nested-blocks-dont-track
this issue is fixed for 0.9.10 and 1.0.0b5, you can test now using either latest master or the rel_0_9 branch.