summaryrefslogtreecommitdiff
path: root/lib/sqlalchemy/orm/unitofwork.py
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-04-01 16:00:57 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-04-01 16:00:57 -0400
commit67481476583d9dadd03f342cfa94628559a4c260 (patch)
treed727d0d402209a74e7ce2de86bd0437e48ce15bc /lib/sqlalchemy/orm/unitofwork.py
parentbef05275aa5410b14ef5fd70c0677b6ea48e168e (diff)
downloadsqlalchemy-67481476583d9dadd03f342cfa94628559a4c260.tar.gz
this version passes one to many tests so far
Diffstat (limited to 'lib/sqlalchemy/orm/unitofwork.py')
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py83
1 files changed, 55 insertions, 28 deletions
diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py
index d2f5946df..7bfac95b6 100644
--- a/lib/sqlalchemy/orm/unitofwork.py
+++ b/lib/sqlalchemy/orm/unitofwork.py
@@ -158,6 +158,9 @@ class UOWTransaction(object):
def execute(self):
+ # execute presort_actions, until all states
+ # have been processed. a presort_action might
+ # add new states to the uow.
while True:
ret = False
for action in self.presort_actions.values():
@@ -166,31 +169,44 @@ class UOWTransaction(object):
if not ret:
break
+ # see if the graph of mapper dependencies has cycles.
self.cycles = cycles = topological.find_cycles(self.dependencies, self.postsort_actions.values())
-
+
if cycles:
- convert = {}
- for rec in cycles:
- convert[rec] = set(rec.per_state_flush_actions(self))
-
- for edge in list(self.dependencies):
- # remove old dependencies between two cycle nodes,
- # splice dependencies for dependencies from/to cycle
- # nodes from non-cycle nodes
- if cycles.issuperset(edge):
- self.dependencies.remove(edge)
- elif edge[0] in cycles:
- for dep in convert[edge[0]]:
- self.dependencies.add((dep, edge[1]))
- elif edge[1] in cycles:
- for dep in convert[edge[1]]:
- self.dependencies.add((edge[0], dep))
-
+ # if yes, break the per-mapper actions into
+ # per-state actions
+ convert = dict(
+ (rec, set(rec.per_state_flush_actions(self)))
+ for rec in cycles
+ )
+
+ # rewrite the existing dependencies to point to
+ # the per-state actions for those per-mapper actions
+ # that were broken up.
+ for edge in list(self.dependencies):
+ if cycles.issuperset(edge):
+ self.dependencies.remove(edge)
+ elif edge[0] in cycles:
+ self.dependencies.remove(edge)
+ for dep in convert[edge[0]]:
+ self.dependencies.add((dep, edge[1]))
+ elif edge[1] in cycles:
+ self.dependencies.remove(edge)
+ for dep in convert[edge[1]]:
+ self.dependencies.add((edge[0], dep))
+
+ # remove actions that were part of the cycles,
+ # or have been marked as "disabled" by the "breaking up"
+ # process
+ for k, v in list(self.postsort_actions.items()):
+ if v.disabled or v in cycles:
+ del self.postsort_actions[k]
+
+ # execute actions
sort = topological.sort(self.dependencies, self.postsort_actions.values())
- print sort
+ #print self.dependencies
+ #print sort
for rec in sort:
- if rec in cycles:
- continue
rec.execute(self)
@@ -219,6 +235,8 @@ class PreSortRec(object):
return ret
class PostSortRec(object):
+ disabled = False
+
def __new__(cls, uow, *args):
key = (cls, ) + args
if key in uow.postsort_actions:
@@ -294,11 +312,6 @@ class ProcessAll(PropertyRecMixin, PostSortRec):
self.dependency_processor.process_saves(uow, states)
def per_state_flush_actions(self, uow):
- for state in self._elements(uow):
- if self.delete:
- self.dependency_processor.per_deleted_state_flush_actions(uow, state)
- else:
- self.dependency_processor.per_saved_state_flush_actions(uow, state)
return iter([])
class SaveUpdateAll(PostSortRec):
@@ -313,7 +326,8 @@ class SaveUpdateAll(PostSortRec):
def per_state_flush_actions(self, uow):
for state in uow.states_for_mapper_hierarchy(self.mapper, False, False):
- yield SaveUpdateState(uow, state)
+ for rec in self.mapper.per_state_flush_actions(uow, state, False):
+ yield rec
class DeleteAll(PostSortRec):
def __init__(self, uow, mapper):
@@ -327,7 +341,8 @@ class DeleteAll(PostSortRec):
def per_state_flush_actions(self, uow):
for state in uow.states_for_mapper_hierarchy(self.mapper, True, False):
- yield DeleteState(uow, state)
+ for rec in self.mapper.per_state_flush_actions(uow, state, True):
+ yield rec
class ProcessState(PostSortRec):
def __init__(self, uow, dependency_processor, delete, state):
@@ -352,6 +367,12 @@ class SaveUpdateState(PostSortRec):
uow
)
+ def __repr__(self):
+ return "%s(%s)" % (
+ self.__class__.__name__,
+ mapperutil.state_str(self.state)
+ )
+
class DeleteState(PostSortRec):
def __init__(self, uow, state):
self.state = state
@@ -363,3 +384,9 @@ class DeleteState(PostSortRec):
uow
)
+ def __repr__(self):
+ return "%s(%s)" % (
+ self.__class__.__name__,
+ mapperutil.state_str(self.state)
+ )
+