]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
working through cycles tests...
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Apr 2010 23:06:35 +0000 (19:06 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 1 Apr 2010 23:06:35 +0000 (19:06 -0400)
lib/sqlalchemy/orm/dependency.py
lib/sqlalchemy/orm/unitofwork.py
test/orm/test_cycles.py

index 973036639a60ee5f563183e73c8a5e3ca2424146..df9213d3e65d715613c51ff3e35b936358307001 100644 (file)
@@ -79,52 +79,62 @@ class DependencyProcessor(object):
                                         before_delete)
 
     def per_state_flush_actions(self, uow, state, isdelete):
-        if True:
-            if not isdelete:
-                parent_saves = unitofwork.SaveUpdateAll(uow, self.parent)
-                child_saves = unitofwork.SaveUpdateAll(uow, self.mapper)
-                assert parent_saves in uow.cycles
-                assert child_saves in uow.cycles
-            else:
-                parent_deletes = unitofwork.DeleteAll(uow, self.parent)
-                child_deletes = unitofwork.DeleteAll(uow, self.mapper)
-                assert parent_deletes in uow.cycles
-                assert child_deletes in uow.cycles
-
         after_save = unitofwork.ProcessAll(uow, self, False, True)
         before_delete = unitofwork.ProcessAll(uow, self, True, True)
         after_save.disabled = True
         before_delete.disabled = True
 
-        sum_ = uow.get_attribute_history(state, self.key, passive=True).sum()
-        if not sum_:
-            return
-
+        # check if the "child" side is part of the cycle
+        child_saves = unitofwork.SaveUpdateAll(uow, self.mapper)
+        child_deletes = unitofwork.DeleteAll(uow, self.mapper)
+        if child_saves not in uow.cycles:
+            assert child_deletes not in uow.cycles
+            # its not, so we will link per-state
+            # actions to the aggregate "saves", "deletes" actions
+            child_actions = [
+                child_saves, child_deletes
+            ]
+        else:
+            # it is.  see if there's any objects.
+            sum_ = uow.get_attribute_history(state, self.key, passive=True).sum()
+            if not sum_:
+                return
+            child_actions = []
+            for child_state in sum_:
+                if child_state is None or child_state not in uow.states:
+                    continue
+                (deleted, listonly) = uow.states[child_state]
+                if deleted:
+                    child_action = unitofwork.DeleteState(uow, child_state)
+                else:
+                    child_action = unitofwork.SaveUpdateState(uow, child_state)
+                child_actions.append(child_action)
+                    
+        # check if the "parent" side is part of the cycle,
+        # if so break up parent_saves
         if not isdelete:
-            save_parent = unitofwork.SaveUpdateState(uow, state)
+            parent_saves = unitofwork.SaveUpdateAll(uow, self.parent)
+            if parent_saves in uow.cycles:
+                parent_saves = unitofwork.SaveUpdateState(uow, state)
+                
             after_save = unitofwork.ProcessState(uow, self, False, state)
             yield after_save
             
-            delete_parent = before_delete = None
+            parent_deletes = before_delete = None
         else:
-            delete_parent = unitofwork.DeleteState(uow, state)
+            parent_deletes = unitofwork.DeleteAll(uow, self.parent)
+            if parent_deletes in uow.cycles:
+                parent_deletes = unitofwork.DeleteState(uow, state)
             before_delete = unitofwork.ProcessState(uow, self, True, state)
             yield before_delete
             
-            save_parent = after_save = None
-
-        for child_state in sum_:
-            if child_state is None:
-                continue
-
-            (deleted, listonly) = uow.states[child_state]
-            if deleted:
-                child_action = unitofwork.DeleteState(uow, child_state)
-            else:
-                child_action = unitofwork.SaveUpdateState(uow, child_state)
-
-            self.per_state_dependencies(uow, save_parent, 
-                                            delete_parent, 
+            parent_saves = after_save = None
+        
+        # establish dependencies between our possibly per-state
+        # parent action and our possibly per-state child action.
+        for child_action in child_actions:
+            self.per_state_dependencies(uow, parent_saves, 
+                                            parent_deletes, 
                                             child_action, 
                                             after_save, before_delete, isdelete)
 
index 4dd9878d511cca9b9908a85f4ce74668ddfda59d..3118e0b9f9e49108f25e961cba75d73dbcaebfe4 100644 (file)
@@ -145,15 +145,15 @@ class UOWTransaction(object):
     
     def states_for_mapper(self, mapper, isdelete, listonly):
         checktup = (isdelete, listonly)
-        for state, tup in self.states.iteritems():
-            if tup == checktup:
+        for state in self.mappers[mapper]:
+            if self.states[state] == checktup:
                 yield state
 
     def states_for_mapper_hierarchy(self, mapper, isdelete, listonly):
         checktup = (isdelete, listonly)
         for mapper in mapper.base_mapper.polymorphic_iterator():
-            for state, tup in self.states.iteritems():
-                if tup == checktup:
+            for state in self.mappers[mapper]:
+                if self.states[state] == checktup:
                     yield state
                 
     def execute(self):
index c197cb627c14b900140bad96c5576bb260906dd0..e728f876a96ec8bc6862ba5066e57de485cd0027 100644 (file)
@@ -41,7 +41,7 @@ class SelfReferentialTest(_base.MappedTest):
                 self.data = data
 
     @testing.resolve_artifact_names
-    def testsingle(self):
+    def test_single(self):
         mapper(C1, t1, properties = {
             'c1s':relationship(C1, cascade="all"),
             'parent':relationship(C1,
@@ -59,17 +59,12 @@ class SelfReferentialTest(_base.MappedTest):
         sess.flush()
 
     @testing.resolve_artifact_names
-    def testmanytooneonly(self):
+    def test_many_to_one_only(self):
         """
 
         test that the circular dependency sort can assemble a many-to-one
         dependency processor when only the object on the "many" side is
-        actually in the list of modified objects.  this requires that the
-        circular sort add the other side of the relationship into the
-        UOWTransaction so that the dependency operation can be tacked onto it.
-
-        This also affects inheritance relationships since they rely upon
-        circular sort as well.
+        actually in the list of modified objects.  
 
         """
         mapper(C1, t1, properties={
@@ -91,7 +86,7 @@ class SelfReferentialTest(_base.MappedTest):
         assert c2.parent_c1==c1.c1
 
     @testing.resolve_artifact_names
-    def testcycle(self):
+    def test_cycle(self):
         mapper(C1, t1, properties = {
             'c1s' : relationship(C1, cascade="all"),
             'c2s' : relationship(mapper(C2, t2), cascade="all, delete-orphan")})