]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- Backported the fix for [ticket:2317] introduced
authorMike Bayer <mike_mp@zzzcomputing.com>
Tue, 24 Apr 2012 14:55:47 +0000 (10:55 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Tue, 24 Apr 2012 14:55:47 +0000 (10:55 -0400)
in 0.7.4, which ensures that the connection
is in a valid state before attempting to call
rollback()/prepare()/release() on savepoint
and two-phase transactions.

CHANGES
lib/sqlalchemy/engine/base.py
test/engine/test_reconnect.py

diff --git a/CHANGES b/CHANGES
index c5dc7ab834b03f9b122c0726cfa0d5d813bfb511..2a41fac5073f991bbbddc3a40d5ffb0b49c4cdb9 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -72,6 +72,13 @@ CHANGES
      a tuple is inadvertently passed to session.query()
      [ticket:2297].
 
+- engine
+  - Backported the fix for [ticket:2317] introduced
+    in 0.7.4, which ensures that the connection
+    is in a valid state before attempting to call
+    rollback()/prepare()/release() on savepoint
+    and two-phase transactions.
+
 - sql
   - Fixed two subtle bugs involving column 
     correspondence in a selectable,
index a3ed5bac164fa0626ee435c070fd5977bd684b70..78058bb6c1450326590ba5719018dce64cbdf94c 100644 (file)
@@ -929,6 +929,13 @@ class Connection(Connectable):
 
         return getattr(self.__connection, 'is_valid', False)
 
+    @property
+    def _still_open_and_connection_is_valid(self):
+        return \
+            not self.closed and \
+            not self.invalidated and \
+            getattr(self.__connection, 'is_valid', False)
+
     @property
     def info(self):
         """A collection of per-DB-API connection instance properties."""
@@ -1077,8 +1084,7 @@ class Connection(Connectable):
             raise
 
     def _rollback_impl(self):
-        if not self.closed and not self.invalidated and \
-                        self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             if self._echo:
                 self.engine.logger.info("ROLLBACK")
             try:
@@ -1109,32 +1115,32 @@ class Connection(Connectable):
             return name
 
     def _rollback_to_savepoint_impl(self, name, context):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             self.engine.dialect.do_rollback_to_savepoint(self, name)
         self.__transaction = context
 
     def _release_savepoint_impl(self, name, context):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             self.engine.dialect.do_release_savepoint(self, name)
         self.__transaction = context
 
     def _begin_twophase_impl(self, xid):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             self.engine.dialect.do_begin_twophase(self, xid)
 
     def _prepare_twophase_impl(self, xid):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             assert isinstance(self.__transaction, TwoPhaseTransaction)
             self.engine.dialect.do_prepare_twophase(self, xid)
 
     def _rollback_twophase_impl(self, xid, is_prepared):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             assert isinstance(self.__transaction, TwoPhaseTransaction)
             self.engine.dialect.do_rollback_twophase(self, xid, is_prepared)
         self.__transaction = None
 
     def _commit_twophase_impl(self, xid, is_prepared):
-        if self._connection_is_valid:
+        if self._still_open_and_connection_is_valid:
             assert isinstance(self.__transaction, TwoPhaseTransaction)
             self.engine.dialect.do_commit_twophase(self, xid, is_prepared)
         self.__transaction = None
@@ -1341,6 +1347,7 @@ class Connection(Connectable):
                 context.handle_dbapi_exception(e)
 
             is_disconnect = self.dialect.is_disconnect(e)
+
             if is_disconnect:
                 self.invalidate(e)
                 self.engine.dispose()
index e380682a65c7ecd3796d73182b13babec7782313..09997a46583cfd8d4421564f2d4e8313b28d3835 100644 (file)
@@ -259,6 +259,27 @@ class RealReconnectTest(TestBase):
 
         conn.close()
 
+    def test_rollback_on_invalid_plain(self):
+        conn = engine.connect()
+        trans = conn.begin()
+        conn.invalidate()
+        trans.rollback()
+
+    @testing.requires.two_phase_transactions
+    def test_rollback_on_invalid_twophase(self):
+        conn = engine.connect()
+        trans = conn.begin_twophase()
+        conn.invalidate()
+        trans.rollback()
+
+    @testing.requires.savepoints
+    def test_rollback_on_invalid_savepoint(self):
+        conn = engine.connect()
+        trans = conn.begin()
+        trans2 = conn.begin_nested()
+        conn.invalidate()
+        trans2.rollback()
+
     def test_invalidate_twice(self):
         conn = engine.connect()
         conn.invalidate()