]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Fixed bug where the state tracking within multiple, nested
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 2 Apr 2015 16:19:15 +0000 (12:19 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 2 Apr 2015 16:21:00 +0000 (12:21 -0400)
: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

(cherry picked from commit 359f471a1203cafd5dc99b5b078ba7d788b67cec)

doc/build/changelog/changelog_09.rst
lib/sqlalchemy/orm/session.py
test/orm/test_transaction.py

index 32339a15448043afa067f28f767d051f1f30fc71..ab1292f494f3b8d646e7fa335466b1f9587ba431 100644 (file)
         :meth:`.Query.select_from` has been called, a warning is emitted.
         As of 1.0.0b5 this will raise an error.
 
+    .. 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
index f976be9428a4a49b3e11cfebe5ff498b1ef9ec2d..e285245656b2bc6d8375a605195c9705e1f957f5 100644 (file)
@@ -298,6 +298,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)
 
index 6bea5cc7b7b26ecf8c46ee639d4d71367678c957..91846a67e6102347d512e7be66702c05746215d9 100644 (file)
@@ -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