]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
moving the per-states operations to be aggreagted on the endpoints to reduce
authorMike Bayer <mike_mp@zzzcomputing.com>
Sun, 4 Apr 2010 15:08:00 +0000 (11:08 -0400)
committerMike Bayer <mike_mp@zzzcomputing.com>
Sun, 4 Apr 2010 15:08:00 +0000 (11:08 -0400)
procesing overhead.

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

index 398bdd91cd6f003efd0c84e0402c7403a6828fbf..7359d855836117ce2b28cbed8d46de12a5832568 100644 (file)
@@ -78,7 +78,12 @@ class DependencyProcessor(object):
                                         after_save, 
                                         before_delete)
 
-    def per_state_flush_actions(self, uow, state, isdelete):
+    def per_state_flush_actions(self, uow, states, isdelete):
+        for state in states:
+            for rec in self._per_state_flush_actions(uow, state, isdelete):
+                yield rec
+                
+    def _per_state_flush_actions(self, uow, state, isdelete):
         # locate and disable the aggregate processors
         # for this dependency
         after_save = unitofwork.ProcessAll(uow, self, False, True)
index fbb66a7dd27bcc88ebfc1a5edb0af55998cc915e..96365397bd017bf2a9e2da2cff1d4081401775d0 100644 (file)
@@ -1062,6 +1062,7 @@ class Mapper(object):
             item = stack.popleft()
             yield item
             stack.extend(item._inheriting_mappers)
+    
 
     def primary_mapper(self):
         """Return the primary mapper corresponding to this mapper's class key (class)."""
@@ -1247,15 +1248,6 @@ class Mapper(object):
             ret[t] = table_to_mapper[t]
         return ret
 
-    @util.memoized_property
-    def _sorted_table_list(self):
-        l = []
-        for mapper in self.base_mapper.polymorphic_iterator():
-            for t in mapper.tables:
-                l.append(t)
-        
-        return sqlutil.sort_tables(l)
-        
     def per_mapper_flush_actions(self, uow):
         saves = unitofwork.SaveUpdateAll(uow, self.base_mapper)
         deletes = unitofwork.DeleteAll(uow, self.base_mapper)
@@ -1264,20 +1256,51 @@ class Mapper(object):
         for prop in self._props.values():
             prop.per_property_flush_actions(uow)
     
-    def per_state_flush_actions(self, uow, state, isdelete):
-        # keep saves before deletes -
-        # this ensures 'row switch' operations work
-        if isdelete:
-            action = unitofwork.DeleteState(uow, state)
-            uow.dependencies.add((unitofwork.SaveUpdateAll(uow, self.base_mapper), action))
-        else:
-            action = unitofwork.SaveUpdateState(uow, state)
-            uow.dependencies.add((action, unitofwork.DeleteAll(uow, self.base_mapper)))
+    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[prop.key] is prop]
+
+    def per_state_flush_actions(self, uow, states, isdelete):
+        
+        mappers_to_states = util.defaultdict(set)
+        
+        save_all = unitofwork.SaveUpdateAll(uow, self.base_mapper)
+        delete_all = unitofwork.DeleteAll(uow, self.base_mapper)
+        for state in states:
+            # keep saves before deletes -
+            # this ensures 'row switch' operations work
+            if isdelete:
+                action = unitofwork.DeleteState(uow, state)
+                uow.dependencies.add((save_all, action))
+            else:
+                action = unitofwork.SaveUpdateState(uow, state)
+                uow.dependencies.add((action, delete_all))
             
-        yield action
-        mapper = state.manager.mapper
-        for prop in mapper._props.values():
-            for rec in prop.per_state_flush_actions(uow, state, isdelete):
+            mappers_to_states[state.manager.mapper].add(state)
+            yield action
+        
+        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])
+                
+            for rec in prop.per_state_flush_actions(uow, states_for_prop, isdelete):
                 yield rec
         
         
index c8eca67eb7ee232bc4a38a77604f77a096ece84d..359e1008b9a0a7d5367f824e5e4752b42891a675 100644 (file)
@@ -338,9 +338,11 @@ class SaveUpdateAll(PostSortRec):
         )
     
     def per_state_flush_actions(self, uow):
-        for state in uow.states_for_mapper_hierarchy(self.mapper, False, False):
-            for rec in self.mapper.per_state_flush_actions(uow, state, False):
-                yield rec
+        for rec in self.mapper.per_state_flush_actions(
+                            uow, 
+                            uow.states_for_mapper_hierarchy(self.mapper, False, False), 
+                            False):
+            yield rec
         
 class DeleteAll(PostSortRec):
     def __init__(self, uow, mapper):
@@ -354,9 +356,11 @@ class DeleteAll(PostSortRec):
         )
 
     def per_state_flush_actions(self, uow):
-        for state in uow.states_for_mapper_hierarchy(self.mapper, True, False):
-            for rec in self.mapper.per_state_flush_actions(uow, state, True):
-                yield rec
+        for rec in self.mapper.per_state_flush_actions(
+                            uow, 
+                            uow.states_for_mapper_hierarchy(self.mapper, True, False), 
+                            True):
+            yield rec
 
 class ProcessState(PostSortRec):
     def __init__(self, uow, dependency_processor, delete, state):