summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorMike Bayer <mike_mp@zzzcomputing.com>2010-04-03 19:41:56 -0400
committerMike Bayer <mike_mp@zzzcomputing.com>2010-04-03 19:41:56 -0400
commit3d3095497b872696e8860763f54217f425c7d35b (patch)
tree72aa4f6b477affde2139bb6616845bc6f04d6364 /lib
parent85156a0fbe43f8691e19c077c92b0d433f9e654b (diff)
downloadsqlalchemy-3d3095497b872696e8860763f54217f425c7d35b.tar.gz
row switch works for post-cycle sorts too...just needed more data in the deps. the pattern here
is more data needed for each tweak.
Diffstat (limited to 'lib')
-rw-r--r--lib/sqlalchemy/orm/dependency.py14
-rw-r--r--lib/sqlalchemy/orm/mapper.py8
-rw-r--r--lib/sqlalchemy/orm/unitofwork.py27
3 files changed, 26 insertions, 23 deletions
diff --git a/lib/sqlalchemy/orm/dependency.py b/lib/sqlalchemy/orm/dependency.py
index 86cac2d87..398bdd91c 100644
--- a/lib/sqlalchemy/orm/dependency.py
+++ b/lib/sqlalchemy/orm/dependency.py
@@ -79,6 +79,8 @@ class DependencyProcessor(object):
before_delete)
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)
before_delete = unitofwork.ProcessAll(uow, self, True, True)
after_save.disabled = True
@@ -88,14 +90,20 @@ class DependencyProcessor(object):
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:
+ # based on the current dependencies we use, the saves/
+ # deletes should always be in the 'cycles' collection
+ # together. if this changes, we will have to break up
+ # this method a bit more.
assert child_deletes not in uow.cycles
- # its not, so we will link per-state
+
+ # child side is not part of the cycle, so we will link per-state
# actions to the aggregate "saves", "deletes" actions
child_actions = [
(child_saves, False), (child_deletes, True)
]
else:
- # it is. see if there's any objects.
+ # child side is part of the cycle. create dependencies for
+ # each related object.
sum_ = uow.get_attribute_history(state, self.key, passive=True).sum()
if not sum_:
return
@@ -114,7 +122,7 @@ class DependencyProcessor(object):
child_actions.append(child_action)
# check if the "parent" side is part of the cycle,
- # if so break up parent_saves
+ # if so break up parent_saves or parent_deletes
if not isdelete:
parent_saves = unitofwork.SaveUpdateAll(uow, self.parent.base_mapper)
if parent_saves in uow.cycles:
diff --git a/lib/sqlalchemy/orm/mapper.py b/lib/sqlalchemy/orm/mapper.py
index 319b06158..ac35ce49b 100644
--- a/lib/sqlalchemy/orm/mapper.py
+++ b/lib/sqlalchemy/orm/mapper.py
@@ -1263,11 +1263,15 @@ class Mapper(object):
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)))
+
yield action
mapper = state.manager.mapper
for prop in mapper._props.values():
@@ -1354,7 +1358,7 @@ class Mapper(object):
self._log_debug(
"detected row switch for identity %s. will update %s, remove %s from "
"transaction", instance_key, state_str(state), state_str(existing))
-
+
# remove the "delete" flag from the existing element
uowtransaction.remove_state_actions(existing)
row_switches[state] = existing
diff --git a/lib/sqlalchemy/orm/unitofwork.py b/lib/sqlalchemy/orm/unitofwork.py
index a4eb00f70..c8eca67eb 100644
--- a/lib/sqlalchemy/orm/unitofwork.py
+++ b/lib/sqlalchemy/orm/unitofwork.py
@@ -105,15 +105,7 @@ class UOWTransaction(object):
def remove_state_actions(self, state):
"""remove pending actions for a state from the uowtransaction."""
- if state in self.states:
- isdelete, listonly = self.states[state]
- self.states[state] = (False, True)
- if isdelete:
- self.postsort_actions.pop((DeleteState, state), None)
- else:
- self.postsort_actions.pop((SaveUpdateState, state), None)
-
-
+ self.states[state] = (False, True)
def get_attribute_history(self, state, key, passive=True):
hashkey = ("history", state, key)
@@ -223,11 +215,9 @@ class UOWTransaction(object):
# execute actions
sort = topological.sort(self.dependencies, self.postsort_actions.values())
- print "------------------------"
-# import pdb
-# pdb.set_trace()
- print self.dependencies
- print sort
+# print "------------------------"
+# print self.dependencies
+# print sort
for rec in sort:
rec.execute(self)
@@ -411,10 +401,11 @@ class DeleteState(PostSortRec):
def execute(self, uow):
mapper = self.state.manager.mapper.base_mapper
- mapper._delete_obj(
- [self.state],
- uow
- )
+ if uow.states[self.state][0]:
+ mapper._delete_obj(
+ [self.state],
+ uow
+ )
def __repr__(self):
return "%s(%s)" % (