From: Mike Bayer Date: Fri, 3 Feb 2006 00:42:22 +0000 (+0000) Subject: switched objectstore begin/commit behavior to do "reentrant counter" X-Git-Tag: rel_0_1_0~76 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=faeeb99a2100465814f2b74c74cde275c52cd119;p=thirdparty%2Fsqlalchemy%2Fsqlalchemy.git switched objectstore begin/commit behavior to do "reentrant counter" --- diff --git a/doc/build/content/unitofwork.myt b/doc/build/content/unitofwork.myt index d3ddb2b366..83f78e804b 100644 --- a/doc/build/content/unitofwork.myt +++ b/doc/build/content/unitofwork.myt @@ -83,27 +83,7 @@ objectstore.commit()

As always, the actual database transaction begin/commit occurs entirely within the objectstore.commit() operation.

- -

Since the begin/commit paradigm works in a stack-based manner, it follows that any level of nesting of begin/commit can be used:

- <&|formatting.myt:code&> - # start with UOW #1 as the thread-local UnitOfWork - a = Foo() - objectstore.begin() # push UOW #2 on the stack - b = Foo() - objectstore.begin() # push UOW #3 on the stack - c = Foo() - - # saves 'c' - objectstore.commit() # commit UOW #3 - - d = Foo() - - # saves 'b' and 'd' - objectstore.commit() # commit UOW #2 - - # saves 'a', everything else prior to it - objectstore.commit() # commit thread-local UOW #1 - +

At the moment, begin/commit supports the same "nesting" behavior as the SQLEngine (note this behavior is not the original "nested" behavior), meaning that repeated calls to begin() will increment a counter, which is not released until that same number of commit() statements occur.

<&|doclib.myt:item, name="transactionnesting", description="Nesting UnitOfWork in a Database Transaction" &>

The UOW commit operation places its INSERT/UPDATE/DELETE operations within the scope of a database transaction controlled by a SQLEngine: diff --git a/lib/sqlalchemy/mapping/objectstore.py b/lib/sqlalchemy/mapping/objectstore.py index f4775f95ef..23b98f42ed 100644 --- a/lib/sqlalchemy/mapping/objectstore.py +++ b/lib/sqlalchemy/mapping/objectstore.py @@ -149,6 +149,10 @@ class UOWAttributeManager(attributes.AttributeManager): class UnitOfWork(object): def __init__(self, parent = None, is_begun = False): self.is_begun = is_begun + if is_begun: + self.begin_count = 1 + else: + self.begin_count = 0 if parent is not None: self.identity_map = parent.identity_map else: @@ -245,10 +249,17 @@ class UnitOfWork(object): # TODO: tie in register_new/register_dirty with table transaction begins ? def begin(self): + if self.is_begun: + self.begin_count += 1 + return u = UnitOfWork(self, True) uow.set(u) def commit(self, *objects): + if self.is_begun: + self.begin_count -= 1 + if self.begin_count > 0: + return commit_context = UOWTransaction(self) if len(objects): @@ -312,10 +323,9 @@ class UnitOfWork(object): def rollback(self): if not self.is_begun: raise "UOW transaction is not begun" - # TODO: locate only objects that are dirty/new/deleted in this UOW, - # roll only those back. - for obj in self.deleted + self.dirty + self.new: - self.attributes.rollback(obj) + # roll back attributes ? nah.... + #for obj in self.deleted + self.dirty + self.new: + # self.attributes.rollback(obj) uow.set(self.parent) class UOWTransaction(object):