dabo Commit
Revision 1495
Date: 2005-10-31 15:52:27 -0800 (Mon, 31 Oct 2005)
Author: ed
Changed:
U trunk/dabo/db/dCursorMixin.py
Log:
Added a new class named 'DataSet', which is a subclass of tuple. The purpose of
this class is to allow SQL-like selections and joins to be made on data as it
exists in Dabo, instead of strictly on the backend. For example, let's say you
create two cursors, and then want to do a join on the data in them. In Fox it's
no big deal, but you currently can't do that in Dabo without calling back to
the database and re-fetching the data.
As of now there is a *very* rudimentary 'select()' method for this class. As
time goes on, I'd like to flesh it out a bit more, and then eventually create a
join() method to go along with it that would accept another DataSet object
along with a bunch of conditions, and return the appropriate result set.
Diff:
Modified: trunk/dabo/db/dCursorMixin.py
===================================================================
--- trunk/dabo/db/dCursorMixin.py 2005-10-31 22:19:32 UTC (rev 1494)
+++ trunk/dabo/db/dCursorMixin.py 2005-10-31 23:52:27 UTC (rev 1495)
@@ -67,7 +67,7 @@
# it will be a separate object.
self.sqlManager = self
# Attribute that holds the data of the cursor
- self._records = ()
+ self._records = DataSet()
# Attribute that holds the current row number
self.__rownumber = -1
@@ -161,14 +161,13 @@
# Not all backends support 'fetchall' after executing a query
# that doesn't return records, such as an update.
try:
- self._records = self.fetchall()
+ self._records = DataSet(self.fetchall())
except:
pass
# Some backend programs do odd things to the description
# This allows each backend to handle these quirks individually.
self.BackendObject.massageDescription(self)
-
if self.RowCount > 0:
self.RowNumber = max(0, self.RowNumber)
maxrow = max(0, (self.RowCount-1) )
@@ -195,8 +194,7 @@
else:
dic[fldNames[i]] =
row[i]
tmpRows.append(dic)
- self._records = tuple(tmpRows)
-
+ self._records = DataSet(tmpRows)
else:
# Make all string values into unicode
for row in self._records:
@@ -205,7 +203,6 @@
if isinstance(val, str):
# String; convert it to
unicode
row[fld]= unicode(val,
self.Encoding)
-
# There can be a problem with the MySQLdb adapter if
# the mx modules are installed on the machine, the
adapter
# will use that type instead of the native datetime.
@@ -222,6 +219,8 @@
except ImportError:
# mx not installed; no problem
pass
+ # Convert to DataSet
+ self._records = DataSet(self._records)
return res
@@ -375,7 +374,7 @@
newRows = []
for elem in sortList:
newRows.append(elem[1])
- self._records = tuple(newRows)
+ self._records = DataSet(newRows)
# restore the RowNumber
if currRowKey:
@@ -664,6 +663,7 @@
filtRec[fld] = rec[fld]
retlist.append(filtRec)
ret = tuple(retlist)
+ ret = DataSet(ret)
return ret
except AttributeError:
return ()
@@ -851,7 +851,7 @@
# Copy the _blank dict to the _records, and adjust everything
accordingly
tmprows = list(self._records)
tmprows.append(self._blank.copy())
- self._records = tuple(tmprows)
+ self._records = DataSet(tmprows)
# Adjust the RowCount and position
self.RowNumber = self.RowCount - 1
# Add the 'new record' flag to the last record (the one we just
added)
@@ -942,7 +942,7 @@
"""
lRec = list(self._records)
del lRec[r]
- self._records = tuple(lRec)
+ self._records = DataSet(lRec)
self.RowNumber = min(self.RowNumber, self.RowCount-1)
@@ -1626,3 +1626,45 @@
UserSQL = property(_getUserSQL, _setUserSQL, None,
_("SQL statement to run. If set, the automatic SQL
builder will not be used."))
+
+
+
+class DataSet(tuple):
+ """ This class assumes that its contents are not ordinary tuples, but
+ rather tuples consisting of dicts, where the dict keys are field names.
+ This is the data structure returned by the dCursorMixin class.
+ """
+ def select(self, flds=None, where=None, orderBy=None):
+ fldList = []
+ whereList = []
+ orderByList = []
+ if flds is None or flds == "*":
+ # All fields
+ flds = self[0].keys()
+ elif isinstance(flds, basestring):
+ # Convert to list
+ flds = [flds]
+ for fld in flds:
+ fldList.append("'%s' : rec['%s']" % (fld, fld))
+ fldsToReturn = ", ".join(fldList)
+ fldsToReturn = "{%s}" % fldsToReturn
+
+ # Where list elements. Each element should be in the form:
<fld> <op> <val>
+ # TODO: add support for format: <fld>.func() <op> <val>
+ # or: func(<fld>) <op> <val>
+ if where is None:
+ whereClause = ""
+ else:
+ if isinstance(where, basestring):
+ where = [where]
+ for wh in where:
+ fld, op, val = wh.split(" ", 2)
+ whereList.append("rec['%s'] %s %s" % (fld, op,
val))
+ whereClause = " and ".join(whereList)
+ if whereClause:
+ whereClause = " if %s" % whereClause
+
+ stmnt = "[%s for rec in self %s]" % (fldsToReturn, whereClause)
+ resultSet = eval(stmnt)
+ return resultSet
+
\ No newline at end of file
_______________________________________________
Post Messages to: [email protected]
Subscription Maintenance: http://leafe.com/mailman/listinfo/dabo-dev