diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-01-27 20:32:52 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-01-27 20:32:52 -0500 |
| commit | f9c2f85a3ac35cd0158dbd818ba0b9d209003304 (patch) | |
| tree | 794f4cac1bed82cfc8a7a901e090f82d15566e93 /lib/sqlalchemy/orm/session.py | |
| parent | 535fc8b1500cc11cc800ee3189d30bc6d8de51a7 (diff) | |
| download | sqlalchemy-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.py | 22 |
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: |
