dabo Commit
Revision 1521
Date: 2005-11-05 12:31:36 -0800 (Sat, 05 Nov 2005)
Author: ed
Changed:
U trunk/dabo/biz/dBizobj.py
U trunk/dabo/db/dCursorMixin.py
Log:
Fixed a potentially serious bug in the getDataSet() logic. I had assumed that
making a copy of a list made a copy of its contents, too. That is wrong.
getDataSet() takes a list of dicts, and uses the slice trick ([:]) to make a
copy of the list; however, each element in the two lists refer to the same
dict, and changing a value in one dict changed it in both. This is, oddly
enough, almost exactly like the VFP problem when you ran a fully-optimized
SQL-Select, the cursor it returned was not a copy of the data, but the source
table USEd AGAIN.
I also added the replace() methods to the cursor and bizobj classes. I
discovered the long-forgotten bizobj method 'replaceFor', which did more or
less the same thing. I looked through all the source code, including the demos
and IDE stuff, and can't find a single place where replaceFor() is used. If
it's OK with you, Paul, I'd like to remove it to avoid confusion.
Speaking of duplication, I removed the getRowCount() and getRowNumber() methods
of dCursorMixin. They have been marked as obsolete for some time now, and I
don't see them used in any of our code.
Diff:
Modified: trunk/dabo/biz/dBizobj.py
===================================================================
--- trunk/dabo/biz/dBizobj.py 2005-11-05 18:34:14 UTC (rev 1520)
+++ trunk/dabo/biz/dBizobj.py 2005-11-05 20:31:36 UTC (rev 1521)
@@ -522,6 +522,18 @@
return tuple([ff[0] for ff in flds])
+ def replace(self, field, valOrExpr, scope=None):
+ """Replaces the value of the specified field with the given
value
+ or expression. All records matching the scope are affected; if
+ no scope is specified, all records are affected.
+
+ 'valOrExpr' will be treated as a literal value, unless it is
prefixed
+ with an equals sign. All expressions will therefore be a string
+ beginning with '='. Literals can be of any type.
+ """
+ self._CurrentCursor.replace(field, valOrExpr, scope=scope)
+
+
def replaceFor(self, cond, fld, val):
"""Replaces all 'fld' values in the recordset with the specified
value, as long as the record meets the specified condition.
Modified: trunk/dabo/db/dCursorMixin.py
===================================================================
--- trunk/dabo/db/dCursorMixin.py 2005-11-05 18:34:14 UTC (rev 1520)
+++ trunk/dabo/db/dCursorMixin.py 2005-11-05 20:31:36 UTC (rev 1521)
@@ -660,9 +660,13 @@
"""
try:
if rows is not None:
- ret = self._records[rowStart:rowStart+rows]
+ tmp = self._records[rowStart:rowStart+rows]
else:
- ret = self._records[rowStart:]
+ tmp = self._records[rowStart:]
+ # The dicts in the returned dat set need to be copied;
+ # otherwise, modifying the data set will modify this
+ # cursor's records!
+ ret = [tmprec.copy() for tmprec in tmp]
except AttributeError:
# return empty dataset
return DataSet()
@@ -685,26 +689,22 @@
ret = DataSet(ret)
return ret
-
- def getRowCount(self):
- """ Get the row count of the current data set.
+
+ def replace(self, field, valOrExpr, scope=None):
+ """Replaces the value of the specified field with the given
value
+ or expression. All records matching the scope are affected; if
+ no scope is specified, all records are affected.
- Obsolete: Just get this from the property RowCount.
+ 'valOrExpr' will be treated as a literal value, unless it is
prefixed
+ with an equals sign. All expressions will therefore be a string
+ beginning with '='. Literals can be of any type.
"""
- return self.RowCount
+ if isinstance(self._records, DataSet):
+ self._records.replace(field, valOrExpr, scope=scope)
+
-
- def getRowNumber(self):
- """ Get the active row number of the data set.
-
- Obsolete: Just get this from the property RowNumber.
- """
- return self.RowNumber
-
-
def first(self):
- """ Move the record pointer to the first record of the data
set.
- """
+ """ Move the record pointer to the first record of the data
set."""
if self.RowCount > 0:
self.RowNumber = 0
else:
@@ -712,8 +712,7 @@
def prior(self):
- """ Move the record pointer back one position in the recordset.
- """
+ """ Move the record pointer back one position in the
recordset."""
if self.RowCount > 0:
if self.RowNumber > 0:
self.RowNumber -= 1
@@ -724,8 +723,7 @@
def next(self):
- """ Move the record pointer forward one position in the
recordset.
- """
+ """ Move the record pointer forward one position in the
recordset."""
if self.RowCount > 0:
if self.RowNumber < (self.RowCount-1):
self.RowNumber += 1
@@ -736,8 +734,7 @@
def last(self):
- """ Move the record pointer to the last record in the recordset.
- """
+ """ Move the record pointer to the last record in the
recordset."""
if self.RowCount > 0:
self.RowNumber = self.RowCount-1
else:
@@ -745,8 +742,7 @@
def save(self, allrows=False):
- """ Save any changes to the data back to the data store.
- """
+ """ Save any changes to the data back to the data store."""
# Make sure that there is data to save
if self.RowCount <= 0:
raise dException.dException, _("No data to save")
@@ -2020,10 +2016,6 @@
with an equals sign. All expressions will therefore be a string
beginning with '='. Literals can be of any type.
"""
-
-# dabo.trace()
-
-
if scope is None:
scope = "True"
else:
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev