From: Mike Bayer Date: Thu, 2 Apr 2015 16:19:15 +0000 (-0400) Subject: - Fixed bug where the state tracking within multiple, nested X-Git-Tag: rel_1_0_0b5~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=359f471a1203cafd5dc99b5b078ba7d788b67cec;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - Fixed bug where the state tracking within multiple, nested :meth:`.Session.begin_nested` operations would fail to propagate the "dirty" flag for an object that had been updated within the inner savepoint, such that if the enclosing savepoint were rolled back, the object would not be part of the state that was expired and therefore reverted to its database state. fixes #3352 --- diff --git a/doc/build/changelog/changelog_09.rst b/doc/build/changelog/changelog_09.rst index 53c4eeaaab..89a5d72da5 100644 --- a/doc/build/changelog/changelog_09.rst +++ b/doc/build/changelog/changelog_09.rst @@ -14,6 +14,18 @@ .. changelog:: :version: 0.9.10 + .. change:: + :tags: bug, orm + :tickets: 3352 + :versions: 1.0.0b5 + + Fixed bug where the state tracking within multiple, nested + :meth:`.Session.begin_nested` operations would fail to propagate + the "dirty" flag for an object that had been updated within + the inner savepoint, such that if the enclosing savepoint were + rolled back, the object would not be part of the state that was + expired and therefore reverted to its database state. + .. change:: :tags: bug, mysql, pymysql :tickets: 3337 diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index f3ad2349c3..4619027e5b 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -305,6 +305,7 @@ class SessionTransaction(object): self._deleted.clear() elif self.nested: self._parent._new.update(self._new) + self._parent._dirty.update(self._dirty) self._parent._deleted.update(self._deleted) self._parent._key_switches.update(self._key_switches) diff --git a/test/orm/test_transaction.py b/test/orm/test_transaction.py index 6bea5cc7b7..91846a67e6 100644 --- a/test/orm/test_transaction.py +++ b/test/orm/test_transaction.py @@ -143,6 +143,34 @@ class SessionTransactionTest(FixtureTest): assert session.connection().execute( 'select count(1) from users').scalar() == 2 + @testing.requires.savepoints + def test_dirty_state_transferred_deep_nesting(self): + User, users = self.classes.User, self.tables.users + + mapper(User, users) + + s = Session(testing.db) + u1 = User(name='u1') + s.add(u1) + s.commit() + + nt1 = s.begin_nested() + nt2 = s.begin_nested() + u1.name = 'u2' + assert attributes.instance_state(u1) not in nt2._dirty + assert attributes.instance_state(u1) not in nt1._dirty + s.flush() + assert attributes.instance_state(u1) in nt2._dirty + assert attributes.instance_state(u1) not in nt1._dirty + + s.commit() + assert attributes.instance_state(u1) in nt2._dirty + assert attributes.instance_state(u1) in nt1._dirty + + s.rollback() + assert attributes.instance_state(u1).expired + eq_(u1.name, 'u1') + @testing.requires.independent_connections def test_transactions_isolated(self): User, users = self.classes.User, self.tables.users