[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[gnue] r7297 - trunk/gnue-common/src/datasources/drivers/Base
From: |
reinhard |
Subject: |
[gnue] r7297 - trunk/gnue-common/src/datasources/drivers/Base |
Date: |
Mon, 4 Apr 2005 18:13:31 -0500 (CDT) |
Author: reinhard
Date: 2005-04-04 18:13:30 -0500 (Mon, 04 Apr 2005)
New Revision: 7297
Modified:
trunk/gnue-common/src/datasources/drivers/Base/ResultSet.py
Log:
Added some comments, changed function order to a more logical one.
Modified: trunk/gnue-common/src/datasources/drivers/Base/ResultSet.py
===================================================================
--- trunk/gnue-common/src/datasources/drivers/Base/ResultSet.py 2005-04-04
22:33:32 UTC (rev 7296)
+++ trunk/gnue-common/src/datasources/drivers/Base/ResultSet.py 2005-04-04
23:13:30 UTC (rev 7297)
@@ -23,21 +23,26 @@
__all__ = ['ResultSet']
-from gnue.common.datasources import GConditions, Exceptions
import string
+from gnue.common.datasources import Exceptions
+
from RecordSet import RecordSet
-###########################################################
-#
-#
-#
-###########################################################
+# =============================================================================
+# Basic ResultSet class
+# =============================================================================
+
class ResultSet:
_recordSetClass = RecordSet
- def __init__(self, dataObject,
cursor=None,defaultValues={},masterRecordSet=None):
+ # ---------------------------------------------------------------------------
+ # Constructor
+ # ---------------------------------------------------------------------------
+
+ def __init__ (self, dataObject, cursor = None, defaultValues = {},
+ masterRecordSet = None):
self._dataObject = dataObject
self._cursor = cursor
self._cachedRecords = []
@@ -66,65 +71,160 @@
if masterRecordSet:
masterRecordSet.addDetailResultSet(self)
- # Since we are overriding __len__
- def __nonzero__(self):
- return 1
- # Return the # of records
- def __len__(self):
- return self.getRecordCount()
+ # ---------------------------------------------------------------------------
+ # Status information
+ # ---------------------------------------------------------------------------
- def __getitem__(self, index):
- rs = self.getRecord(index)
- if not rs:
- raise IndexError
- else:
- return rs
-
-
- # Returns whether this result set is read only or not
- def isReadOnly(self):
+ def isReadOnly (self):
return self._readonly
+ # ---------------------------------------------------------------------------
- # Returns 1=At first record, 0=Not first record
- def isFirstRecord(self):
+ def isFirstRecord (self):
return (self._currentRecord == 0)
+ # ---------------------------------------------------------------------------
- # Returns 1=At last record, 0=Not last record
- def isLastRecord(self):
+ def isLastRecord (self):
if self._currentRecord < len(self._cachedRecords) - 1 or \
self._cacheNextRecord():
return False
else:
return True
+ # ---------------------------------------------------------------------------
# returns -1=No records in memory, #=Current record #
- def getRecordNumber(self):
+ def getRecordNumber (self):
return self._currentRecord
+ # ---------------------------------------------------------------------------
- # returns # of records currently loaded
- def getCacheCount(self):
- return len(self._cachedRecords)
+ def getCacheCount (self):
+ return len (self._cachedRecords)
- # returns # of records the
- def getRecordCount(self):
+ # ---------------------------------------------------------------------------
+
+ def getRecordCount (self):
return self._recordCount > 0 and self._recordCount or self.getCacheCount()
+ # ---------------------------------------------------------------------------
+
+ # Returns True if the resultset or a detail resultset has uncommitted changes
+ def isPending(self):
+ for rec in (self._cachedRecords):
+ if rec.isPending ():
+ return True
+ return False
+
+ # ---------------------------------------------------------------------------
+
+ # Returns 1=DataObject has uncommitted changes
+ def isRecordPending(self):
+ return self.current.isPending()
+
+ # ---------------------------------------------------------------------------
+
+ # Returns 1=Field is bound to a database field
+ # TODO: pass a list of bound field names to RecordSet instead
+ def isFieldBound(self, fieldName):
+
+ # TODO: until the case problem get's fixed in common we do the following
+ # workaround.
+ for item in self._dataObject._fieldReferences.keys ():
+ if item.lower () == fieldName.lower ():
+ return True
+
+ return False
+
+
+ # ---------------------------------------------------------------------------
+ # Load cacheCount number of new records
+ # ---------------------------------------------------------------------------
+
+ def _cacheNextRecord (self):
+ rs = self._loadNextRecord()
+ if rs:
+ self._dataObject._dataSource._onRecordLoaded(self._cachedRecords[-1])
+ return rs
+
+
+ # ---------------------------------------------------------------------------
# Get a specific record (0=based)
- def getRecord(self, record):
- while (record + 1 > len(self._cachedRecords)) and self._cacheNextRecord():
+ # ---------------------------------------------------------------------------
+
+ def getRecord (self, record):
+ while (record + 1 > len (self._cachedRecords)) and self._cacheNextRecord
():
pass
- if record + 1 > len(self._cachedRecords):
+ if record + 1 > len (self._cachedRecords):
return None
else:
- return self._cachedRecords[record]
+ return self._cachedRecords [record]
+ # ---------------------------------------------------------------------------
+ # Get data as array
+ # ---------------------------------------------------------------------------
+
+ def getArray (self, fields):
+ """
+ This function returns the values of the given fields for all records as a
+ 2-dimensional list. The record pointer is *not* moved.
+ """
+
+ # First, load all records into the cache
+ while self._cacheNextRecord():
+ pass
+
+ # Now build up the array
+ result = []
+ for record in self._cachedRecords:
+ line = []
+ for field in fields:
+ line.append (record [field])
+ result.append (line)
+ return result
+
+
+ # ---------------------------------------------------------------------------
+ # Notification of record navigation
+ # ---------------------------------------------------------------------------
+
+ # TODO: Unify __notifyListeners and notifyDetailObjects
+
+ # Other objects can register here. Their currentRecordMoved method will then
+ # get called whenever the current record of this ResultSet changes.
+ def registerListener (self, listener):
+ if listener not in self.__listeners:
+ self.__listeners.append (listener)
+ # Inform new listener about current record. This happens whenever the
+ # *Resultset* (not the current record but the whole resultset) changes.
+ if self._currentRecord >= 0:
+ listener.currentRecordMoved ()
+
+ # ---------------------------------------------------------------------------
+
+ # This gets called whenever the ResultSet gets a new current recordset,
+ # that happens in case of record navigation, in case of inserting a new
+ # record, and in case of posting data (the current record could have been
+ # deleted, or the backend could have changed some data).
+ def __notifyListeners (self):
+ for listener in self.__listeners:
+ listener.currentRecordMoved ()
+
+ # ---------------------------------------------------------------------------
+
+ def notifyDetailObjects(self):
+ gDebug (8,'Master record changed; Notifying Detail Objects')
+ for detail in self._dataObject._detailObjects:
+ if detail[1]:
+ detail[1].masterResultSetChanged(self,
+ detail[0]._masterRecordChanged(self))
+
+ # ---------------------------------------------------------------------------
+
# Sync self.current with self._currentRecord and adjust detail resultsets and
# the user interface
def __sync (self):
@@ -136,6 +236,11 @@
self.__notifyListeners ()
+ # ---------------------------------------------------------------------------
+ # Record navigation
+ # ---------------------------------------------------------------------------
+
+
# Move to a record number already in cache
# -1 sets the current record to None
def __move (self, record):
@@ -145,50 +250,46 @@
self._currentRecord = record
self.__sync ()
+ # ---------------------------------------------------------------------------
- # move to record #, returns record or None if record number out of range
- def setRecord(self, record):
-
+ def setRecord (self, record):
while (record > len(self._cachedRecords) -1) and self._cacheNextRecord():
pass
-
if record >= len(self._cachedRecords):
return None
else:
self.__move (record)
return self.current
+ # ---------------------------------------------------------------------------
- # returns next record, or None if no more records
- def nextRecord(self):
- if self._currentRecord + 1 == len(self._cachedRecords):
- if not self._cacheNextRecord():
+ def nextRecord (self):
+ if self._currentRecord + 1 == len (self._cachedRecords):
+ if not self._cacheNextRecord ():
return None
-
self.__move (self._currentRecord + 1)
return self.current
+ # ---------------------------------------------------------------------------
- # returns 1=New record loaded, 0=At first record
- def prevRecord(self):
+ def prevRecord (self):
if self._currentRecord < 1:
return None
else:
self.__move (self._currentRecord - 1)
return self.current
+ # ---------------------------------------------------------------------------
- # returns 1=at first record, 0=No records loaded
- def firstRecord(self):
+ def firstRecord (self):
if self._currentRecord < 0:
if not self._cacheNextRecord():
return None
-
self.__move (0)
return self.current
+ # ---------------------------------------------------------------------------
- # returns 1=at last record, 0=No records loaded
def lastRecord(self):
if self._currentRecord == -1:
return None
@@ -199,43 +300,6 @@
return self.current
-
- # Insert a blank record after the current record
- def insertRecord(self):
- if self.isReadOnly():
- # Provide better feedback??
- tmsg = _("Attempted to insert into a read only datasource")
- raise Exceptions.ReadOnlyError, tmsg
- else:
- gDebug (8, 'Inserting a blank record in %s' % self)
- self._currentRecord += 1
- self._cachedRecords.insert(self._currentRecord,
self._createEmptyRecord())
- self._recordCount += 1
- self.current = self._cachedRecords[self._currentRecord]
-
- # Set any dataobject-wide default values
- for field in self._dataObject._defaultValues.keys():
- gDebug (8, "DataObject-Wide default for %s" % field)
- self.current.setField(field,
self._dataObject._defaultValues[field],False)
-
- # Set any resultset specific values
- for field in self._defaultValues.keys():
- gDebug (8, "ResultSet-specific default for %s" % field)
- self.current.setField(field, self._defaultValues[field],False)
-
- # Pull any primary keys from a master record set
- if self._masterRecordSet != None and hasattr(self._dataObject,
'_masterfields'):
- i = 0
- for field in self._dataObject._masterfields:
- gDebug (8, "Value for %s to %s" % (field, \
- self._masterRecordSet.getField (field)))
-
self.current.setField(self._dataObject._detailfields[i],self._masterRecordSet.getField(field),False)
- i += 1
-
- self.notifyDetailObjects()
- self.__notifyListeners ()
- return self.current
-
# ---------------------------------------------------------------------------
# Find a record by field values
# ---------------------------------------------------------------------------
@@ -268,50 +332,51 @@
self.__move (-1)
return self.current
+
# ---------------------------------------------------------------------------
- # Get data as array
+ # Insert a new record after the current one
# ---------------------------------------------------------------------------
- def getArray (self, fields):
- """
- This function returns the values of the given fields for all records as a
- 2-dimensional list. The record pointer is *not* moved.
- """
+ def insertRecord(self):
+ if self.isReadOnly():
+ # Provide better feedback??
+ tmsg = _("Attempted to insert into a read only datasource")
+ raise Exceptions.ReadOnlyError, tmsg
+ else:
+ gDebug (8, 'Inserting a blank record in %s' % self)
+ self._currentRecord += 1
+ self._cachedRecords.insert(self._currentRecord,
self._createEmptyRecord())
+ self._recordCount += 1
+ self.current = self._cachedRecords[self._currentRecord]
- # First, load all records into the cache
- while self._cacheNextRecord():
- pass
+ # Set any dataobject-wide default values
+ for field in self._dataObject._defaultValues.keys():
+ gDebug (8, "DataObject-Wide default for %s" % field)
+ self.current.setField(field,
self._dataObject._defaultValues[field],False)
- # Now build up the array
- result = []
- for record in self._cachedRecords:
- line = []
- for field in fields:
- line.append (record [field])
- result.append (line)
- return result
+ # Set any resultset specific values
+ for field in self._defaultValues.keys():
+ gDebug (8, "ResultSet-specific default for %s" % field)
+ self.current.setField(field, self._defaultValues[field],False)
- # ---------------------------------------------------------------------------
- # Close the result set
- # ---------------------------------------------------------------------------
+ # Pull any primary keys from a master record set
+ if self._masterRecordSet != None and hasattr(self._dataObject,
'_masterfields'):
+ i = 0
+ for field in self._dataObject._masterfields:
+ gDebug (8, "Value for %s to %s" % (field, \
+ self._masterRecordSet.getField (field)))
+
self.current.setField(self._dataObject._detailfields[i],self._masterRecordSet.getField(field),False)
+ i += 1
- def close (self):
- """
- This function should be called, if a result set is no longer needed. It
- breaks up reference cycles so garbage collection can do it's job.
- """
+ self.notifyDetailObjects()
+ self.__notifyListeners ()
+ return self.current
- for item in self._cachedRecords:
- item._parent = None
- if self._dataObject._dataSource:
- self._dataObject._dataSource.close ()
+ # ---------------------------------------------------------------------------
+ # Create a new record with a copy of the existing one
+ # ---------------------------------------------------------------------------
- self._dataObject = None
- self._cachedRecords = []
- self.__listeners = []
-
-
def duplicateRecord(self, exclude=(), include=()):
current = self.current
inserted = self.insertRecord()
@@ -346,19 +411,11 @@
return inserted
- # Returns 1=DataObject, or a detail resultset, has uncommitted changes
- def isPending(self):
- for rec in (self._cachedRecords):
- if rec.isPending ():
- return True
- return False
+ # ---------------------------------------------------------------------------
+ # TODO: What's this??
+ # ---------------------------------------------------------------------------
- # Returns 1=DataObject has uncommitted changes
- def isRecordPending(self):
- return self.current.isPending()
-
-
def getPostingRecordset(self):
global postingRecordset
return postingRecordset
@@ -421,6 +478,7 @@
else:
self._currentRecord = -1
+
# ---------------------------------------------------------------------------
# Sync resultset with backend, and sync listeners with resultset
# ---------------------------------------------------------------------------
@@ -441,121 +499,85 @@
self.__sync ()
- def notifyDetailObjects(self):
- gDebug (8,'Master record changed; Notifying Detail Objects')
- for detail in self._dataObject._detailObjects:
- if detail[1]:
- detail[1].masterResultSetChanged(self,
- detail[0]._masterRecordChanged(self))
+ # ---------------------------------------------------------------------------
+ # Close the result set
+ # ---------------------------------------------------------------------------
+ def close (self):
+ """
+ This function should be called, if a result set is no longer needed. It
+ breaks up reference cycles so garbage collection can do it's job.
+ """
- # Other objects can register here. Their currentRecordMoved method will then
- # get called whenever the current record of this ResultSet changes.
- def registerListener (self, listener):
- if listener not in self.__listeners:
- self.__listeners.append (listener)
- # Inform new listener about current record. This happens whenever the
- # *Resultset* (not the current record but the whole resultset) changes.
- if self._currentRecord >= 0:
- listener.currentRecordMoved ()
+ for item in self._cachedRecords:
+ item._parent = None
+ if self._dataObject._dataSource:
+ self._dataObject._dataSource.close ()
- # This gets called whenever the ResultSet gets a new current recordset,
- # that happens in case of record navigation, in case of inserting a new
- # record, and in case of posting data (the current record could have been
- # deleted, or the backend could have changed some data).
- def __notifyListeners (self):
- for listener in self.__listeners:
- listener.currentRecordMoved ()
+ self._dataObject = None
+ self._cachedRecords = []
+ self.__listeners = []
- # Returns 1=Field is bound to a database field
- def isFieldBound(self, fieldName):
-
- # TODO: until the case problem get's fixed in common we do the following
- # workaround.
- for item in self._dataObject._fieldReferences.keys ():
- if item.lower () == fieldName.lower ():
- return True
-
- return False
-
-
- # Load cacheCount number of new records
- def _cacheNextRecord(self):
- rs = self._loadNextRecord()
- if rs:
- self._dataObject._dataSource._onRecordLoaded(self._cachedRecords[-1])
- return rs
-
-
# ---------------------------------------------------------------------------
- # Nice string representation
+ # Virtual methods
# ---------------------------------------------------------------------------
- def __repr__ (self):
- do = self._dataObject
- if hasattr (do, 'table'):
- return "<ResultSet for %s>" % do.table
- else:
- return "<Unbound/Static ResultSet>"
-
-
- ###
- ### Methods below should be overridden by Vendor Specific functions
- ### (_createEmptyRecord may not need to be overridden in all cases)
- ###
-
# Load cacheCount number of new records
def _loadNextRecord(self):
return False
+ # ---------------------------------------------------------------------------
+
# Create an empty recordset
def _createEmptyRecord (self):
return self._recordSetClass (parent = self,
rowidField = self.__rowidField,
primarykeyFields = self.__primarykeyFields)
- # Iterator support (Python 2.2+)
- def __iter__(self):
- return _ResultSetIter(self)
+ # ---------------------------------------------------------------------------
+ # Sequence behaviour
+ # ---------------------------------------------------------------------------
+ def __iter__ (self):
+ record = self.firstRecord ()
+ while record:
+ yield record
+ record = self.nextRecord ()
-# A simple resultset iterator
-# Lets you use ResultSets as:
-#
-# for record in myResultSet:
-# blah
-#
-# NOTE: Python 2.2+ (but it won't get called in
-# Python 2.1 or below, so not a problem)
-#
-class _ResultSetIter:
- def __init__(self, resultset):
- self.resultset = resultset
- self.used = False
- self.done = False
+ # ---------------------------------------------------------------------------
- def __iter__(self):
- return self
+ def __nonzero__ (self):
+ return True
- def next(self):
- if self.done:
- raise StopIteration
- if not self.used:
- rs = self.resultset.firstRecord()
- self.used = True
+ # ---------------------------------------------------------------------------
+
+ def __len__ (self):
+ return self.getRecordCount ()
+
+ # ---------------------------------------------------------------------------
+
+ def __getitem__ (self, index):
+ record = self.getRecord (index)
+ if not record:
+ raise IndexError
else:
- rs = self.resultset.nextRecord()
+ return record
- if not rs:
- self.done = True
- raise StopIteration
+
+ # ---------------------------------------------------------------------------
+ # Nice string representation
+ # ---------------------------------------------------------------------------
+
+ def __repr__ (self):
+ do = self._dataObject
+ if hasattr (do, 'table'):
+ return "<ResultSet for %s>" % do.table
else:
- return rs
+ return "<Unbound/Static ResultSet>"
# TODO: wtf?
postingRecordset = None
-
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [gnue] r7297 - trunk/gnue-common/src/datasources/drivers/Base,
reinhard <=