From cd464c7aac765f65c032cf1f6a6a59010b7f1607 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 14 Dec 2009 01:34:06 +0000 Subject: [PATCH] - merged r6553 from trunk - Session.merge() now properly overwrites a many-to-one or uselist=False attribute to None if the attribute is also None in the given object to be merged. --- CHANGES | 4 ++++ lib/sqlalchemy/orm/properties.py | 12 +++++++----- test/orm/test_merge.py | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index 3cee14b5af..e804822c37 100644 --- a/CHANGES +++ b/CHANGES @@ -28,6 +28,10 @@ CHANGES in expression which is an insert()/update()/delete() construct. [ticket:1054] + - Session.merge() now properly overwrites a many-to-one or + uselist=False attribute to None if the attribute + is also None in the given object to be merged. + - Fixed a needless select which would occur when merging transient objects that contained a null primary key identifier. [ticket:1618] diff --git a/lib/sqlalchemy/orm/properties.py b/lib/sqlalchemy/orm/properties.py index e874e37471..e3ecad3b10 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -665,11 +665,13 @@ class RelationProperty(StrategizedProperty): if current is not None: _recursive[(current, self)] = True obj = session._merge(current, dont_load=dont_load, _recursive=_recursive) - if obj is not None: - if dont_load: - dest_state.dict[self.key] = obj - else: - setattr(dest, self.key, obj) + else: + obj = None + + if dont_load: + dest_state.dict[self.key] = obj + else: + setattr(dest, self.key, obj) def cascade_iterator(self, type_, state, visited_instances, halt_on=None): if not type_ in self.cascade: diff --git a/test/orm/test_merge.py b/test/orm/test_merge.py index d0f667237c..4c8fb87839 100644 --- a/test/orm/test_merge.py +++ b/test/orm/test_merge.py @@ -454,6 +454,28 @@ class MergeTest(_fixtures.FixtureTest): eq_(on_load.called, 2) assert u3 is u + @testing.resolve_artifact_names + def test_value_to_none(self): + mapper(User, users, properties={ + 'address':relation(mapper(Address, addresses),uselist = False, backref='user') + }) + sess = sessionmaker()() + u = User(id=7, name="fred", address=Address(id=1, email_address='foo@bar.com')) + sess.add(u) + sess.commit() + sess.close() + + u2 = User(id=7, name=None, address=None) + u3 = sess.merge(u2) + assert u3.name is None + assert u3.address is None + + sess.close() + + a1 = Address(id=1, user=None) + a2 = sess.merge(a1) + assert a2.user is None + @testing.resolve_artifact_names def test_transient_dontload(self): mapper(User, users) -- 2.47.3