diff options
| author | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-02-09 01:46:06 -0500 |
|---|---|---|
| committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2019-02-09 14:38:43 -0500 |
| commit | b2afef966dcc44e991f22a8fb68de4f1220bd674 (patch) | |
| tree | f30aed7c4d8876e63d98a239ee8251a427639f1c /lib | |
| parent | fcb5dbf39569bcacb70a3fed05f469d73b64f116 (diff) | |
| download | sqlalchemy-b2afef966dcc44e991f22a8fb68de4f1220bd674.tar.gz | |
Don't run pending_to_persistent for non-new objects
Fixed fairly simple but critical issue where the
:meth:`.SessionEvents.pending_to_persistent` event would be invoked for
objects not just when they move from pending to persistent, but when they
were also already persistent and just being updated, thus causing the event
to be invoked for all objects on every update.
Fixes: #4489
Change-Id: Ibe147020aa62f7d605cb1029b7f3b776f42e6b43
Diffstat (limited to 'lib')
| -rw-r--r-- | lib/sqlalchemy/orm/session.py | 14 | ||||
| -rw-r--r-- | lib/sqlalchemy/orm/unitofwork.py | 2 |
2 files changed, 13 insertions, 3 deletions
diff --git a/lib/sqlalchemy/orm/session.py b/lib/sqlalchemy/orm/session.py index 6d4198a4e..0b1a3b101 100644 --- a/lib/sqlalchemy/orm/session.py +++ b/lib/sqlalchemy/orm/session.py @@ -1827,7 +1827,14 @@ class Session(_SessionClassMethods): states, self, to_transient=to_transient ) - def _register_newly_persistent(self, states): + def _register_persistent(self, states): + """Register all persistent objects from a flush. + + This is used both for pending objects moving to the persistent + state as well as already persistent objects. + + """ + pending_to_persistent = self.dispatch.pending_to_persistent or None for state in states: mapper = _state_mapper(state) @@ -1871,6 +1878,9 @@ class Session(_SessionClassMethods): ) state.key = instance_key + # there can be an existing state in the identity map + # that is replaced when the primary keys of two instances + # are swapped; see test/orm/test_naturalpks.py -> test_reverse self.identity_map.replace(state) state._orphaned_outside_of_session = False @@ -1881,7 +1891,7 @@ class Session(_SessionClassMethods): self._register_altered(states) if pending_to_persistent is not None: - for state in states: + for state in states.intersection(self._new): pending_to_persistent(self, state.obj()) # remove from new last, might be the last strong ref diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 3b91c8990..1f2221ea9 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -440,7 +440,7 @@ class UOWTransaction(object): if isdel: self.session._remove_newly_deleted(isdel) if other: - self.session._register_newly_persistent(other) + self.session._register_persistent(other) class IterateMappersMixin(object): |
