summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2019-02-09 01:46:06 -0500
committerMike Bayer <mike_mp@zzzcomputing.com>2019-02-09 14:38:43 -0500
commitb2afef966dcc44e991f22a8fb68de4f1220bd674 (patch)
treef30aed7c4d8876e63d98a239ee8251a427639f1c /lib
parentfcb5dbf39569bcacb70a3fed05f469d73b64f116 (diff)
downloadsqlalchemy-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.py14
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py2
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):