]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
refined system bywhich dependencyprocessor per-state actions
authorMike Bayer <mike_mp@zzzcomputing.com>
Fri, 9 Apr 2010 17:57:49 +0000 (13:57 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Fri, 9 Apr 2010 17:57:49 +0000 (13:57 -0400)
are established

lib/sqlalchemy/orm/dependency.py
lib/sqlalchemy/orm/mapper.py
lib/sqlalchemy/orm/unitofwork.py
test/orm/test_unitofworkv2.py

index d94c6b43f54fba576986bf197c02336d667de942..dfcddacaa215c641879d70ea115da9b9404de2a2 100644 (file)
@@ -115,16 +115,12 @@ class DependencyProcessor(object):
         
         """
 
-        # TODO: this check sucks.  somehow get mapper to 
-        # not even call this.
-        if ('has_flush_activity', self) not in uow.attributes:
-            return
+        # assertions to ensure this method isn't being
+        # called unnecessarily.  can comment these out when 
+        # code is stable
+        assert ('has_flush_activity', self) in uow.attributes
+        assert not self.post_update or not self._check_reverse(uow)
         
-        # TODO: why are we calling this ? shouldnt per_property
-        # have stopped us from getting keyhere ?
-        if self.post_update and self._check_reverse(uow):
-            # TODO: coverage here
-            return
 
         # locate and disable the aggregate processors
         # for this dependency
index 0ea0342c40067ef193361338ae4837242a4d6daf..72bc8ee317731e1ec8e69703e13eb7391a44a17a 100644 (file)
@@ -1265,31 +1265,8 @@ class Mapper(object):
         for prop in self._props.values():
             prop.per_property_flush_actions(uow)
     
-    def _property_iterator(self, mappers):
-        """return an iterator of all MapperProperty objects
-        and a list containing all mappers which use that property,
-        descending through the polymorphic hierarchy of this
-        mapper.
-
-        'mappers' is a set which will limit the traversal
-        to just those mappers.
-
-        """
-        props = set()
-        for mapper in self.polymorphic_iterator():
-            if mapper not in mappers:
-                continue
-
-            for prop in mapper._props.values():
-                if prop not in props:
-                    props.add(prop)
-                    yield prop, [m for m in mappers 
-                                    if m._props.get(prop.key) is prop]
-
     def _per_state_flush_actions(self, uow, states, isdelete):
         
-        mappers_to_states = util.defaultdict(set)
-        
         base_mapper = self.base_mapper
         save_all = unitofwork.SaveUpdateAll(uow, base_mapper)
         delete_all = unitofwork.DeleteAll(uow, base_mapper)
@@ -1303,19 +1280,8 @@ class Mapper(object):
                 action = unitofwork.SaveUpdateState(uow, state, base_mapper)
                 uow.dependencies.add((action, delete_all))
             
-            mappers_to_states[state.manager.mapper].add(state)
             yield action
         
-        # TODO: can't we just loop through the frigging entries 
-        # that are already in the uow instead of this goofy 
-        # polymorphic BS ?
-        for prop, mappers in self._property_iterator(set(mappers_to_states)):
-            states_for_prop = []
-            for mapper in mappers:
-                states_for_prop += list(mappers_to_states[mapper])
-            
-            prop.per_state_flush_actions(uow, states_for_prop, isdelete)
-        
     def _save_obj(self, states, uowtransaction, postupdate=False, 
                                 post_update_cols=None, single=False):
         """Issue ``INSERT`` and/or ``UPDATE`` statements for a list of objects.
index bdfaa008b273c722b7535384ffdeeac3b6d8a1c9..c93f8af200ccb1bc72078b90d400992debb8d7f1 100644 (file)
@@ -79,6 +79,7 @@ class UOWTransaction(object):
         # information.
         self.attributes = {}
         
+        self.deps = util.defaultdict(set)
         self.mappers = util.defaultdict(set)
         self.presort_actions = {}
         self.postsort_actions = {}
@@ -146,6 +147,16 @@ class UOWTransaction(object):
                     postupdate=True, \
                     post_update_cols=set(post_update_cols))
     
+    @util.memoized_property
+    def _mapper_for_dep(self):
+        return util.PopulateDict(
+                    lambda tup:tup[0]._props.get(tup[1].key) is tup[1].prop
+                )
+    
+    def filter_states_for_dep(self, dep, states):
+        mapper_for_dep = self._mapper_for_dep
+        return [s for s in states if mapper_for_dep[(s.manager.mapper, dep)]]
+        
     def states_for_mapper(self, mapper, isdelete, listonly):
         checktup = (isdelete, listonly)
         for state in self.mappers[mapper]:
@@ -341,6 +352,10 @@ class GetDependentObjects(PropertyRecMixin, PreSortRec):
             return False
 
 class ProcessAll(PropertyRecMixin, PostSortRec):
+    def __init__(self, uow, *args):
+        super(ProcessAll, self).__init__(uow, *args)
+        uow.deps[self.dependency_processor.parent.base_mapper].add(self.dependency_processor)
+        
     def execute(self, uow):
         states = list(self._elements(uow))
         if self.delete:
@@ -368,11 +383,16 @@ class SaveUpdateAll(PostSortRec):
         )
     
     def per_state_flush_actions(self, uow):
+        states = list(uow.states_for_mapper_hierarchy(self.mapper, False, False))
         for rec in self.mapper._per_state_flush_actions(
                             uow, 
-                            uow.states_for_mapper_hierarchy(self.mapper, False, False)
+                            states
                             False):
             yield rec
+            
+        for dep in uow.deps[self.mapper]:
+            states_for_prop = uow.filter_states_for_dep(dep, states)
+            dep.per_state_flush_actions(uow, states_for_prop, False)
         
 class DeleteAll(PostSortRec):
     def __init__(self, uow, mapper):
@@ -386,11 +406,16 @@ class DeleteAll(PostSortRec):
         )
 
     def per_state_flush_actions(self, uow):
+        states = list(uow.states_for_mapper_hierarchy(self.mapper, True, False))
         for rec in self.mapper._per_state_flush_actions(
                             uow, 
-                            uow.states_for_mapper_hierarchy(self.mapper, True, False)
+                            states
                             True):
             yield rec
+            
+        for dep in uow.deps[self.mapper]:
+            states_for_prop = uow.filter_states_for_dep(dep, states)
+            dep.per_state_flush_actions(uow, states_for_prop, True)
 
 class ProcessState(PostSortRec):
     def __init__(self, uow, dependency_processor, delete, state):
index e9183297d27f8a875aa1602ec95b66bc1d995dcd..728cdfd7bb6f3c0266228eab6c3604898902ee2d 100644 (file)
@@ -466,7 +466,7 @@ class SingleCycleTest(UOWTest):
     
         n1.children.append(n2)
 
-        self._assert_uow_size(sess, 4)
+        self._assert_uow_size(sess, 3)
     
         sess.flush()
     
@@ -476,7 +476,7 @@ class SingleCycleTest(UOWTest):
         self._assert_uow_size(sess, 2)
     
         n1.children
-        self._assert_uow_size(sess, 3)
+        self._assert_uow_size(sess, 2)
 
 class SingleCycleM2MTest(_base.MappedTest, testing.AssertsExecutionResults):