From 3757034d2de03f23dabb9456d773e34b8b09edb0 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Fri, 4 May 2012 19:27:57 -0400 Subject: [PATCH] - [bug] Fixed issue in unit of work whereby setting a non-None self-referential many-to-one relationship to None would fail to persist the change if the former value was not already loaded. [ticket:2477]. --- CHANGES | 7 +++++++ lib/sqlalchemy/orm/attributes.py | 2 +- test/orm/test_unitofworkv2.py | 25 +++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 0c47aa66e6..0be1dc951b 100644 --- a/CHANGES +++ b/CHANGES @@ -71,6 +71,13 @@ CHANGES set of objects that weren't modified in that sub-transaction. [ticket:2452] + - [bug] Fixed issue in unit of work + whereby setting a non-None self-referential + many-to-one relationship to None + would fail to persist the change if the + former value was not already loaded. + [ticket:2477]. Also in 0.7.7 + - [bug] Fixed bug in relationship comparisons whereby calling unimplemented methods like SomeClass.somerelationship.like() would diff --git a/lib/sqlalchemy/orm/attributes.py b/lib/sqlalchemy/orm/attributes.py index 7625ccead6..00d640066a 100644 --- a/lib/sqlalchemy/orm/attributes.py +++ b/lib/sqlalchemy/orm/attributes.py @@ -627,7 +627,7 @@ class ScalarObjectAttributeImpl(ScalarAttributeImpl): if current is not None: ret = [(instance_state(current), current)] else: - ret = [] + ret = [(None, None)] if self.key in state.committed_state: original = state.committed_state[self.key] diff --git a/test/orm/test_unitofworkv2.py b/test/orm/test_unitofworkv2.py index d7e2150db5..cfd36e696d 100644 --- a/test/orm/test_unitofworkv2.py +++ b/test/orm/test_unitofworkv2.py @@ -777,6 +777,31 @@ class SingleCycleTest(UOWTest): lambda ctx: {'id':n1.id}) ) + def test_many_to_one_set_null_unloaded(self): + Node, nodes = self.classes.Node, self.tables.nodes + + mapper(Node, nodes, properties={ + 'parent':relationship(Node, remote_side=nodes.c.id) + }) + sess = create_session() + n1 = Node(data='n1') + n2 = Node(data='n2', parent=n1) + sess.add_all([n1, n2]) + sess.flush() + sess.close() + + n2 = sess.query(Node).filter_by(data='n2').one() + n2.parent = None + self.assert_sql_execution( + testing.db, + sess.flush, + CompiledSQL( + "UPDATE nodes SET parent_id=:parent_id WHERE " + "nodes.id = :nodes_id", + lambda ctx: {"parent_id":None, "nodes_id":n2.id} + ) + ) + def test_cycle_rowswitch(self): Node, nodes = self.classes.Node, self.tables.nodes -- 2.47.3