]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- ConnectionProxy now has wrapper methods for all transaction
authorMike Bayer <mike_mp@zzzcomputing.com>
Sat, 16 Jan 2010 19:04:39 +0000 (19:04 +0000)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sat, 16 Jan 2010 19:04:39 +0000 (19:04 +0000)
lifecycle events, including begin(), rollback(), commit()
begin_nested(), begin_prepared(), prepare(), release_savepoint(),
etc.

CHANGES
lib/sqlalchemy/engine/base.py
lib/sqlalchemy/interfaces.py
test/engine/test_execute.py

diff --git a/CHANGES b/CHANGES
index 9e439354e777088f508818bf65291fb95949b58d..68d497ca78588ae43d38f76f8edd473c561543cf 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -342,6 +342,11 @@ CHANGES
     for "sqlalchemy.engine" is enabled overall.  Note that the
     default setting of "echo" is `None`. [ticket:1554]
   
+  - ConnectionProxy now has wrapper methods for all transaction
+    lifecycle events, including begin(), rollback(), commit()
+    begin_nested(), begin_prepared(), prepare(), release_savepoint(),
+    etc.
+    
   - Connection pool logging now uses both INFO and DEBUG
     log levels for logging.  INFO is for major events such
     as invalidated connections, DEBUG for all the acquire/return
index 86a2a7fdb5fffac017f57eeac09d3ab8b6a6b1c4..564fa50a949cb7c859969e91b80655dfc05d3804 100644 (file)
@@ -1523,6 +1523,36 @@ def _proxy_connection_cls(cls, proxy):
         def _cursor_executemany(self, cursor, statement, parameters, context=None):
             return proxy.cursor_execute(super(ProxyConnection, self)._cursor_executemany, cursor, statement, parameters, context, True)
 
+        def _begin_impl(self):
+            return proxy.begin(self, super(ProxyConnection, self)._begin_impl)
+            
+        def _rollback_impl(self):
+            return proxy.rollback(self, super(ProxyConnection, self)._rollback_impl)
+
+        def _commit_impl(self):
+            return proxy.commit(self, super(ProxyConnection, self)._commit_impl)
+
+        def _savepoint_impl(self, name=None):
+            return proxy.savepoint(self, super(ProxyConnection, self)._savepoint_impl, name=name)
+
+        def _rollback_to_savepoint_impl(self, name, context):
+            return proxy.rollback_savepoint(self, super(ProxyConnection, self)._rollback_to_savepoint_impl, name, context)
+            
+        def _release_savepoint_impl(self, name, context):
+            return proxy.release_savepoint(self, super(ProxyConnection, self)._release_savepoint_impl, name, context)
+
+        def _begin_twophase_impl(self, xid):
+            return proxy.begin_twophase(self, super(ProxyConnection, self)._begin_twophase_impl, xid)
+
+        def _prepare_twophase_impl(self, xid):
+            return proxy.prepare_twophase(self, super(ProxyConnection, self)._prepare_twophase_impl, xid)
+
+        def _rollback_twophase_impl(self, xid, is_prepared):
+            return proxy.rollback_twophase(self, super(ProxyConnection, self)._rollback_twophase_impl, xid, is_prepared)
+
+        def _commit_twophase_impl(self, xid, is_prepared):
+            return proxy.commit_twophase(self, super(ProxyConnection, self)._commit_twophase_impl, xid, is_prepared)
+
     return ProxyConnection
 
 
index e4a9adee1fb6351d5100632ff45d22341c82cf69..c2a267d5f32c7250eebe73904e098bcc60c8bc06 100644 (file)
@@ -152,5 +152,54 @@ class ConnectionProxy(object):
         """Intercept low-level cursor execute() events."""
         
         return execute(cursor, statement, parameters, context)
-
+    
+    def begin(self, conn, begin):
+        """Intercept begin() events."""
+        
+        return begin()
+        
+    def rollback(self, conn, rollback):
+        """Intercept rollback() events."""
+        
+        return rollback()
+        
+    def commit(self, conn, commit):
+        """Intercept commit() events."""
+        
+        return commit()
+        
+    def savepoint(self, conn, savepoint, name=None):
+        """Intercept savepoint() events."""
+        
+        return savepoint(name=name)
+        
+    def rollback_savepoint(self, conn, rollback_savepoint, name, context):
+        """Intercept rollback_savepoint() events."""
+        
+        return rollback_savepoint(name, context)
+        
+    def release_savepoint(self, conn, release_savepoint, name, context):
+        """Intercept release_savepoint() events."""
+        
+        return release_savepoint(name, context)
+        
+    def begin_twophase(self, conn, begin_twophase, xid):
+        """Intercept begin_twophase() events."""
+        
+        return begin_twophase(xid)
+        
+    def prepare_twophase(self, conn, prepare_twophase, xid):
+        """Intercept prepare_twophase() events."""
+        
+        return prepare_twophase(xid)
+        
+    def rollback_twophase(self, conn, rollback_twophase, xid, is_prepared):
+        """Intercept rollback_twophase() events."""
+        
+        return rollback_twophase(xid, is_prepared)
+        
+    def commit_twophase(self, conn, commit_twophase, xid, is_prepared):
+        """Intercept commit_twophase() events."""
+        
+        return commit_twophase(xid, is_prepared)
         
index 4a1342bd5c5401934aa52a80e47160efc9fc6c6c..45d7763f02c3de65790d796997afedcc10cc9f2b 100644 (file)
@@ -106,7 +106,6 @@ class ProxyConnectionTest(TestBase):
                 return execute(clauseelement, *multiparams, **params)
 
             def cursor_execute(self, execute, cursor, statement, parameters, context, executemany):
-                print "CE", statement, parameters
                 cursor_stmts.append(
                     (str(statement), parameters, None)
                 )
@@ -173,4 +172,61 @@ class ProxyConnectionTest(TestBase):
             assert_stmts(compiled, stmts)
             assert_stmts(cursor, cursor_stmts)
     
+    def test_transactional(self):
+        track = []
+        class TrackProxy(ConnectionProxy):
+            def __getattribute__(self, key):
+                fn = object.__getattribute__(self, key)
+                def go(*arg, **kw):
+                    track.append(fn.__name__)
+                    return fn(*arg, **kw)
+                return go
+
+        engine = engines.testing_engine(options={'proxy':TrackProxy()})
+        conn = engine.connect()
+        trans = conn.begin()
+        conn.execute("select 1")
+        trans.rollback()
+        trans = conn.begin()
+        conn.execute("select 1")
+        trans.commit()
+        
+        eq_(track, ['begin', 'execute', 'cursor_execute', 
+                        'rollback', 'begin', 'execute', 'cursor_execute', 'commit'])
+        
+    @testing.requires.savepoints
+    @testing.requires.two_phase_transactions
+    def test_transactional_advanced(self):
+        track = []
+        class TrackProxy(ConnectionProxy):
+            def __getattribute__(self, key):
+                fn = object.__getattribute__(self, key)
+                def go(*arg, **kw):
+                    track.append(fn.__name__)
+                    return fn(*arg, **kw)
+                return go
+
+        engine = engines.testing_engine(options={'proxy':TrackProxy()})
+        conn = engine.connect()
+        
+        trans = conn.begin()
+        trans2 = conn.begin_nested()
+        conn.execute("select 1")
+        trans2.rollback()
+        trans2 = conn.begin_nested()
+        conn.execute("select 1")
+        trans2.commit()
+        trans.rollback()
+        
+        trans = conn.begin_twophase()
+        conn.execute("select 1")
+        trans.prepare()
+        trans.commit()
+
+        eq_(track, ['begin', 'savepoint', 'execute', 'cursor_execute', 'execute', 'cursor_execute',
+                    'rollback_savepoint', 'execute', 'cursor_execute', 'savepoint', 'execute',
+                     'cursor_execute', 'execute', 'cursor_execute', 'release_savepoint', 'execute',
+                      'cursor_execute', 'rollback', 'begin_twophase', 'execute', 'cursor_execute',
+                       'prepare_twophase', 'execute', 'cursor_execute', 'commit_twophase',
+                        'execute', 'cursor_execute', 'execute', 'cursor_execute'])