]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- added close() method to Transaction. closes out a transaction using rollback
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 17 Aug 2007 21:20:49 +0000 (21:20 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 17 Aug 2007 21:20:49 +0000 (21:20 +0000)
  if it's the outermost transaction, otherwise just ends without affecting
  the outer transaction.

- transactional and non-transactional Session integrates better with bound
  connection; a close() will ensure that connection transactional state is
  the same as that which existed on it before being bound to the Session.

CHANGES
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/orm/session.py
test/engine/transaction.py
test/orm/session.py

diff --git a/CHANGES b/CHANGES
index 81505bf5abb01357e69c855cad2c298100188897..12ee19af4884641405e9cb888ed4c08bd409ef35 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -11,6 +11,14 @@ CHANGES
 - Added session.prune(), trims away instances cached in a session that are no
   longer referenced elsewhere. (A utility for strong-ref identity maps).
 
+- added close() method to Transaction.  closes out a transaction using rollback
+  if it's the outermost transaction, otherwise just ends without affecting
+  the outer transaction.
+
+- transactional and non-transactional Session integrates better with bound 
+  connection; a close() will ensure that connection transactional state is 
+  the same as that which existed on it before being bound to the Session.
+
 0.4.0beta3
 ----------
 
index 8fe34bf3f5605b98f7f257fd8ad905f815eb1747..faeb00cc98ca0942b77644a0e35a0448027f5c28 100644 (file)
@@ -864,6 +864,20 @@ class Transaction(object):
     connection = property(lambda s:s._connection, doc="The Connection object referenced by this Transaction")
     is_active = property(lambda s:s._is_active)
 
+    def close(self):
+        """close this transaction.
+        
+        If this transaction is the base transaction in a begin/commit nesting, 
+        the transaction will rollback().  Otherwise, the method returns.
+        
+        This is used to cancel a Transaction without affecting the scope of
+        an enclosign transaction.
+        """
+        if not self._parent._is_active:
+            return
+        if self._parent is self:
+            self.rollback()
+        
     def rollback(self):
         if not self._parent._is_active:
             return
index f21d8d69bcd19524d348ee25b438b218f74b1108..5a91f8fbfe4ae0f29c0972441beeb94558b4c336 100644 (file)
@@ -243,7 +243,7 @@ class SessionTransaction(object):
             if t[2]:
                 t[0].close()
             else:
-                t[1].rollback()
+                t[1].close()
         self.session.transaction = None
 
     def __enter__(self):
index 7adefbac2b2d81d06b216ce7718651d0a7293147..cf0be06596489426d3b2232646a62bc3a69ec713 100644 (file)
@@ -116,6 +116,49 @@ class TransactionTest(PersistTest):
         result = connection.execute("select * from query_users")
         assert len(result.fetchall()) == 0
         connection.close()
+
+    @testing.exclude('mysql', '<', (5, 0, 3))
+    def testclose(self):
+        connection = testbase.db.connect()
+        transaction = connection.begin()
+        connection.execute(users.insert(), user_id=1, user_name='user1')
+        connection.execute(users.insert(), user_id=2, user_name='user2')
+        connection.execute(users.insert(), user_id=3, user_name='user3')
+        trans2 = connection.begin()
+        connection.execute(users.insert(), user_id=4, user_name='user4')
+        connection.execute(users.insert(), user_id=5, user_name='user5')
+        assert connection.in_transaction()
+        trans2.close()
+        assert connection.in_transaction()
+        transaction.commit()
+        assert not connection.in_transaction()
+        self.assert_(connection.scalar("select count(1) from query_users") == 5)
+
+        result = connection.execute("select * from query_users")
+        assert len(result.fetchall()) == 5
+        connection.close()
+
+    @testing.exclude('mysql', '<', (5, 0, 3))
+    def testclose2(self):
+        connection = testbase.db.connect()
+        transaction = connection.begin()
+        connection.execute(users.insert(), user_id=1, user_name='user1')
+        connection.execute(users.insert(), user_id=2, user_name='user2')
+        connection.execute(users.insert(), user_id=3, user_name='user3')
+        trans2 = connection.begin()
+        connection.execute(users.insert(), user_id=4, user_name='user4')
+        connection.execute(users.insert(), user_id=5, user_name='user5')
+        assert connection.in_transaction()
+        trans2.close()
+        assert connection.in_transaction()
+        transaction.close()
+        assert not connection.in_transaction()
+        self.assert_(connection.scalar("select count(1) from query_users") == 0)
+
+        result = connection.execute("select * from query_users")
+        assert len(result.fetchall()) == 0
+        connection.close()
+
     
     @testing.supported('postgres', 'mysql', 'oracle')
     @testing.exclude('mysql', '<', (5, 0, 3))
index e6db74baac76bfa89fa2e813b7589ed1435d4657..c4fa10f0a076797036841eccc1b0f579209ff3ef 100644 (file)
@@ -378,6 +378,21 @@ class SessionTest(AssertMixin):
         sess.commit()
         assert not c.in_transaction()
         assert c.scalar("select count(1) from users") == 1
+        c.execute("delete from users")
+        assert c.scalar("select count(1) from users") == 0
+        
+        c = testbase.db.connect()
+
+        trans = c.begin()
+        sess = create_session(bind=c, transactional=False)
+        u = User()
+        sess.save(u)
+        sess.flush()
+        assert c.in_transaction()
+        trans.commit()
+        assert not c.in_transaction()
+        assert c.scalar("select count(1) from users") == 1
+        
         
     @engines.close_open_connections
     def test_update(self):