From: Mike Bayer Date: Sun, 6 Mar 2011 20:37:18 +0000 (-0500) Subject: - A tweak to the unit of work causes it to order X-Git-Tag: rel_0_7b3~41 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=438c31e6d50b5eb51920429a4ac61e84eed8828d;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git - A tweak to the unit of work causes it to order the flush along relationship() dependencies even if the given objects don't have any inter-attribute references in memory, which was the behavior in 0.5 and earlier, so a flush of Parent/Child with only foreign key/primary key set will succeed. This while still maintaining 0.6 and above's not generating a ton of useless internal dependency structures within the flush that don't correspond to state actually within the current flush. [ticket:2082] --- diff --git a/CHANGES b/CHANGES index 907bc4a03a..02dc1cbac2 100644 --- a/CHANGES +++ b/CHANGES @@ -17,6 +17,18 @@ CHANGES acquire the full list of objects in a single values() call. [ticket:2087] + - A tweak to the unit of work causes it to order + the flush along relationship() dependencies even if + the given objects don't have any inter-attribute + references in memory, which was the behavior in + 0.5 and earlier, so a flush of Parent/Child with + only foreign key/primary key set will succeed. + This while still maintaining 0.6 and above's not + generating a ton of useless internal dependency + structures within the flush that don't correspond + to state actually within the current flush. + [ticket:2082] + - sql - Added a fully descriptive error message for the case where Column is subclassed and _make_proxy() diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index 402d031c31..338ecfb55e 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -242,7 +242,9 @@ class DependencyProcessor(object): if history and not history.empty(): return True else: - return False + return states and \ + not self.prop._is_self_referential() and \ + self.mapper in uowcommit.mappers def _verify_canload(self, state): if state is not None and \ diff --git a/test/orm/test_unitofworkv2.py b/test/orm/test_unitofworkv2.py index 20b643b4de..4063ccfabc 100644 --- a/test/orm/test_unitofworkv2.py +++ b/test/orm/test_unitofworkv2.py @@ -400,6 +400,77 @@ class RudimentaryFlushTest(UOWTest): ), ) + def test_natural_ordering(self): + """test that unconnected items take relationship() into account regardless.""" + + mapper(User, users) + mapper(Address, addresses, properties={ + 'parent':relationship(User) + }) + + sess = create_session() + + u1 = User(id=1, name='u1') + a1 = Address(id=1, user_id=1, email_address='a2') + + sess.add_all([u1, a1]) + self.assert_sql_execution( + testing.db, + sess.flush, + CompiledSQL( + "INSERT INTO users (id, name) VALUES (:id, :name)", + {'id':1, 'name':'u1'}), + CompiledSQL( + "INSERT INTO addresses (id, user_id, email_address) " + "VALUES (:id, :user_id, :email_address)", + {'email_address': 'a2', 'user_id': 1, 'id': 1} + ) + ) + + sess.delete(u1) + sess.delete(a1) + self.assert_sql_execution( + testing.db, + sess.flush, + CompiledSQL( + "DELETE FROM addresses WHERE addresses.id = :id", + [{'id': 1}] + ), + CompiledSQL( + "DELETE FROM users WHERE users.id = :id", + [{'id': 1}] + ) + ) + + def test_natural_selfref(self): + """test that unconnected items take relationship() into account regardless.""" + + mapper(Node, nodes, properties={ + 'children':relationship(Node) + }) + + sess = create_session() + + n1 = Node(id=1) + n2 = Node(id=2, parent_id=1) + n3 = Node(id=3, parent_id=2) + + # insert order is determined from add order since they + # are the same class + sess.add_all([n1, n2, n3]) + + self.assert_sql_execution( + testing.db, + sess.flush, + CompiledSQL( + "INSERT INTO nodes (id, parent_id, data) VALUES " + "(:id, :parent_id, :data)", + [{'parent_id': None, 'data': None, 'id': 1}, + {'parent_id': 1, 'data': None, 'id': 2}, + {'parent_id': 2, 'data': None, 'id': 3}] + ), + ) + def test_many_to_many(self): mapper(Item, items, properties={ 'keywords':relationship(Keyword, secondary=item_keywords)