From b1635e3d6ee9ce959b1ef3806a6fc9799bcb7c70 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Tue, 4 Jan 2011 10:56:48 -0500 Subject: [PATCH] merge r8343809aca9d, fix for [ticket:2013] --- CHANGES | 4 ++++ lib/sqlalchemy/orm/dependency.py | 17 +++++++++------- lib/sqlalchemy/orm/unitofwork.py | 2 +- test/orm/test_unitofwork.py | 33 +++++++++++++++++++++++--------- 4 files changed, 39 insertions(+), 17 deletions(-) diff --git a/CHANGES b/CHANGES index 50bcdce6b4..4fa60983c0 100644 --- a/CHANGES +++ b/CHANGES @@ -14,6 +14,10 @@ CHANGES that weren't previously saved in the "mutable changes" dictionary. + - Fixed bug whereby "passive_deletes='all'" wasn't passing + the correct symbols to lazy loaders during flush, thereby + causing an unwarranted load. [ticket:2013] + - Fixed bug which prevented composite mapped attributes from being used on a mapped select statement. [ticket:1997]. Note the workings of composite are slated to diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index bc38e9ef24..11f8fc48b0 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -26,6 +26,9 @@ class DependencyProcessor(object): self.passive_deletes = prop.passive_deletes self.passive_updates = prop.passive_updates self.enable_typechecks = prop.enable_typechecks + self._passive_delete_flag = self.passive_deletes and \ + attributes.PASSIVE_NO_INITIALIZE or \ + attributes.PASSIVE_OFF self.key = prop.key if not self.prop.synchronize_pairs: raise sa_exc.ArgumentError( @@ -394,7 +397,7 @@ class OneToManyDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: for child in history.deleted: if child is not None and self.hasparent(child) is False: @@ -461,7 +464,7 @@ class OneToManyDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: for child in history.deleted: if child is not None and \ @@ -641,7 +644,7 @@ class ManyToOneDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: if self.cascade.delete_orphan: todelete = history.sum() @@ -663,7 +666,7 @@ class ManyToOneDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: ret = True for child in history.deleted: @@ -689,7 +692,7 @@ class ManyToOneDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: self._post_update(state, uowcommit, history.sum()) @@ -888,7 +891,7 @@ class ManyToManyDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) def presort_saves(self, uowcommit, states): if not self.passive_updates: @@ -935,7 +938,7 @@ class ManyToManyDP(DependencyProcessor): history = uowcommit.get_attribute_history( state, self.key, - passive=self.passive_deletes) + passive=self._passive_delete_flag) if history: for child in history.non_added(): if child is None or \ diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 66b5bb0226..7da87119c6 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -143,7 +143,7 @@ class UOWTransaction(object): self.states[state] = (isdelete, True) - def get_attribute_history(self, state, key, passive=True): + def get_attribute_history(self, state, key, passive=attributes.PASSIVE_NO_INITIALIZE): """facade to attributes.get_state_history(), including caching of results.""" hashkey = ("history", state, key) diff --git a/test/orm/test_unitofwork.py b/test/orm/test_unitofwork.py index a10fb216e9..8484949548 100644 --- a/test/orm/test_unitofwork.py +++ b/test/orm/test_unitofwork.py @@ -892,16 +892,14 @@ class ExtraPassiveDeletesTest(_base.MappedTest): @testing.resolve_artifact_names def test_assertions(self): mapper(MyOtherClass, myothertable) - try: - mapper(MyClass, mytable, properties={ - 'children':relationship(MyOtherClass, + assert_raises_message( + sa.exc.ArgumentError, + "Can't set passive_deletes='all' in conjunction with 'delete' " + "or 'delete-orphan' cascade", + relationship, MyOtherClass, passive_deletes='all', - cascade="all")}) - assert False - except sa.exc.ArgumentError, e: - eq_(str(e), - "Can't set passive_deletes='all' in conjunction with 'delete' " - "or 'delete-orphan' cascade") + cascade="all" + ) @testing.resolve_artifact_names def test_extra_passive(self): @@ -948,6 +946,23 @@ class ExtraPassiveDeletesTest(_base.MappedTest): mc.children[0].data = 'some new data' assert_raises(sa.exc.DBAPIError, session.flush) + @testing.resolve_artifact_names + def test_dont_emit(self): + mapper(MyOtherClass, myothertable) + mapper(MyClass, mytable, properties={ + 'children': relationship(MyOtherClass, + passive_deletes='all', + cascade="save-update")}) + session = Session() + mc = MyClass() + session.add(mc) + session.commit() + mc.id + + session.delete(mc) + + # no load for "children" should occur + self.assert_sql_count(testing.db, session.flush, 1) class ColumnCollisionTest(_base.MappedTest): """Ensure the mapper doesn't break bind param naming rules on flush.""" -- 2.47.2