From e8e446e92a59ed1cf347a8d224991fc828602ab0 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Mon, 14 Dec 2009 01:29:51 +0000 Subject: [PATCH] - 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 6326030fc3..079814e038 100644 --- a/CHANGES +++ b/CHANGES @@ -776,6 +776,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 190be8d660..7d078cf125 100644 --- a/lib/sqlalchemy/orm/properties.py +++ b/lib/sqlalchemy/orm/properties.py @@ -661,11 +661,13 @@ class RelationProperty(StrategizedProperty): if current is not None: _recursive[(current, self)] = True obj = session._merge(current, load=load, _recursive=_recursive) - if obj is not None: - if not load: - dest_state.dict[self.key] = obj - else: - setattr(dest, self.key, obj) + else: + obj = None + + if not 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 e76e588d80..533c3ea5d1 100644 --- a/test/orm/test_merge.py +++ b/test/orm/test_merge.py @@ -456,6 +456,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_no_load(self): mapper(User, users) -- 2.47.3