diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py index df9213d3e6..0c3c532d9f 100644 --- a/lib/sqlalchemy/orm/dependency.py +++ b/lib/sqlalchemy/orm/dependency.py @@ -64,11 +64,11 @@ class DependencyProcessor(object): after_save = unitofwork.ProcessAll(uow, self, False, True) before_delete = unitofwork.ProcessAll(uow, self, True, True) - parent_saves = unitofwork.SaveUpdateAll(uow, self.parent) - child_saves = unitofwork.SaveUpdateAll(uow, self.mapper) + parent_saves = unitofwork.SaveUpdateAll(uow, self.parent.base_mapper) + child_saves = unitofwork.SaveUpdateAll(uow, self.mapper.base_mapper) - parent_deletes = unitofwork.DeleteAll(uow, self.parent) - child_deletes = unitofwork.DeleteAll(uow, self.mapper) + parent_deletes = unitofwork.DeleteAll(uow, self.parent.base_mapper) + child_deletes = unitofwork.DeleteAll(uow, self.mapper.base_mapper) self.per_property_dependencies(uow, parent_saves, @@ -85,8 +85,8 @@ class DependencyProcessor(object): before_delete.disabled = True # check if the "child" side is part of the cycle - child_saves = unitofwork.SaveUpdateAll(uow, self.mapper) - child_deletes = unitofwork.DeleteAll(uow, self.mapper) + child_saves = unitofwork.SaveUpdateAll(uow, self.mapper.base_mapper) + child_deletes = unitofwork.DeleteAll(uow, self.mapper.base_mapper) if child_saves not in uow.cycles: assert child_deletes not in uow.cycles # its not, so we will link per-state @@ -101,19 +101,22 @@ class DependencyProcessor(object): return child_actions = [] for child_state in sum_: - if child_state is None or child_state not in uow.states: + if child_state is None: continue - (deleted, listonly) = uow.states[child_state] - if deleted: - child_action = unitofwork.DeleteState(uow, child_state) + if child_state not in uow.states: + child_action = None else: - child_action = unitofwork.SaveUpdateState(uow, child_state) + (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: - parent_saves = unitofwork.SaveUpdateAll(uow, self.parent) + parent_saves = unitofwork.SaveUpdateAll(uow, self.parent.base_mapper) if parent_saves in uow.cycles: parent_saves = unitofwork.SaveUpdateState(uow, state) @@ -122,7 +125,7 @@ class DependencyProcessor(object): parent_deletes = before_delete = None else: - parent_deletes = unitofwork.DeleteAll(uow, self.parent) + parent_deletes = unitofwork.DeleteAll(uow, self.parent.base_mapper) if parent_deletes in uow.cycles: parent_deletes = unitofwork.DeleteState(uow, state) before_delete = unitofwork.ProcessState(uow, self, True, state) diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py index 9a18bd4cf6..22b5e5177a 100644 --- a/lib/sqlalchemy/orm/mapper.py +++ b/lib/sqlalchemy/orm/mapper.py @@ -1269,7 +1269,8 @@ class Mapper(object): action = unitofwork.SaveUpdateState(uow, state) yield action - for prop in self._props.values(): + mapper = state.manager.mapper + for prop in mapper._props.values(): for rec in prop.per_state_flush_actions(uow, state, isdelete): yield rec diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py index 3118e0b9f9..76cdde6358 100644 --- a/lib/sqlalchemy/orm/unitofwork.py +++ b/lib/sqlalchemy/orm/unitofwork.py @@ -170,7 +170,9 @@ class UOWTransaction(object): break # see if the graph of mapper dependencies has cycles. - self.cycles = cycles = topological.find_cycles(self.dependencies, self.postsort_actions.values()) + self.cycles = cycles = topological.find_cycles( + self.dependencies, + self.postsort_actions.values()) if cycles: # if yes, break the per-mapper actions into @@ -184,7 +186,9 @@ class UOWTransaction(object): # the per-state actions for those per-mapper actions # that were broken up. for edge in list(self.dependencies): - if cycles.issuperset(edge): + if None in edge: + self.dependencies.remove(edge) + elif cycles.issuperset(edge): self.dependencies.remove(edge) elif edge[0] in cycles: self.dependencies.remove(edge) @@ -317,7 +321,8 @@ class ProcessAll(PropertyRecMixin, PostSortRec): class SaveUpdateAll(PostSortRec): def __init__(self, uow, mapper): self.mapper = mapper - + assert mapper is mapper.base_mapper + def execute(self, uow): self.mapper._save_obj( uow.states_for_mapper_hierarchy(self.mapper, False, False), @@ -332,6 +337,7 @@ class SaveUpdateAll(PostSortRec): class DeleteAll(PostSortRec): def __init__(self, uow, mapper): self.mapper = mapper + assert mapper is mapper.base_mapper def execute(self, uow): self.mapper._delete_obj(