dabo Commit
Revision 7259
Date: 2012-09-24 23:43:31 -0700 (Mon, 24 Sep 2012)
Author: Jacekk
Trac: http://trac.dabodev.com/changeset/7259
Changed:
U trunk/dabo/biz/dBizobj.py
U trunk/dabo/db/dCursorMixin.py
Log:
Fix for cursor metadata synchronization issue on business and data layer point
of contact.
When master and child business objects are involved in transaction, raising
exception in any child object, e.g. BusinessRuleViolation on saving it, causes
that master recognizes yourself as saved and child doesn't.
All subsequent save attempts raises broken foreign key relation from backend
when saving new rows, since there is no related parent row in master table.
This commit fixes this issue.
Warning! Now all modified cursors recognizes themselves as changed until the
transaction is committed - it changes previous behavior.
Diff:
Modified: trunk/dabo/biz/dBizobj.py
===================================================================
--- trunk/dabo/biz/dBizobj.py 2012-09-24 19:41:04 UTC (rev 7258)
+++ trunk/dabo/biz/dBizobj.py 2012-09-25 06:43:31 UTC (rev 7259)
@@ -42,7 +42,8 @@
# Dictionary holding any default values to apply when a new
record is created. This is
# now the DefaultValues property (used to be self.defaultValues
attribute)
self._defaultValues = {}
-
+ # Holder for cursor changed rows history.
+ self._savedRowsHistory = {}
# PKs of rows to be filtered out when filtering Virtual fields
self.__filterPKVirtual = []
@@ -368,6 +369,8 @@
ret = self._hasTransactionToken() and crs.commitTransaction()
if ret:
self._releaseTransactionToken()
+ # Flush cursor status history.
+ self._flushSavedCursorsHistory()
return ret
@@ -384,6 +387,8 @@
ret = self._hasTransactionToken() and crs.rollbackTransaction()
if ret:
self._releaseTransactionToken()
+ # Clear history of cursor row changes.
+ self._discardSavedCursorsHistory()
return ret
@@ -449,7 +454,7 @@
try:
self.scanKeys(self.save, self._visitedKeys,
startTransaction=False,
saveTheChildren=saveTheChildren,
scanRequeryChildren=False)
- except (dException.DBQueryException, dException.dException):
+ except dException.dException:
if startTransaction:
self.rollbackTransaction()
raise
@@ -463,7 +468,7 @@
try:
self.scan(self.save, startTransaction=False,
saveTheChildren=saveTheChildren, scanRequeryChildren=False)
- except (dException.DBQueryException,
dException.dException):
+ except dException.dException:
if startTransaction:
self.rollbackTransaction()
raise
@@ -534,7 +539,7 @@
self.requeryAllChildren()
except (dException.ConnectionLostException,
dException.NoRecordsException):
raise
- except (dException.DBQueryException, dException.dException):
+ except dException.dException:
# Something failed; reset things.
if startTransaction:
self.rollbackTransaction()
@@ -2637,6 +2642,30 @@
self.__currentCursorKey = newKey
+ def _discardSavedCursorsHistory(self):
+ for child in self._children:
+ child._discardSavedCursorsHistory()
+ self._savedRowsHistory.clear()
+
+
+ def _flushSavedCursorsHistory(self):
+ for child in self._children:
+ child._flushSavedCursorsHistory()
+ for key in self._savedRowsHistory:
+ try:
+
self.__cursors[key]._postSaveUpdateInternals(self._savedRowsHistory[key])
+ except KeyError:
+ self._savedRowsHistory[key] = []
+
+
+ def _updateSavedCursorsHistory(self, row):
+ key = self._CurrentCursorKey
+ if key in self._savedRowsHistory:
+ self._savedRowsHistory[key].append(row)
+ else:
+ self._savedRowsHistory[key] = [row]
+
+
## Property getter/setter methods ##
def _getAutoPopulatePK(self):
try:
Modified: trunk/dabo/db/dCursorMixin.py
===================================================================
--- trunk/dabo/db/dCursorMixin.py 2012-09-24 19:41:04 UTC (rev 7258)
+++ trunk/dabo/db/dCursorMixin.py 2012-09-25 06:43:31 UTC (rev 7259)
@@ -1734,15 +1734,24 @@
except IndexError:
# For some reason we could not retrieve
the matching PK record
pass
+ if self._bizobj:
+ # Let the bizobj do cleanup for us.
+ self._bizobj._updateSavedCursorsHistory(row)
+ else:
+ # Let's cleanup myself.
+ self._postSaveUpdateInternals([row])
+ if not newrec and not res:
+ # Different backends may cause res to be None
+ # even if the save is successful.
+ self.BackendObject.noResultsOnSave()
+
+ def _postSaveUpdateInternals(self, rows):
+ """Update internal cusrsor data after successful transaction
commitment."""
+ for row in rows:
self._clearMemento(row)
- if newrec:
- self._clearNewRecord(row=row, pkVal=recKey)
- else:
- if not res:
- # Different backends may cause res to
be None
- # even if the save is successful.
- self.BackendObject.noResultsOnSave()
+ self._clearNewRecord(row)
+ del rows[:]
def _clearMemento(self, row=None):
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev
Searchable Archives: http://leafe.com/archives/search/dabo-dev
This message:
http://leafe.com/archives/byMID/[email protected]