summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/session.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2012-01-27 20:32:52 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2012-01-27 20:32:52 -0500
commitf9c2f85a3ac35cd0158dbd818ba0b9d209003304 (patch)
tree794f4cac1bed82cfc8a7a901e090f82d15566e93 /lib/sqlalchemy/orm/session.py
parent535fc8b1500cc11cc800ee3189d30bc6d8de51a7 (diff)
downloadsqlalchemy-f9c2f85a3ac35cd0158dbd818ba0b9d209003304.tar.gz
- [bug] Fixed issue where modified session state
established after a failed flush would be committed as part of the subsequent transaction that begins automatically after manual call to rollback(). The state of the session is checked within rollback(), and if new state is present, a warning is emitted and restore_snapshot() is called a second time, discarding those changes. [ticket:2389] - repaired testing.assert_warnings to also verify that any warnings were emitted
Diffstat (limited to 'lib/sqlalchemy/orm/session.py')
-rw-r--r--lib/sqlalchemy/orm/session.py22
1 files changed, 18 insertions, 4 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py
index eb03a5b81..4299290d0 100644
--- a/lib/sqlalchemy/orm/session.py
+++ b/lib/sqlalchemy/orm/session.py
@@ -343,6 +343,16 @@ class SessionTransaction(object):
sess = self.session
+ if self.session._enable_transaction_accounting and \
+ not sess._is_clean():
+ # if items were added, deleted, or mutated
+ # here, we need to re-restore the snapshot
+ util.warn(
+ "Session's state has been changed on "
+ "a non-active transaction - this state "
+ "will be discarded.")
+ self._restore_snapshot()
+
self.close()
if self._parent and _capture_exception:
self._parent._rollback_exception = sys.exc_info()[1]
@@ -575,7 +585,7 @@ class Session(object):
if self.transaction is not None:
if subtransactions or nested:
self.transaction = self.transaction._begin(
- nested=nested)
+ nested=nested)
else:
raise sa_exc.InvalidRequestError(
"A transaction is already begun. Use subtransactions=True "
@@ -1542,16 +1552,20 @@ class Session(object):
if self._flushing:
raise sa_exc.InvalidRequestError("Session is already flushing")
+ if self._is_clean():
+ return
try:
self._flushing = True
self._flush(objects)
finally:
self._flushing = False
+ def _is_clean(self):
+ return not self.identity_map.check_modified() and \
+ not self._deleted and \
+ not self._new
+
def _flush(self, objects=None):
- if (not self.identity_map.check_modified() and
- not self._deleted and not self._new):
- return
dirty = self._dirty_states
if not dirty and not self._deleted and not self._new: