From: Mike Bayer Date: Sun, 4 Apr 2010 15:08:00 +0000 (-0400) Subject: moving the per-states operations to be aggreagted on the endpoints to reduce X-Git-Tag: rel_0_6_0~63 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9916c0412e9442bda386154a3c71c06f4d6944e6;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git moving the per-states operations to be aggreagted on the endpoints to reduce procesing overhead. --- diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index 398bdd91cd..7359d85583 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -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) diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index fbb66a7dd2..96365397bd 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -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 diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index c8eca67eb7..359e1008b9 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -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):