dabo Commit
Revision 3372
Date: 2007-09-15 12:07:44 -0700 (Sat, 15 Sep 2007)
Author: Ed
Trac: http://svn.dabodev.com/trac/dabo/changeset/3372
Changed:
U trunk/dabo/db/dBackend.py
U trunk/dabo/db/dCursorMixin.py
U trunk/dabo/db/dbSQLite.py
Log:
Added more rigorous checking to determine if calls to getFIelds() need to be
made. Now the code tracks the field list requested by each select statement,
and if the list has not changed, the call to _storeFieldTypes() can be safely
skipped.
Diff:
Modified: trunk/dabo/db/dBackend.py
===================================================================
--- trunk/dabo/db/dBackend.py 2007-09-13 21:03:02 UTC (rev 3371)
+++ trunk/dabo/db/dBackend.py 2007-09-15 19:07:44 UTC (rev 3372)
@@ -399,7 +399,7 @@
return None
- def setNonUpdateFields(self, cursor, callback, autoQuote=True):
+ def setNonUpdateFields(self, cursor, autoQuote=True):
"""Normally, this routine should work for all backends. But
in the case of SQLite, the routine that grabs an empty cursor
doesn't fill in the description, so that backend has to use
@@ -407,7 +407,7 @@
"""
if not cursor.Table:
# No table specified, so no update checking is possible
- return
+ return None
# This is the current description of the cursor.
if not cursor.FieldDescription:
# A query hasn't been run yet; so we need to get one
@@ -436,7 +436,7 @@
for s in [z for z in stdFlds if z[0] == b[0] ]
if (b[1] != s[1]) or (b[3] != s[3]) or (b[4] !=
s[4])
or (b[5] != s[5]) or (b[6] != s[6]) ]
- callback(ret0)
+ return ret0
def getStructureDescription(self, cursor):
Modified: trunk/dabo/db/dCursorMixin.py
===================================================================
--- trunk/dabo/db/dCursorMixin.py 2007-09-13 21:03:02 UTC (rev 3371)
+++ trunk/dabo/db/dCursorMixin.py 2007-09-15 19:07:44 UTC (rev 3372)
@@ -66,6 +66,14 @@
self.sortOrder = ""
# Is the sort case-sensitive?
self.sortCase = True
+ # Holds the last SQL run in a requery() call.
+ self._lastSQL = ""
+ # These are used to determine if the field list of successive
select statements
+ # are identical.
+ self.__lastExecute = ""
+ self.__lastFieldList = ""
+ self._whitespacePat = re.compile(r"(\s+)")
+ self._selectStatementPat =
re.compile(r"\bselect\b(.+)\bfrom\b", re.I | re.M | re.S)
# Holds the keys in the original, unsorted order for unsorting
the dataset
self.__unsortedRows = []
# Holds the name of fields to be skipped when updating the
backend, such
@@ -167,7 +175,7 @@
return pk
- def _correctFieldType(self, field_val, field_name, _fromRequery=False):
+ def _correctFieldType(self, field_val, field_name, _newQuery=False):
"""Correct the type of the passed field_val, based on
self.DataStructure.
This is called by self.execute(), and contains code to convert
all strings
@@ -177,7 +185,7 @@
"""
ret = field_val
showError = False
- if _fromRequery:
+ if _newQuery:
pythonType = self._types.get(field_name,
type(field_val))
daboType = dabo.db.getDaboType(pythonType)
@@ -258,7 +266,7 @@
return ret
- def execute(self, sql, params=(), _fromRequery=False, errorClass=None):
+ def execute(self, sql, params=(), _newQuery=False, errorClass=None):
""" Execute the sql, and populate the DataSet if it is a select
statement."""
# The idea here is to let the super class do the actual work in
# retrieving the data. However, many cursor classes can only
return
@@ -299,7 +307,7 @@
# This allows each backend to handle these quirks individually.
self.BackendObject.massageDescription(self)
- if _fromRequery:
+ if self._newStructure(sql):
self._storeFieldTypes()
if sql.strip().split()[0].lower() not in ("select", "pragma"):
@@ -322,7 +330,7 @@
dic = {}
for idx, fldName in enumerate(fldNames):
dic[fldName] =
self._correctFieldType(field_val=row[idx],
-
field_name=fldName, _fromRequery=_fromRequery)
+
field_name=fldName, _newQuery=_newQuery)
tmpRows.append(dic)
_records = tmpRows
else:
@@ -330,7 +338,7 @@
for row in _records:
for fld, val in row.items():
row[fld] =
self._correctFieldType(field_val=val, field_name=fld,
-
_fromRequery=_fromRequery)
+
_newQuery=_newQuery)
self._records = dDataSet(_records)
@@ -350,6 +358,25 @@
ac = self.AuxCursor
self._syncAuxProperties()
return ac.execute(sql)
+
+
+ def _newStructure(self, sql):
+ """Attempts to parse the SQL to determine if the fields being
selected will require
+ a new call to set the structure. Non-select statements likewise
will return False.
+ """
+ if sql == self.__lastExecute:
+ return False
+ # See if it's a select statement
+ mtch = self._selectStatementPat.search(sql)
+ if not mtch:
+ return False
+ # Normalize white space
+ fldlist = self._whitespacePat.sub(" ", mtch.groups()[0]).strip()
+ if self.__lastFieldList == fldlist:
+ return False
+ else:
+ self.__lastFieldList = fldlist
+ return True
def _syncAuxProperties(self):
@@ -369,19 +396,22 @@
def requery(self, params=None):
- self._lastSQL = self.CurrentSQL
+ currSQL = self.CurrentSQL
+ newQuery = (self._lastSQL != currSQL)
+ self._lastSQL = currSQL
self.lastParams = params
self._savedStructureDescription = []
- self.execute(self.CurrentSQL, params, _fromRequery=True)
+ self.execute(currSQL, params, _newQuery=newQuery)
# clear mementos and new record flags:
self._mementos = {}
self._newRecords = {}
- # Check for any derived fields that should not be included in
- # any updates.
- self.__setNonUpdateFields()
+ if newQuery:
+ # Check for any derived fields that should not be
included in
+ # any updates.
+ self.__setNonUpdateFields()
# Clear the unsorted list, and then apply the current sort
self.__unsortedRows = []
@@ -641,8 +671,10 @@
nonUpdateFieldAliases.append(field_alias)
self.__nonUpdateFields = nonUpdateFieldAliases
else:
+ # Create the _dataStructure attribute
+ self._getDataStructure()
# Delegate to the backend object to figure it out.
- self.BackendObject.setNonUpdateFields(self,
self.__setNonUpdateFields)
+ self.__nonUpdateFields =
self.BackendObject.setNonUpdateFields(self)
def isChanged(self, allRows=True, includeNewUnchanged=False):
Modified: trunk/dabo/db/dbSQLite.py
===================================================================
--- trunk/dabo/db/dbSQLite.py 2007-09-13 21:03:02 UTC (rev 3371)
+++ trunk/dabo/db/dbSQLite.py 2007-09-15 19:07:44 UTC (rev 3372)
@@ -34,7 +34,7 @@
fieldNames = (fld[0] for fld in cursor.description)
for idx, field_name in enumerate(fieldNames):
if _types:
- ret[field_name] =
cursor._correctFieldType(row[idx], field_name, _fromRequery=True)
+ ret[field_name] =
cursor._correctFieldType(row[idx], field_name, _newQuery=True)
else:
ret[field_name] = row[idx]
return ret
@@ -161,13 +161,13 @@
return tuple(fields)
- def setNonUpdateFields(self, cursor, callback):
+ def setNonUpdateFields(self, cursor):
# Use an alternative, since grabbing an empty cursor, as is
done in the
# default method, doesn't provide a description. Assume that
any field with
# the same name as the fields in the base table will be
updatable.
if not cursor.Table:
# No table specified, so no update checking is possible
- return
+ return None
# This is the current description of the cursor.
descFlds = cursor.FieldDescription
# Get the field info for the table
@@ -177,8 +177,8 @@
stdFlds = [ff["name"] for ff in rs]
# Get all the fields that are not in the table.
- callback([d[0] for d in descFlds
- if d[0] not in [s[0] for s in stdFlds] ])
+ return [d[0] for d in descFlds
+ if d[0] not in [s[0] for s in stdFlds] ]
def getUpdateTablePrefix(self, table, autoQuote=True):
_______________________________________________
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/dabo-dev/[EMAIL PROTECTED]