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]

Reply via email to