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]

Reply via email to