commit-gnue
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

CVSROOT: /cvsroot/gnue


From: Jason Cater
Subject: CVSROOT: /cvsroot/gnue
Date: Tue, 18 Nov 2003 21:07:10 -0500

Module name:    gnue-common
Branch:         datasource-cleanup
Changes by:     Jason Cater <address@hidden>    03/11/18 21:07:09
Reply-to: address@hidden

CVSROOT:        /cvsroot/gnue
Module name:    gnue-common
Branch:         datasource-cleanup
Changes by:     Jason Cater <address@hidden>    03/11/18 21:07:09

Modified files:
        src/datasources: GConnections.py GDataObjects.py 
        src/datasources/drivers/Base: __init__.py 
        src/datasources/drivers/DBSIG2: Connection.py DataObject.py 
                                        RecordSet.py ResultSet.py 
        src/datasources/drivers/adodbapi/adodbapi: Connection.py 
        src/datasources/drivers/appserver/appserver: Connection.py 
                                                     DataObject.py 
                                                     RecordSet.py 
                                                     ResultSet.py 
        src/datasources/drivers/db2/db2: Connection.py 
        src/datasources/drivers/dbf/dbf: Connection.py 
        src/datasources/drivers/gadfly/gadfly: Connection.py 
        src/datasources/drivers/informix/informix: Connection.py 
        src/datasources/drivers/ingres/ingres: Connection.py 
        src/datasources/drivers/mysql/mysql: Connection.py 
        src/datasources/drivers/oracle/Base: Connection.py 
        src/datasources/drivers/postgresql/Base: Connection.py 
                                                 DataObject.py 
        src/datasources/drivers/postgresql/pypgsql: Driver.py 
        src/datasources/drivers/sapdb/sapdb: Connection.py 
        src/datasources/drivers/sqlite/sqlite: Connection.py 
        src/datasources/drivers/sqlrelay/sqlrelay: Connection.py 
        src/datasources/drivers/sybase/sybase: Connection.py 
Added files:
        src/datasources: Exceptions.py 
        src/datasources/drivers/Base: Connection.py DataObject.py 
                                      RecordSet.py ResultSet.py 
Removed files:
        src/datasources/drivers/DBSIG2: Driver.py 

Log message:
        got the datasource changes working with gnue-forms

CVSWeb URLs:
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/Exceptions.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/GConnections.py.diff?only_with_tag=datasource-cleanup&tr1=1.52.2.3&tr2=1.52.2.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/GDataObjects.py.diff?only_with_tag=datasource-cleanup&tr1=1.72.2.2&tr2=1.72.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/Base/Connection.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/Base/DataObject.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/Base/RecordSet.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/Base/ResultSet.py?only_with_tag=datasource-cleanup&rev=1.1.2.1
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/Base/__init__.py.diff?only_with_tag=datasource-cleanup&tr1=1.1&tr2=1.1.2.1&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/DataObject.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.3&tr2=1.1.2.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.2&tr2=1.1.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/appserver/appserver/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.3&tr2=1.1.2.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.2&tr2=1.1.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.2&tr2=1.1.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/db2/db2/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/dbf/dbf/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/informix/informix/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.2&tr2=1.1.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/ingres/ingres/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/mysql/mysql/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.2&tr2=1.1.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/oracle/Base/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/postgresql/Base/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.3&tr2=1.1.2.4&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py.diff?only_with_tag=datasource-cleanup&tr1=1.35.2.2&tr2=1.35.2.3&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text
http://savannah.gnu.org/cgi-bin/viewcvs/gnue/gnue-common/src/datasources/drivers/sybase/sybase/Connection.py.diff?only_with_tag=datasource-cleanup&tr1=1.1.2.1&tr2=1.1.2.2&r1=text&r2=text

Patches:
Index: gnue-common/src/datasources/Exceptions.py
diff -c /dev/null gnue-common/src/datasources/Exceptions.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/Exceptions.py   Tue Nov 18 21:07:06 2003
***************
*** 0 ****
--- 1,80 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # GDataObjects.py
+ #
+ # DESCRIPTION:
+ # This is a temporary backwards compatability file.
+ # Should be removed at some point.
+ #
+ # NOTES:
+ #
+ 
+ class Error(StandardError):
+   # Base exception
+   pass
+ 
+ class LoginError(Error):
+   # Raised when invalid login user/pass was provided
+   # Client should attempt to get better information and
+   # try again
+   pass
+ 
+ class ConnectError(Error):
+   # Raised when connection data is invalid (e.g., host not found, etc).
+   # Client should probably not attempt to relogin.  Exit gracefully
+   # with a reason.
+   pass
+ 
+ class ProviderNotSupportedError(Error):
+   # Raised when a datasource type is requested that the dbdriver
+   # does not support (e.g., not all dbdrivers support raw sql mode.)
+   pass
+ 
+ class ObjectTypeNotAvailableError(Error):
+   # Raised when a datasource type is requested that the dbdriver
+   # does not support (e.g., not all dbdrivers support raw sql mode.)
+   pass
+ 
+ class ReadOnlyError(Error):
+   # Raised when an attempt is made to update a read-only data object.
+   pass
+ 
+ class MasterDetailFieldMismatch(Error):
+   # Raised when a the number of master fields doesn't match the
+   # number of detail fields. (e.g., masterlink="id,subid"
+   # and detaillink="id" would be a problem; must be 1:1)
+   pass
+ 
+ class ConnectionError(Error):
+   # Generic error reading from the database connection
+   pass
+ 
+ class DataTypeNotAvailable(Error):
+   # Raised when a datatype is not supported by an database
+   # during writing a schema definition to the database
+   pass
+ 
+ class NoWriteSchemaSupport(Error):
+   # Raised when a database adapter doesn't support
+   # writing Schema to datasource
+   pass
+ 
Index: gnue-common/src/datasources/GConnections.py
diff -c gnue-common/src/datasources/GConnections.py:1.52.2.3 
gnue-common/src/datasources/GConnections.py:1.52.2.4
*** gnue-common/src/datasources/GConnections.py:1.52.2.3        Tue Nov 18 
19:01:05 2003
--- gnue-common/src/datasources/GConnections.py Tue Nov 18 21:07:06 2003
***************
*** 33,39 ****
  from ConfigParser import *
  import sys, string, copy, netrc
  from gnue.common.apps import GDebug
! from gnue.common.datasources import GDataObjects
  from gnue.common.datasources import GLoginHandler
  from gnue.common.datasources.drivers import DRIVERS as ALLDRIVERS
  from gnue.common.utils.FileUtils import openResource, dyn_import
--- 33,39 ----
  from ConfigParser import *
  import sys, string, copy, netrc
  from gnue.common.apps import GDebug
! from gnue.common.datasources import Exceptions
  from gnue.common.datasources import GLoginHandler
  from gnue.common.datasources.drivers import DRIVERS as ALLDRIVERS
  from gnue.common.utils.FileUtils import openResource, dyn_import
***************
*** 56,62 ****
    # in an unreadable format.
    pass
  
! LoginError = GDataObjects.LoginError
  
  
  class GConnections:
--- 56,62 ----
    # in an unreadable format.
    pass
  
! LoginError = Exceptions.LoginError
  
  
  class GConnections:
***************
*** 185,191 ****
  
    def getConnection(self, connection_name):
  
-     print "getConnection: %s" % (connection_name)
  
      connection_name = connection_name.lower()
  
--- 185,190 ----
***************
*** 201,208 ****
      # their own transactions, etc.
      connection_base = connection_name.split(':')[0]
  
-     print "connection_base=%s" % connection_base
- 
      # This will throw a GConnections.NotFoundError if an unknown
      # connection name is specified.  The calling method should
      # catch this exception and handle it properly (exit w/message)
--- 200,205 ----
***************
*** 218,231 ****
        basedriver = driver
        extradriver = ""
  
-     print "basedriver: %s; extradriver=%s" % (basedriver, extradriver)
- 
      path = []
  
      dbdriver = None
  
      basemodule = _find_base_driver(basedriver, ALLDRIVERS)
-     print "basemodule=%s" % basemodule
      GDebug.printMesg(1,'Using %s as base driver for %s' %  (basemodule, 
driver))
  
      if basemodule:
--- 215,225 ----
***************
*** 233,239 ****
  
      if not dbdriver:
        tmsg = _("No database driver found for provider type '%s'") % driver
!       raise GDataObjects.ProviderNotSupportedError, tmsg
  
  
      conn = dbdriver.Connection(self, connection_name, parameters)
--- 227,233 ----
  
      if not dbdriver:
        tmsg = _("No database driver found for provider type '%s'") % driver
!       raise Exceptions.ProviderNotSupportedError, tmsg
  
  
      conn = dbdriver.Connection(self, connection_name, parameters)
***************
*** 247,266 ****
    #
    def getDataObject(self, connection_name, connection_type):
  
-     print "getDataObject: %s %s" % (connection_name, connection_type)
- 
      # This will throw a GConnections.NotFoundError if an unknown
      # connection name is specified.  The calling method should
      # catch this exception and handle it properly (exit w/message)
      connection = self.getConnection(connection_name)
  
      try:
!       dd = connection._supportedDataObjects[connection_type](connection)
        GDebug.printMesg (1,'Attaching to %s (%s)' % (dd.__class__.__name__, 
connection_type))
        return dd
      except KeyError:
        tmsg = _("DB Driver '%s' does not support source type '%s'") % 
(connection, connection_type)
!       raise GDataObjects.ObjectTypeNotAvailableError, tmsg
  
  
  
--- 241,258 ----
    #
    def getDataObject(self, connection_name, connection_type):
  
      # This will throw a GConnections.NotFoundError if an unknown
      # connection name is specified.  The calling method should
      # catch this exception and handle it properly (exit w/message)
      connection = self.getConnection(connection_name)
  
      try:
!       dd = connection.supportedDataObjects[connection_type](connection)
        GDebug.printMesg (1,'Attaching to %s (%s)' % (dd.__class__.__name__, 
connection_type))
        return dd
      except KeyError:
        tmsg = _("DB Driver '%s' does not support source type '%s'") % 
(connection, connection_type)
!       raise Exceptions.ObjectTypeNotAvailableError, tmsg
  
  
  
***************
*** 277,283 ****
    #
    def requestConnection(self, dataObject):
  
!     print "requestConnection: %s" % dataObject
  
      # Support for multiple open connections
      # to same database.
--- 269,276 ----
    #
    def requestConnection(self, dataObject):
  
!     print """TODO: once this branch makes it into CVS head,
!       eliminate the GConnections.requestConnection logic!"""
  
      # Support for multiple open connections
      # to same database.
***************
*** 286,291 ****
--- 279,285 ----
      # their own transactions, etc.
  
      self.loginToConnection(dataObject._connection)
+     dataObject.connect()
  
  
    def loginToConnection(self, connection):
***************
*** 293,299 ****
      connection_name = connection.name
      connection_base = connection_name.split(':')[0]
  
-     print "loginToConnection: %s" % connection
      try:
        connected = connection.__connected
      except AttributeError:
--- 287,292 ----
***************
*** 387,393 ****
              attempts = 0
              self._loginHandler.destroyLoginDialog()
  
!           except GDataObjects.LoginError, error:
              # Oops, they must have entered an invalid user/password.
              # Those silly users.
              # user: Hey! Who are you calling silly?!!!
--- 380,386 ----
              attempts = 0
              self._loginHandler.destroyLoginDialog()
  
!           except Exceptions.LoginError, error:
              # Oops, they must have entered an invalid user/password.
              # Those silly users.
              # user: Hey! Who are you calling silly?!!!
***************
*** 400,412 ****
                # Four times is plenty...
                #self._loginHandler.destroyLoginDialog()
                tmsg = _("Unable to log in after 4 attempts.\n\nError: %s") % 
error
!               raise GDataObjects.LoginError, tmsg
  
            except GLoginHandler.UserCanceledLogin:
              # Guess they changed their minds. Treat as a login error.
              self._loginHandler.destroyLoginDialog()
              tmsg = _("User canceled the login request.")
!             raise GDataObjects.LoginError, tmsg
  
      connection.__connected = 1
  
--- 393,405 ----
                # Four times is plenty...
                #self._loginHandler.destroyLoginDialog()
                tmsg = _("Unable to log in after 4 attempts.\n\nError: %s") % 
error
!               raise Exceptions.LoginError, tmsg
  
            except GLoginHandler.UserCanceledLogin:
              # Guess they changed their minds. Treat as a login error.
              self._loginHandler.destroyLoginDialog()
              tmsg = _("User canceled the login request.")
!             raise Exceptions.LoginError, tmsg
  
      connection.__connected = 1
  
Index: gnue-common/src/datasources/GDataObjects.py
diff -c gnue-common/src/datasources/GDataObjects.py:1.72.2.2 
gnue-common/src/datasources/GDataObjects.py:1.72.2.3
*** gnue-common/src/datasources/GDataObjects.py:1.72.2.2        Fri Oct 10 
08:18:48 2003
--- gnue-common/src/datasources/GDataObjects.py Tue Nov 18 21:07:06 2003
***************
*** 22,774 ****
  # GDataObjects.py
  #
  # DESCRIPTION:
! # Class
  #
  # NOTES:
  #
! # HISTORY:
  #
  
! from gnue.common.apps import GDebug
! from gnue.common.datasources import GConditions
! import string
! 
! postingRecordset = None
! 
! class Error(StandardError):
!   # Base exception
!   pass
! 
! class LoginError(Error):
!   # Raised when invalid login user/pass was provided
!   # Client should attempt to get better information and
!   # try again
!   pass
! 
! class ConnectError(Error):
!   # Raised when connection data is invalid (e.g., host not found, etc).
!   # Client should probably not attempt to relogin.  Exit gracefully
!   # with a reason.
!   pass
! 
! class ProviderNotSupportedError(Error):
!   # Raised when a datasource type is requested that the dbdriver
!   # does not support (e.g., not all dbdrivers support raw sql mode.)
!   pass
! 
! class ObjectTypeNotAvailableError(Error):
!   # Raised when a datasource type is requested that the dbdriver
!   # does not support (e.g., not all dbdrivers support raw sql mode.)
!   pass
! 
! class ReadOnlyError(Error):
!   # Raised when an attempt is made to update a read-only data object.
!   pass
! 
! class MasterDetailFieldMismatch(Error):
!   # Raised when a the number of master fields doesn't match the
!   # number of detail fields. (e.g., masterlink="id,subid"
!   # and detaillink="id" would be a problem; must be 1:1)
!   pass
! 
! class ConnectionError(Error):
!   # Generic error reading from the database connection
!   pass
! 
! class DataTypeNotAvailable(Error):
!   # Raised when a datatype is not supported by an database
!   # during writing a schema definition to the database
!   pass
! 
! class NoWriteSchemaSupport(Error):
!   # Raised when a database adapter doesn't support
!   # writing Schema to datasource
!   pass
! 
! 
! 
! ###########################################################
! #
! #
! #
! ###########################################################
! class DataObject:
! 
!   def __init__(self, connection):
!     self._connection = connection
! 
!     self.masterlink = ""
!     self.detaillink = ""
! 
!     self._masterfields = []
!     self._detailfields = []
!     self._staticCondition = None
! 
!     self._masterObject = None
!     self._detailObjects = []
!     self._dataConnection = None
!     self._resultSetClass = ResultSet
!     self._fieldReferences = {}  # Set by GDataSource; lists all fields
!                                 # a client explicitly references
! 
!     self._unboundFieldReferences = {}  # Contains names of all unbound
!                                        # field references
! 
!     self._defaultValues = {}
! 
!     self._unicodeMode = 0 # if set to true, datasources will unicode
!                           # strings instead of strings in local encoding
!                           # and if non unicode strings are passed to the
!                           # db driver a warning is raised (in 0.6.0 an
!                           # exception will be raised)
! 
!     # TODO: This is to keep old code from breaking.
!     # TODO: 0.5.1 was last version to support
!     # TODO triggerExtensions (functionality is now
!     # TODO: encapsulated in Connection objects.
!     self.triggerExtensions = connection
! 
!   # Do we have a master datasource?
!   def hasMaster(self):
!     return self._masterObject != None
! 
!   # Do not over-ride by vendor code
!   def createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
!     return self._createResultSet(
!        GConditions.combineConditions(conditions, self._staticCondition),
!        readOnly=readOnly, masterRecordSet=masterRecordSet, sql=sql)
! 
!   # Designed to be replaced by vendor-specific code
!   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
\
!                        sql=""):
!     pass
! 
!   # Do not over-ride by vendor code
!   def getQueryString(self,conditions={},forDetailSQL=None,additionalSQL=""):
!     return self._buildQuery(conditions,forDetailSQL,additionalSQL)
! 
!   def createEmptyResultSet(self, readOnly=0, masterRecordSet=None):
!     return self._createEmptyResultSet(readOnly, masterRecordSet)
! 
!   # Designed to be replaced by vendor-specific code
!   def _createEmptyResultSet(self, readOnly=0, masterRecordSet=None):
!     cond = GConditions.GCondition()
!     ceq = GConditions.GCeq(cond)
!     GConditions.GCConst(ceq,1,"number")
!     GConditions.GCConst(ceq,0,"number")
!     return self.createResultSet(conditions=cond, readOnly=readOnly,
!                                 masterRecordSet=masterRecordSet)
! 
! 
!   # Add a detail data object.  This dataobject will create a new resultset
!   # everytime this dataobject changes (new record, etc).  The optional
!   # handler will be called after the detail dataobject is notified.  The
!   # client application may wish to add a handler to know when the detail
!   # has been requeried.  handler is a method that takes two arguments:
!   # the master ResultSet and the detail ResultSet
!   def addDetailDataObject(self, dataObject, handler=None, **params):
! 
!     dataObject.__dict__.update(params)
! 
!     GDebug.printMesg (1,"Adding a master/detail relationship to DataObject")
!     dataObject._masterObject = self
!     dataObject._masterfields = string.split(hasattr(dataObject,'masterlink') 
and \
!                                  string.lower(dataObject.masterlink) or "", 
',')
!     dataObject._detailfields = string.split(hasattr(dataObject,'detaillink') 
and \
!                                  string.lower(dataObject.detaillink) or "", 
',')
! 
!     if len(dataObject._masterfields) != len(dataObject._detailfields):
!       tmsg = _("master=%s; detail=%s") % (dataObject._masterfields, 
dataObject._detailfields)
!       raise MasterDetailFieldMismatch, tmsg
! 
!     # Make sure "master" fields will be in our future query
!     for field in dataObject._masterfields:
!       self._fieldReferences[string.strip(field)] = ""
! 
!     for field in dataObject._detailfields:
!       dataObject._fieldReferences[string.strip(field)] = ""
! 
!     self._detailObjects.append ([dataObject, handler])
! 
! 
!   #
!   # Connect to database from a GConnection object
!   #
!   def connect(self):
!     self._dataConnection = self._connection.native
!     self._postConnect()
! 
!   def commit(self):
!     pass
! 
!   def rollback(self):
!     pass
! 
! 
!   #
!   # Schema (metadata) functions
!   #
! 
!   # TODO: DEPRECATED!!!!!
!   def getSchemaTypes(self):
!     print "WARNING: Your app is calling GDataObject.getSchemaTypes()"
!     return self._connection.schema.types[:]
! 
!   # TODO: DEPRECATED!!!!!
!   def getSchemaList(self, type=None):
!     print "WARNING: Your app is calling GDataObject.getSchemaList()"
!     return self._connection.schema.find(type=type)
! 
!   # TODO: DEPRECATED!!!!!
!   def getSchemaByName(self, name, type=None):
!     print "WARNING: Your app is calling GDataObject.getSchemaByName()"
!     return self._connection.schema.findfirst(name=name, type=type)
! 
! 
! 
! 
!   # Called when new record master in master/detail is queried
!   def _masterRecordChanged(self, master):
!     GDebug.printMesg (5, 'Master Record Changed')
!     criteria = {}
! 
!     # If a detail result set has already been created for a particular
!     # master record set, then just return/reuse this old set (after all,
!     # it may contain uncommitted changes)
!     if (not master.current._cachedDetailResultSets.has_key(self)) or \
!         ( not int(gConfig('CacheDetailRecords')) and \
!           not master.current._cachedDetailResultSets[self].isPending() ):
!       doQuery = None
!       for i in range(0, len(self._masterfields)):
!         GDebug.printMesg(10,"Adding criteria")
!         criteria[string.strip(self._detailfields[i])] = \
!             master.current.getField(string.strip(self._masterfields[i]))
! 
!         #If all are set to None then this will prevent the details
!         #from being queried.  This happens are startup with blank master
!         #datasources.
!         doQuery = doQuery or 
master.current.getField(string.strip(self._masterfields[i]))
! 
!         GDebug.printMesg(10,master.current.getField(self._masterfields[i]))
!       if doQuery:
!         master.current.addDetailResultSet(self.createResultSet(\
!              conditions=criteria, masterRecordSet=master.current))
!       else:
!         master.current.addDetailResultSet(self.createEmptyResultSet())
! ##      master.current._cachedDetailResultSets[self] = \
! ##          self.createResultSet(conditions=criteria, 
masterRecordSet=master.current)
!     return master.current._cachedDetailResultSets[self]
! 
! 
! ###########################################################
! #
! #
! #
! ###########################################################
! class ResultSet:
! 
!   def __init__(self, dataObject, 
cursor=None,defaultValues={},masterRecordSet=None):
!      self._dataObject = dataObject
!      self._recordSetClass = RecordSet
!      self._cursor = cursor
!      self._cachedRecords = []
!      self._currentRecord = -1
!      self._masterRecordSet = masterRecordSet
!      self._readonly = 0
!      self._recordCount = 0
!      self._postingRecord = None
! 
!      self._defaultValues = {}
!      self._defaultValues.update(defaultValues)
! 
!      self.current = None
! 
!      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()
! 
!   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):
!     return self._readonly
! 
! 
!   # Returns 1=At first record, 0=Not first record
!   def isFirstRecord(self):
!     return (self._currentRecord == 0)
! 
! 
!   # Returns 1=At last record, 0=Not last record
!   def isLastRecord(self):
!     if self._currentRecord < len(self._cachedRecords) - 1 or \
!        self._cacheNextRecord():
!       return 0
!     else:
!       return 1
! 
! 
!   # returns -1=No records in memory, #=Current record #
!   def getRecordNumber(self):
!     return self._currentRecord
! 
! 
!   # returns # of records currently loaded
!   def getCacheCount(self):
!     return len(self._cachedRecords)
! 
!   # returns # of records the
!   def getRecordCount(self):
!     return self._recordCount  > 0 and self._recordCount or 
self.getCacheCount()
! 
!   # Get a specific record (0=based)
!   def getRecord(self, record):
!     while (record + 1 > len(self._cachedRecords)) and self._cacheNextRecord():
!       pass
! 
!     if record + 1 > len(self._cachedRecords):
!       return None
!     else:
!       return self._cachedRecords[record]
! 
! 
!   # move to record #, returns 1=New record loaded, 0=invalid #
!   def setRecord(self, record):
! 
!     while (record > len(self._cachedRecords) -1) and self._cacheNextRecord():
!       pass
! 
!     if record >= len(self._cachedRecords):
!       return None
!     else:
!       self._currentRecord = record
!       self.current = self._cachedRecords[self._currentRecord]
!       self.notifyDetailObjects()
!       return self.current
! 
!   # returns 1=New record loaded, 0=No more records
!   def nextRecord(self):
!     if self._currentRecord + 1 == len(self._cachedRecords):
!       if not self._cacheNextRecord():
!         return None
! 
!     self._currentRecord += 1
!     self.current = self._cachedRecords[self._currentRecord]
!     self.notifyDetailObjects()
!     return self.current
! 
! 
!   # returns 1=New record loaded, 0=At first record
!   def prevRecord(self):
!     if self._currentRecord < 1:
!       return None
!     else:
!       self._currentRecord -= 1
!       self.current = self._cachedRecords[self._currentRecord]
!       self.notifyDetailObjects()
!       return self.current
! 
! 
!   # returns 1=at first record, 0=No records loaded
!   def firstRecord(self):
!     if self._currentRecord < 0:
!       if not self._cacheNextRecord():
!         return None
! 
!     self._currentRecord = 0
!     self.current = self._cachedRecords[0]
!     self.notifyDetailObjects()
!     return self.current
! 
! 
! 
!   # returns 1=at last record, 0=No records loaded
!   def lastRecord(self):
!     if self._currentRecord == -1:
!       return None
!     else:
!       while self._cacheNextRecord():
!         pass
!       self._currentRecord = len(self._cachedRecords) - 1
!       self.current = self._cachedRecords[self._currentRecord]
!       self.notifyDetailObjects()
!       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 ReadOnlyError, tmsg
!     else:
!       GDebug.printMesg(7,'Inserting a blank record')
!       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():
!         self.current.setField(field, self._dataObject._defaultValues[field],0)
! 
!       # Set any resultset specific values
!       for field in self._defaultValues.keys():
!         self.current.setField(field, self._defaultValues[field],0)
! 
!       # 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:
!           
self.current.setField(self._dataObject._detailfields[i],self._masterRecordSet.getField(field),0)
!           i += 1
! 
!       self.notifyDetailObjects()
!       return self.current
! 
! 
!   # Returns 1=DataObject, or a detail resultset, has uncommitted changes
!   def isPending(self):
!     for rec in (self._cachedRecords):
!       if rec.isPending():
!         return 1
!       else:
!         for detail in rec._cachedDetailResultSets.values():
!           if detail.isPending():
!             return 1
!     return 0
! 
! 
!   # Returns 1=DataObject has uncommitted changes
!   def isRecordPending(self):
!     return self.current.isPending()
! 
! 
!   def getPostingRecordset(self):
!     global postingRecordset
!     print postingRecordset
!     return postingRecordset
! 
!   # Post changes to the database
!   def post(self, foreign_keys={}):
!     global postingRecordset
!     # post our changes
!     self._update_cursor = self._dataObject._dataConnection.cursor()
! 
!     recordPosition = 0
!     while recordPosition < len(self._cachedRecords):
!       self._postingRecord = self._cachedRecords[recordPosition]
!       postingRecordset = self._postingRecord
!       delete = self._postingRecord._emptyFlag or 
self._postingRecord._deleteFlag
!       if not delete:
!         # Flip the flag for 'default' values to true so that hidden
!         # default fields are included in insert statements
!         if self._postingRecord.isPending():
!           for field in self._dataObject._defaultValues.keys():
!             self._postingRecord._modifiedFlags[field] = 1
! 
!         for field in foreign_keys.keys():
!           self._postingRecord._fields[field] = foreign_keys[field]
!           # Some DBs will throw an exception if you update a Primary Key
!           # (even if you are updating to the same value)
!           if self._postingRecord._insertFlag:
!             self._postingRecord._modifiedFlags[field] = 1
! 
!         recordPosition += 1
!       else:
!         # Adjust the current record if a preceding record
!         # or the current record is deleted
!         if recordPosition <= self._currentRecord:
!           self._currentRecord -= 1
!         self._cachedRecords.pop(recordPosition)
!         self._recordCount -= 1
! 
!       self._postingRecord.post()
! 
!     # Move to record 0 if all preceding records were deleted
!     # (or set to -1 if all records were deleted)
!     if self._currentRecord < 0:
!       if len(self._cachedRecords):
!         self._currentRecord = 0
!       else:
!         self._currentRecord = -1
! # TODO: I don't think we need this anymore
! #    if self._currentRecord >= self._recordCount:
! #      self._currentRecord = self._recordCount - 1
! 
!   def notifyDetailObjects(self):
!     GDebug.printMesg(5,'Master record changed; Notifying Detail Objects')
!     for detail in self._dataObject._detailObjects:
!       if detail[1]:
!         detail[1].masterResultSetChanged(self,
!                                          detail[0]._masterRecordChanged(self))
! 
! 
!   # Returns 1=Field is bound to a database field
!   def isFieldBound(self, fieldName):
!     if self._dataObject._fieldReferences.has_key(fieldName):
!       return 1
!     else:
!       #TODO: the string.lower() line should never be called but is left
!       #TODO: here untill the code is cleaned up
!       return 
self._dataObject._fieldReferences.has_key(string.lower(fieldName))
! 
! 
!   # Load cacheCount number of new records
!   def _cacheNextRecord(self):
!     rs = self._loadNextRecord()
!     if rs:
!       self._dataObject._dataSource._onRecordLoaded(self._cachedRecords[-1])
!     return rs
! 
! 
! 
!   ###
!   ### 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 0
! 
!   # Create an empty recordset
!   def _createEmptyRecord(self):
!     return self._recordSetClass(self)
! 
!   # Iterator support (Python 2.2+)
!   def __iter__(self):
!     return _ResultSetIter(self)
! 
! 
! ###########################################################
! #
! #
! #
! ###########################################################
! class RecordSet:
! 
!   def __init__(self, parent, initialData={}, dbIdentifier=None, 
defaultData={}):
!     self._detailObjects = []
!     self._dbIdentifier = dbIdentifier
!     self._deleteFlag = 0
!     self._updateFlag = 0
!     self._parent = parent
!     self._modifiedFlags = {}      # If field name is present as a key,
!                                   # then field has been modified
! 
!     self._cachedDetailResultSets = {}
! 
!     self._initialData = initialData
! 
!     if self._initialData and len(self._initialData):
!       self._insertFlag = 0
!       self._emptyFlag = 0
!       self._fields = {}
!       self._fields.update(initialData)
!     else:
!       self._insertFlag = 1
!       self._emptyFlag = 1
!       self._fields = {}
!       self._fields.update(defaultData)
! 
!   def __setitem__(self, attr, val):
!     self.setField(attr, val)
! 
!   def __getitem__(self, attr):
!     return self.getField(attr)
! 
!   # Returns 1=Record has uncommitted changes
!   def isPending(self):
! 
!     # The _insertFlag and _deleteFlag takes care of records that
!     # were inserted, but then deleted before a save (i.e., nothing to do)
!     if self._emptyFlag or self._insertFlag and self._deleteFlag:
!       return 0
!     else:
!       return self._insertFlag or self._deleteFlag or self._updateFlag
! 
! 
!   # Returns 1=Record is pending a deletion
!   def isDeleted(self):
!     if self._emptyFlag:
!       return 0
!     else:
!       return self._deleteFlag and not self._insertFlag
! 
! 
!   # Returns 1=Record is pending an update
!   def isModified(self):
!     if self._emptyFlag or self._insertFlag:
!       return 0
!     else:
!       return self._updateFlag
! 
! 
!   # Returns 1=Record is pending an insertion
!   def isInserted(self):
!     if self._emptyFlag:
!       return 0
!     else:
!       return self._insertFlag and not self._deleteFlag
! 
! 
!   # Returns 1=Record is empty (inserted, but no data set)
!   def isEmpty(self):
!     return self._emptyFlag
! 
! 
!   # Returns current value of "field"
!   def getField(self, field):
!     try:
!       return self._fields[field]
!     except KeyError:
!       try:
! 
!         # TODO: When we're confident that
!         # TODO: all field names are lowercase,
!         # TODO: then this can be removed.
! 
!         return self._fields[string.lower(field)]
!       except KeyError:
!         # If a field value has yet to be set
!         # (either from a query or via a setField),
!         # then _fields will not contain a key
!         # for the requested field even though
!         # the field name may still be valid.
!         return None
! 
! 
!   # Sets current value of "field"
!   # If trackMod is set to 0 then the modification flag isn't raised
!   def setField(self, field, value, trackMod = 1):
!     # If this field is bound to a datasource and the datasource is read only,
!     # generate an error.
!     if self._parent.isFieldBound(field) and self._parent.isReadOnly():
!       # Provide better feedback??
!       tmsg = _("Attempted to modify read only field '%s'") % field
!       raise ReadOnlyError, tmsg
!     else:
!       fn = string.lower(field)
!       self._fields[fn] = value
!       if trackMod == 1:
!         if self._parent.isFieldBound(field):
!           self._emptyFlag = 0
!           self._updateFlag = 1
!           self._modifiedFlags[fn] = 1
! 
!           try:
!             self._parent._dataObject._dataSource._onModification(self)
!           except AttributeError:
!             pass
!     return value
! 
!   # Batch mode of above setField method
!   # If trackMod is set to 0 then the modification flag isn't raised
!   def setFields(self, updateDict, trackMod = 1):
!     # If this field is bound to a datasource and the datasource is read only,
!     # generate an error.
!     for field in updateDict.keys():
!       self.setField(field, updateDict[field], trackMod)
! 
! 
!   # Returns 1=Field has been modified
!   def isFieldModified(self, fieldName):
!     if self._modifiedFlags.has_key (fieldName):
!       return 1
!     else:
!       #TODO: the string.lower() line should never be called but is left here
!       #TODO: until the code is clean
!       return self._modifiedFlags.has_key (string.lower(fieldName))
! 
! 
!   # Mark the current record as deleted
!   def delete(self):
!     if self._parent.isReadOnly():
!       # Provide better feedback??
!       tmsg = _("Attempted to delete from a read only datasource")
!       raise ReadOnlyError, tmsg
!     else:
!       self._deleteFlag = 1
! 
! 
!   # Posts changes to database
!   def post(self):
!     # Should a post() to a read only datasource cause a ReadOnlyError?
!     # It does no harm to attempt to post since nothing will be posted,
!     # But does this allow sloppy programming?
! 
!     GDebug.printMesg(5,'Preparing to post datasource %s' %  
self._parent._dataObject.name)
! 
!     # Save the initial status so we know if any triggers changed us
!     status = (self._insertFlag, self._deleteFlag, self._updateFlag)
! 
!     # Call the hooks for commit-level hooks
!     if not self._emptyFlag and 
hasattr(self._parent._dataObject,'_dataSource'):
! 
!       if self._insertFlag and not self._deleteFlag:
!         self._parent._dataObject._dataSource._beforeCommitInsert(self)
!       elif self._deleteFlag and not self._insertFlag:
!         self._parent._dataObject._dataSource._beforeCommitDelete(self)
!       elif self._updateFlag:
!         self._parent._dataObject._dataSource._beforeCommitUpdate(self)
! 
!     #
!     # If the record status changed while we were doing the triggers,
!     # start from the beginning and run the triggers again.
!     #
!     if status != (self._insertFlag, self._deleteFlag, self._updateFlag):
!       self.post()
!       return
! 
! 
!     if self.isPending():
!       GDebug.printMesg(5,'Posting datasource %s' % 
self._parent._dataObject.name)
! 
!       if self.isPending():
!         self._postChanges()
! 
! 
!     # Post all detail records
!     for child in (self._cachedDetailResultSets.keys()):
!       c = self._cachedDetailResultSets[child]._dataObject
!       # Set the primary key for any new child records
!       fk = {}
!       for i in range(len(c._masterfields)):
!         fk[c._detailfields[i]] = self.getField(c._masterfields[i])
! 
!       self._cachedDetailResultSets[child].post(foreign_keys=fk)
! 
! 
!   # Sets the ResultSet associated with this master record
!   def addDetailResultSet(self, resultSet):
!     self._cachedDetailResultSets[resultSet._dataObject] = resultSet
! 
! 
!   ###
!   ### Methods below should be over-written by Vendor Specific functions
!   ###
! 
!   # Post any changes to database
!   def _postChanges(self):
!     return 1
  
  
  # Used to store schema data
  class Schema:
    def __init__(self, attrs={}, getChildSchema=None):
      self.name = ''
--- 22,42 ----
  # GDataObjects.py
  #
  # DESCRIPTION:
! # This is a temporary backwards compatability file.
! # Should be removed at some point.
  #
  # NOTES:
  #
! # TODO: Generate warnings whenever anything in this file is accessed.
  #
  
! from Exceptions import *
! from drivers.Base import *
  
  
  # Used to store schema data
+ # TODO: Is this used anywhere??
+ import string
  class Schema:
    def __init__(self, attrs={}, getChildSchema=None):
      self.name = ''
***************
*** 789,823 ****
      return ()
  
  
- 
- # 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 = 0
-     self.done = 0
- 
-   def __iter__(self):
-     return self
- 
-   def next(self):
-     if self.done:
-       raise StopIteration
-     if self.used:
-       rs = self.resultset.firstRecord()
-     else:
-       rs = self.resultset.nextRecord()
- 
-     if not rs:
-       raise StopIteration
-     else:
-       return rs
  
--- 57,60 ----
Index: gnue-common/src/datasources/drivers/Base/Connection.py
diff -c /dev/null gnue-common/src/datasources/drivers/Base/Connection.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/drivers/Base/Connection.py      Tue Nov 18 
21:07:07 2003
***************
*** 0 ****
--- 1,71 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # Connection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['Connection']
+ 
+ 
+ # System Init:
+ #   +-- GConnections initializes
+ #   +-- GParser initializes:
+ #     +-- GDataSource loaded
+ #   +-- GDataSources Intialized
+ #     +-- GConnection.getDataObject()
+ #       +--
+ #
+ class Connection:
+   def __init__(self, connections, name, parameters):
+     self.manager = connections
+     self.parameters = parameters
+     self.name = name
+ 
+     # Text encoding used by the database.
+     # (Not all databases support this concept)
+     try:
+       self._encoding = parameters['encoding']
+     except KeyError:
+       try:
+          self._encoding = gConfig('textEncoding')
+       except KeyError:
+         # TODO: Is this a safe default?
+         self._encoding = 'iso8859-1'
+ 
+ 
+   # Commit changes to the database
+   def commit(self):
+     pass
+ 
+   # Rollback changes to the database
+   def rollback(self):
+     pass
+ 
+   # Close the connection to the database backend
+   def close(self):
+     pass
+ 
+   def connect(self, connectData):
+     pass
\ No newline at end of file
Index: gnue-common/src/datasources/drivers/Base/DataObject.py
diff -c /dev/null gnue-common/src/datasources/drivers/Base/DataObject.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/drivers/Base/DataObject.py      Tue Nov 18 
21:07:07 2003
***************
*** 0 ****
--- 1,209 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # DataObject.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['DataObject']
+ 
+ from ResultSet import ResultSet
+ 
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GConditions, Exceptions
+ import string
+ 
+ from ResultSet import ResultSet
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class DataObject:
+ 
+   _resultSetClass = ResultSet
+ 
+   def __init__(self, connection):
+     self._connection = connection
+ 
+     self.masterlink = ""
+     self.detaillink = ""
+ 
+     self._masterfields = []
+     self._detailfields = []
+     self._staticCondition = None
+ 
+     self._masterObject = None
+     self._detailObjects = []
+     self._dataConnection = None
+     self._fieldReferences = {}  # Set by GDataSource; lists all fields
+                                 # a client explicitly references
+ 
+     self._unboundFieldReferences = {}  # Contains names of all unbound
+                                        # field references
+ 
+     self._defaultValues = {}
+ 
+     self._unicodeMode = 0 # if set to true, datasources will unicode
+                           # strings instead of strings in local encoding
+                           # and if non unicode strings are passed to the
+                           # db driver a warning is raised (in 0.6.0 an
+                           # exception will be raised)
+ 
+     # TODO: This is to keep old code from breaking.
+     # TODO: 0.5.1 was last version to support
+     # TODO triggerExtensions (functionality is now
+     # TODO: encapsulated in Connection objects.
+     self.triggerExtensions = connection
+ 
+   # Do we have a master datasource?
+   def hasMaster(self):
+     return self._masterObject != None
+ 
+   # Do not over-ride by vendor code
+   def createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
sql=""):
+     return self._createResultSet(
+        GConditions.combineConditions(conditions, self._staticCondition),
+        readOnly=readOnly, masterRecordSet=masterRecordSet, sql=sql)
+ 
+   # Designed to be replaced by vendor-specific code
+   def _createResultSet(self, conditions={}, readOnly=0, masterRecordSet=None, 
\
+                        sql=""):
+     pass
+ 
+   # Do not over-ride by vendor code
+   def getQueryString(self,conditions={},forDetailSQL=None,additionalSQL=""):
+     return self._buildQuery(conditions,forDetailSQL,additionalSQL)
+ 
+   def createEmptyResultSet(self, readOnly=0, masterRecordSet=None):
+     return self._createEmptyResultSet(readOnly, masterRecordSet)
+ 
+   # Designed to be replaced by vendor-specific code
+   def _createEmptyResultSet(self, readOnly=0, masterRecordSet=None):
+     cond = GConditions.GCondition()
+     ceq = GConditions.GCeq(cond)
+     GConditions.GCConst(ceq,1,"number")
+     GConditions.GCConst(ceq,0,"number")
+     return self.createResultSet(conditions=cond, readOnly=readOnly,
+                                 masterRecordSet=masterRecordSet)
+ 
+ 
+   # Add a detail data object.  This dataobject will create a new resultset
+   # everytime this dataobject changes (new record, etc).  The optional
+   # handler will be called after the detail dataobject is notified.  The
+   # client application may wish to add a handler to know when the detail
+   # has been requeried.  handler is a method that takes two arguments:
+   # the master ResultSet and the detail ResultSet
+   def addDetailDataObject(self, dataObject, handler=None, **params):
+ 
+     dataObject.__dict__.update(params)
+ 
+     GDebug.printMesg (1,"Adding a master/detail relationship to DataObject")
+     dataObject._masterObject = self
+     dataObject._masterfields = string.split(hasattr(dataObject,'masterlink') 
and \
+                                  string.lower(dataObject.masterlink) or "", 
',')
+     dataObject._detailfields = string.split(hasattr(dataObject,'detaillink') 
and \
+                                  string.lower(dataObject.detaillink) or "", 
',')
+ 
+     if len(dataObject._masterfields) != len(dataObject._detailfields):
+       tmsg = _("master=%s; detail=%s") % (dataObject._masterfields, 
dataObject._detailfields)
+       raise Exceptions.MasterDetailFieldMismatch, tmsg
+ 
+     # Make sure "master" fields will be in our future query
+     for field in dataObject._masterfields:
+       self._fieldReferences[string.strip(field)] = ""
+ 
+     for field in dataObject._detailfields:
+       dataObject._fieldReferences[string.strip(field)] = ""
+ 
+     self._detailObjects.append ([dataObject, handler])
+ 
+   #
+   # Connect to database from a GConnection object
+   #
+   def connect(self):
+     self._dataConnection = self._connection.native
+ 
+   def commit(self):
+     pass
+ 
+   def rollback(self):
+     pass
+ 
+ 
+   #
+   # Schema (metadata) functions
+   #
+ 
+   # TODO: DEPRECATED!!!!!
+   def getSchemaTypes(self):
+     print "WARNING: Your app is calling GDataObject.getSchemaTypes()"
+     return self._connection.schema.types[:]
+ 
+   # TODO: DEPRECATED!!!!!
+   def getSchemaList(self, type=None):
+     print "WARNING: Your app is calling GDataObject.getSchemaList()"
+     return self._connection.schema.find(type=type)
+ 
+   # TODO: DEPRECATED!!!!!
+   def getSchemaByName(self, name, type=None):
+     print "WARNING: Your app is calling GDataObject.getSchemaByName()"
+     return self._connection.schema.findfirst(name=name, type=type)
+ 
+ 
+ 
+ 
+   # Called when new record master in master/detail is queried
+   def _masterRecordChanged(self, master):
+     GDebug.printMesg (5, 'Master Record Changed')
+     criteria = {}
+ 
+     # If a detail result set has already been created for a particular
+     # master record set, then just return/reuse this old set (after all,
+     # it may contain uncommitted changes)
+     if (not master.current._cachedDetailResultSets.has_key(self)) or \
+         ( not int(gConfig('CacheDetailRecords')) and \
+           not master.current._cachedDetailResultSets[self].isPending() ):
+       doQuery = None
+       for i in range(0, len(self._masterfields)):
+         GDebug.printMesg(10,"Adding criteria")
+         criteria[string.strip(self._detailfields[i])] = \
+             master.current.getField(string.strip(self._masterfields[i]))
+ 
+         #If all are set to None then this will prevent the details
+         #from being queried.  This happens are startup with blank master
+         #datasources.
+         doQuery = doQuery or 
master.current.getField(string.strip(self._masterfields[i]))
+ 
+         GDebug.printMesg(10,master.current.getField(self._masterfields[i]))
+       if doQuery:
+         master.current.addDetailResultSet(self.createResultSet(\
+              conditions=criteria, masterRecordSet=master.current))
+       else:
+         master.current.addDetailResultSet(self.createEmptyResultSet())
+ ##      master.current._cachedDetailResultSets[self] = \
+ ##          self.createResultSet(conditions=criteria, 
masterRecordSet=master.current)
+     return master.current._cachedDetailResultSets[self]
+ 
Index: gnue-common/src/datasources/drivers/Base/RecordSet.py
diff -c /dev/null gnue-common/src/datasources/drivers/Base/RecordSet.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/drivers/Base/RecordSet.py       Tue Nov 18 
21:07:07 2003
***************
*** 0 ****
--- 1,246 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # GConnection.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['RecordSet']
+ 
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GConditions, Exceptions
+ import string
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class RecordSet:
+ 
+   def __init__(self, parent, initialData={}, dbIdentifier=None, 
defaultData={}):
+     self._detailObjects = []
+     self._dbIdentifier = dbIdentifier
+     self._deleteFlag = 0
+     self._updateFlag = 0
+     self._parent = parent
+     self._modifiedFlags = {}      # If field name is present as a key,
+                                   # then field has been modified
+ 
+     self._cachedDetailResultSets = {}
+ 
+     self._initialData = initialData
+ 
+     if self._initialData and len(self._initialData):
+       self._insertFlag = 0
+       self._emptyFlag = 0
+       self._fields = {}
+       self._fields.update(initialData)
+     else:
+       self._insertFlag = 1
+       self._emptyFlag = 1
+       self._fields = {}
+       self._fields.update(defaultData)
+ 
+   def __setitem__(self, attr, val):
+     self.setField(attr, val)
+ 
+   def __getitem__(self, attr):
+     return self.getField(attr)
+ 
+   # Returns 1=Record has uncommitted changes
+   def isPending(self):
+ 
+     # The _insertFlag and _deleteFlag takes care of records that
+     # were inserted, but then deleted before a save (i.e., nothing to do)
+     if self._emptyFlag or self._insertFlag and self._deleteFlag:
+       return 0
+     else:
+       return self._insertFlag or self._deleteFlag or self._updateFlag
+ 
+ 
+   # Returns 1=Record is pending a deletion
+   def isDeleted(self):
+     if self._emptyFlag:
+       return 0
+     else:
+       return self._deleteFlag and not self._insertFlag
+ 
+ 
+   # Returns 1=Record is pending an update
+   def isModified(self):
+     if self._emptyFlag or self._insertFlag:
+       return 0
+     else:
+       return self._updateFlag
+ 
+ 
+   # Returns 1=Record is pending an insertion
+   def isInserted(self):
+     if self._emptyFlag:
+       return 0
+     else:
+       return self._insertFlag and not self._deleteFlag
+ 
+ 
+   # Returns 1=Record is empty (inserted, but no data set)
+   def isEmpty(self):
+     return self._emptyFlag
+ 
+ 
+   # Returns current value of "field"
+   def getField(self, field):
+     try:
+       return self._fields[field]
+     except KeyError:
+       try:
+ 
+         # TODO: When we're confident that
+         # TODO: all field names are lowercase,
+         # TODO: then this can be removed.
+ 
+         return self._fields[string.lower(field)]
+       except KeyError:
+         # If a field value has yet to be set
+         # (either from a query or via a setField),
+         # then _fields will not contain a key
+         # for the requested field even though
+         # the field name may still be valid.
+         return None
+ 
+ 
+   # Sets current value of "field"
+   # If trackMod is set to 0 then the modification flag isn't raised
+   def setField(self, field, value, trackMod = 1):
+     # If this field is bound to a datasource and the datasource is read only,
+     # generate an error.
+     if self._parent.isFieldBound(field) and self._parent.isReadOnly():
+       # Provide better feedback??
+       tmsg = _("Attempted to modify read only field '%s'") % field
+       raise Exceptions.ReadOnlyError, tmsg
+     else:
+       fn = string.lower(field)
+       self._fields[fn] = value
+       if trackMod == 1:
+         if self._parent.isFieldBound(field):
+           self._emptyFlag = 0
+           self._updateFlag = 1
+           self._modifiedFlags[fn] = 1
+ 
+           try:
+             self._parent._dataObject._dataSource._onModification(self)
+           except AttributeError:
+             pass
+     return value
+ 
+   # Batch mode of above setField method
+   # If trackMod is set to 0 then the modification flag isn't raised
+   def setFields(self, updateDict, trackMod = 1):
+     # If this field is bound to a datasource and the datasource is read only,
+     # generate an error.
+     for field in updateDict.keys():
+       self.setField(field, updateDict[field], trackMod)
+ 
+ 
+   # Returns 1=Field has been modified
+   def isFieldModified(self, fieldName):
+     if self._modifiedFlags.has_key (fieldName):
+       return 1
+     else:
+       #TODO: the string.lower() line should never be called but is left here
+       #TODO: until the code is clean
+       return self._modifiedFlags.has_key (string.lower(fieldName))
+ 
+ 
+   # Mark the current record as deleted
+   def delete(self):
+     if self._parent.isReadOnly():
+       # Provide better feedback??
+       tmsg = _("Attempted to delete from a read only datasource")
+       raise Exceptions.ReadOnlyError, tmsg
+     else:
+       self._deleteFlag = 1
+ 
+ 
+   # Posts changes to database
+   def post(self):
+     # Should a post() to a read only datasource cause a ReadOnlyError?
+     # It does no harm to attempt to post since nothing will be posted,
+     # But does this allow sloppy programming?
+ 
+     GDebug.printMesg(5,'Preparing to post datasource %s' %  
self._parent._dataObject.name)
+ 
+     # Save the initial status so we know if any triggers changed us
+     status = (self._insertFlag, self._deleteFlag, self._updateFlag)
+ 
+     # Call the hooks for commit-level hooks
+     if not self._emptyFlag and 
hasattr(self._parent._dataObject,'_dataSource'):
+ 
+       if self._insertFlag and not self._deleteFlag:
+         self._parent._dataObject._dataSource._beforeCommitInsert(self)
+       elif self._deleteFlag and not self._insertFlag:
+         self._parent._dataObject._dataSource._beforeCommitDelete(self)
+       elif self._updateFlag:
+         self._parent._dataObject._dataSource._beforeCommitUpdate(self)
+ 
+     #
+     # If the record status changed while we were doing the triggers,
+     # start from the beginning and run the triggers again.
+     #
+     if status != (self._insertFlag, self._deleteFlag, self._updateFlag):
+       self.post()
+       return
+ 
+ 
+     if self.isPending():
+       GDebug.printMesg(5,'Posting datasource %s' % 
self._parent._dataObject.name)
+ 
+       if self.isPending():
+         self._postChanges()
+ 
+ 
+     # Post all detail records
+     for child in (self._cachedDetailResultSets.keys()):
+       c = self._cachedDetailResultSets[child]._dataObject
+       # Set the primary key for any new child records
+       fk = {}
+       for i in range(len(c._masterfields)):
+         fk[c._detailfields[i]] = self.getField(c._masterfields[i])
+ 
+       self._cachedDetailResultSets[child].post(foreign_keys=fk)
+ 
+ 
+   # Sets the ResultSet associated with this master record
+   def addDetailResultSet(self, resultSet):
+     self._cachedDetailResultSets[resultSet._dataObject] = resultSet
+ 
+ 
+   ###
+   ### Methods below should be over-written by Vendor Specific functions
+   ###
+ 
+   # Post any changes to database
+   def _postChanges(self):
+     return 1
+ 
Index: gnue-common/src/datasources/drivers/Base/ResultSet.py
diff -c /dev/null gnue-common/src/datasources/drivers/Base/ResultSet.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/drivers/Base/ResultSet.py       Tue Nov 18 
21:07:07 2003
***************
*** 0 ****
--- 1,367 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # ResultSet.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ __all__ = ['ResultSet']
+ 
+ from gnue.common.apps import GDebug
+ from gnue.common.datasources import GConditions, Exceptions
+ import string
+ 
+ from RecordSet import RecordSet
+ 
+ ###########################################################
+ #
+ #
+ #
+ ###########################################################
+ class ResultSet:
+ 
+   _recordSetClass = RecordSet
+ 
+   def __init__(self, dataObject, 
cursor=None,defaultValues={},masterRecordSet=None):
+      self._dataObject = dataObject
+      self._cursor = cursor
+      self._cachedRecords = []
+      self._currentRecord = -1
+      self._masterRecordSet = masterRecordSet
+      self._readonly = 0
+      self._recordCount = 0
+      self._postingRecord = None
+ 
+      self._defaultValues = {}
+      self._defaultValues.update(defaultValues)
+ 
+      self.current = None
+ 
+      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()
+ 
+   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):
+     return self._readonly
+ 
+ 
+   # Returns 1=At first record, 0=Not first record
+   def isFirstRecord(self):
+     return (self._currentRecord == 0)
+ 
+ 
+   # Returns 1=At last record, 0=Not last record
+   def isLastRecord(self):
+     if self._currentRecord < len(self._cachedRecords) - 1 or \
+        self._cacheNextRecord():
+       return 0
+     else:
+       return 1
+ 
+ 
+   # returns -1=No records in memory, #=Current record #
+   def getRecordNumber(self):
+     return self._currentRecord
+ 
+ 
+   # returns # of records currently loaded
+   def getCacheCount(self):
+     return len(self._cachedRecords)
+ 
+   # returns # of records the
+   def getRecordCount(self):
+     return self._recordCount  > 0 and self._recordCount or 
self.getCacheCount()
+ 
+   # Get a specific record (0=based)
+   def getRecord(self, record):
+     while (record + 1 > len(self._cachedRecords)) and self._cacheNextRecord():
+       pass
+ 
+     if record + 1 > len(self._cachedRecords):
+       return None
+     else:
+       return self._cachedRecords[record]
+ 
+ 
+   # move to record #, returns 1=New record loaded, 0=invalid #
+   def setRecord(self, record):
+ 
+     while (record > len(self._cachedRecords) -1) and self._cacheNextRecord():
+       pass
+ 
+     if record >= len(self._cachedRecords):
+       return None
+     else:
+       self._currentRecord = record
+       self.current = self._cachedRecords[self._currentRecord]
+       self.notifyDetailObjects()
+       return self.current
+ 
+   # returns 1=New record loaded, 0=No more records
+   def nextRecord(self):
+     if self._currentRecord + 1 == len(self._cachedRecords):
+       if not self._cacheNextRecord():
+         return None
+ 
+     self._currentRecord += 1
+     self.current = self._cachedRecords[self._currentRecord]
+     self.notifyDetailObjects()
+     return self.current
+ 
+ 
+   # returns 1=New record loaded, 0=At first record
+   def prevRecord(self):
+     if self._currentRecord < 1:
+       return None
+     else:
+       self._currentRecord -= 1
+       self.current = self._cachedRecords[self._currentRecord]
+       self.notifyDetailObjects()
+       return self.current
+ 
+ 
+   # returns 1=at first record, 0=No records loaded
+   def firstRecord(self):
+     if self._currentRecord < 0:
+       if not self._cacheNextRecord():
+         return None
+ 
+     self._currentRecord = 0
+     self.current = self._cachedRecords[0]
+     self.notifyDetailObjects()
+     return self.current
+ 
+ 
+ 
+   # returns 1=at last record, 0=No records loaded
+   def lastRecord(self):
+     if self._currentRecord == -1:
+       return None
+     else:
+       while self._cacheNextRecord():
+         pass
+       self._currentRecord = len(self._cachedRecords) - 1
+       self.current = self._cachedRecords[self._currentRecord]
+       self.notifyDetailObjects()
+       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.printMesg(7,'Inserting a blank record')
+       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():
+         self.current.setField(field, self._dataObject._defaultValues[field],0)
+ 
+       # Set any resultset specific values
+       for field in self._defaultValues.keys():
+         self.current.setField(field, self._defaultValues[field],0)
+ 
+       # 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:
+           
self.current.setField(self._dataObject._detailfields[i],self._masterRecordSet.getField(field),0)
+           i += 1
+ 
+       self.notifyDetailObjects()
+       return self.current
+ 
+ 
+   # Returns 1=DataObject, or a detail resultset, has uncommitted changes
+   def isPending(self):
+     for rec in (self._cachedRecords):
+       if rec.isPending():
+         return 1
+       else:
+         for detail in rec._cachedDetailResultSets.values():
+           if detail.isPending():
+             return 1
+     return 0
+ 
+ 
+   # Returns 1=DataObject has uncommitted changes
+   def isRecordPending(self):
+     return self.current.isPending()
+ 
+ 
+   def getPostingRecordset(self):
+     global postingRecordset
+     return postingRecordset
+ 
+   # Post changes to the database
+   def post(self, foreign_keys={}):
+     global postingRecordset
+     # post our changes
+     self._update_cursor = self._dataObject._dataConnection.cursor()
+ 
+     recordPosition = 0
+     while recordPosition < len(self._cachedRecords):
+       self._postingRecord = self._cachedRecords[recordPosition]
+       postingRecordset = self._postingRecord
+       delete = self._postingRecord._emptyFlag or 
self._postingRecord._deleteFlag
+       if not delete:
+         # Flip the flag for 'default' values to true so that hidden
+         # default fields are included in insert statements
+         if self._postingRecord.isPending():
+           for field in self._dataObject._defaultValues.keys():
+             self._postingRecord._modifiedFlags[field] = 1
+ 
+         for field in foreign_keys.keys():
+           self._postingRecord._fields[field] = foreign_keys[field]
+           # Some DBs will throw an exception if you update a Primary Key
+           # (even if you are updating to the same value)
+           if self._postingRecord._insertFlag:
+             self._postingRecord._modifiedFlags[field] = 1
+ 
+         recordPosition += 1
+       else:
+         # Adjust the current record if a preceding record
+         # or the current record is deleted
+         if recordPosition <= self._currentRecord:
+           self._currentRecord -= 1
+         self._cachedRecords.pop(recordPosition)
+         self._recordCount -= 1
+ 
+       self._postingRecord.post()
+ 
+     # Move to record 0 if all preceding records were deleted
+     # (or set to -1 if all records were deleted)
+     if self._currentRecord < 0:
+       if len(self._cachedRecords):
+         self._currentRecord = 0
+       else:
+         self._currentRecord = -1
+ # TODO: I don't think we need this anymore
+ #    if self._currentRecord >= self._recordCount:
+ #      self._currentRecord = self._recordCount - 1
+ 
+   def notifyDetailObjects(self):
+     GDebug.printMesg(5,'Master record changed; Notifying Detail Objects')
+     for detail in self._dataObject._detailObjects:
+       if detail[1]:
+         detail[1].masterResultSetChanged(self,
+                                          detail[0]._masterRecordChanged(self))
+ 
+ 
+   # Returns 1=Field is bound to a database field
+   def isFieldBound(self, fieldName):
+     if self._dataObject._fieldReferences.has_key(fieldName):
+       return 1
+     else:
+       #TODO: the string.lower() line should never be called but is left
+       #TODO: here untill the code is cleaned up
+       return 
self._dataObject._fieldReferences.has_key(string.lower(fieldName))
+ 
+ 
+   # Load cacheCount number of new records
+   def _cacheNextRecord(self):
+     rs = self._loadNextRecord()
+     if rs:
+       self._dataObject._dataSource._onRecordLoaded(self._cachedRecords[-1])
+     return rs
+ 
+ 
+ 
+   ###
+   ### 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 0
+ 
+   # Create an empty recordset
+   def _createEmptyRecord(self):
+     return self._recordSetClass(self)
+ 
+   # Iterator support (Python 2.2+)
+   def __iter__(self):
+     return _ResultSetIter(self)
+ 
+ 
+ 
+ # 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 = 0
+     self.done = 0
+ 
+   def __iter__(self):
+     return self
+ 
+   def next(self):
+     if self.done:
+       raise StopIteration
+     if self.used:
+       rs = self.resultset.firstRecord()
+     else:
+       rs = self.resultset.nextRecord()
+ 
+     if not rs:
+       raise StopIteration
+     else:
+       return rs
+ 
+ 
+ # TODO: wtf?
+ postingRecordset = None
+ 
Index: gnue-common/src/datasources/drivers/Base/__init__.py
diff -c /dev/null gnue-common/src/datasources/drivers/Base/__init__.py:1.1.2.1
*** /dev/null   Tue Nov 18 21:07:09 2003
--- gnue-common/src/datasources/drivers/Base/__init__.py        Tue Nov 18 
21:07:07 2003
***************
*** 0 ****
--- 1,32 ----
+ #
+ # This file is part of GNU Enterprise.
+ #
+ # GNU Enterprise is free software; you can redistribute it
+ # and/or modify it under the terms of the GNU General Public
+ # License as published by the Free Software Foundation; either
+ # version 2, or (at your option) any later version.
+ #
+ # GNU Enterprise is distributed in the hope that it will be
+ # useful, but WITHOUT ANY WARRANTY; without even the implied
+ # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ # PURPOSE. See the GNU General Public License for more details.
+ #
+ # You should have received a copy of the GNU General Public
+ # License along with program; see the file COPYING. If not,
+ # write to the Free Software Foundation, Inc., 59 Temple Place
+ # - Suite 330, Boston, MA 02111-1307, USA.
+ #
+ # Copyright 2000-2003 Free Software Foundation
+ #
+ # FILE:
+ # Base/__init__.py
+ #
+ # DESCRIPTION:
+ #
+ # NOTES:
+ #
+ 
+ from Connection import Connection
+ from DataObject import DataObject
+ from ResultSet import ResultSet
+ from RecordSet import RecordSet
\ No newline at end of file
Index: gnue-common/src/datasources/drivers/DBSIG2/Connection.py
diff -c gnue-common/src/datasources/drivers/DBSIG2/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/DBSIG2/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/DBSIG2/Connection.py:1.1.2.1    Thu Oct 
 9 21:21:09 2003
--- gnue-common/src/datasources/drivers/DBSIG2/Connection.py    Tue Nov 18 
21:07:07 2003
***************
*** 33,44 ****
  
  __all__ = ['Connection']
  
! from gnue.common.datasources import GConnection
  from gnue.common.apps import GDebug
  import string
  import types
  
! class Connection(GConnection.Connection):
  
    # This should be over-ridden only if driver needs more than user/pass
    def getLoginFields(self):
--- 33,45 ----
  
  __all__ = ['Connection']
  
! from gnue.common.datasources import Exceptions
! from gnue.common.datasources.drivers.Base.Connection import Connection as 
BaseConnection
  from gnue.common.apps import GDebug
  import string
  import types
  
! class Connection(BaseConnection):
  
    # This should be over-ridden only if driver needs more than user/pass
    def getLoginFields(self):
***************
*** 50,56 ****
      try:
        self.native.commit()
      except self._DatabaseError, value:
!       raise GDataObjects.ConnectionError, value
  
      self._beginTransaction()
  
--- 51,57 ----
      try:
        self.native.commit()
      except self._DatabaseError, value:
!       raise Exceptions.ConnectionError, value
  
      self._beginTransaction()
  
Index: gnue-common/src/datasources/drivers/DBSIG2/DataObject.py
diff -c gnue-common/src/datasources/drivers/DBSIG2/DataObject.py:1.1.2.3 
gnue-common/src/datasources/drivers/DBSIG2/DataObject.py:1.1.2.4
*** gnue-common/src/datasources/drivers/DBSIG2/DataObject.py:1.1.2.3    Sun Oct 
12 15:47:15 2003
--- gnue-common/src/datasources/drivers/DBSIG2/DataObject.py    Tue Nov 18 
21:07:07 2003
***************
*** 33,39 ****
  
  __all__ = ['DataObject','DataObject_SQL','DataObject_Object']
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  import string
  import types
--- 33,40 ----
  
  __all__ = ['DataObject','DataObject_SQL','DataObject_Object']
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import DataObject as BaseDataObject
  from gnue.common.apps import GDebug
  import string
  import types
***************
*** 44,50 ****
  #
  #
  #
! class DataObject(GDataObjects.DataObject):
  
    _escapeSingleQuote = "'"
    _resultSetClass = ResultSet
--- 45,51 ----
  #
  #
  #
! class DataObject(BaseDataObject):
  
    _escapeSingleQuote = "'"
    _resultSetClass = ResultSet
***************
*** 94,100 ****
  
  
    def __init__(self, *args, **params):
!     GDataObjects.DataObject.__init__(self, *args, **params)
  
      GDebug.printMesg (1,"DB-SIG database driver backend initializing")
  
--- 95,101 ----
  
  
    def __init__(self, *args, **params):
!     BaseDataObject.__init__(self, *args, **params)
  
      GDebug.printMesg (1,"DB-SIG database driver backend initializing")
  
***************
*** 114,120 ****
      try:
        return value.strftime(self._dateTimeFormat)
      except AttributeError:
!       
        if value == None:
          return "NULL"
  
--- 115,121 ----
      try:
        return value.strftime(self._dateTimeFormat)
      except AttributeError:
! 
        if value == None:
          return "NULL"
  
***************
*** 159,165 ****
          return "'%s'" % string.replace(str(value),
                                         "'",
                                         "%s'" % self._escapeSingleQuote)
!         
  
    # Used by drivers with a unique id (like rowid) (see Oracle for example)
    def _checkForPrimaryId(self):
--- 160,166 ----
          return "'%s'" % string.replace(str(value),
                                         "'",
                                         "%s'" % self._escapeSingleQuote)
! 
  
    # Used by drivers with a unique id (like rowid) (see Oracle for example)
    def _checkForPrimaryId(self):
***************
*** 182,190 ****
          recordCount = cursor.rowcount
          #disable the count query and see if anyone screams
          #recordCount = self._getQueryCount(conditions,sql)
!         
      except self._DatabaseError, err:
!       raise GDataObjects.ConnectionError, err
  
      rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
      if self._strictQueryCount:
--- 183,191 ----
          recordCount = cursor.rowcount
          #disable the count query and see if anyone screams
          #recordCount = self._getQueryCount(conditions,sql)
! 
      except self._DatabaseError, err:
!       raise Exceptions.ConnectionError, err
  
      rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
      if self._strictQueryCount:
***************
*** 258,268 ****
          if len(result) < self.conditionElements[otype][0]:
            tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
                (otype, self.conditionElements[otype][0], len(result))
!           raise GConditions.ConditionError, tmsg
          if len(result) > self.conditionElements[otype][1]:
            tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
                  (otype, self.conditionElements[otype][0], len(result))
!           raise GConditions.ConditionError, tmsg
  
          if self.conditionElements[otype][3] == None:
            return self.conditionElements[otype][2] % tuple(result)
--- 259,269 ----
          if len(result) < self.conditionElements[otype][0]:
            tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
                (otype, self.conditionElements[otype][0], len(result))
!           raise Exceptions.ConditionError, tmsg
          if len(result) > self.conditionElements[otype][1]:
            tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
                  (otype, self.conditionElements[otype][0], len(result))
!           raise Exceptions.ConditionError, tmsg
  
          if self.conditionElements[otype][3] == None:
            return self.conditionElements[otype][2] % tuple(result)
***************
*** 271,277 ****
              (string.join(result, self.conditionElements[otype][3]))
        else:
          tmsg = _('Condition clause "%s" is not supported by this db driver.') 
% otype
!         raise GConditions.ConditionNotSupported, tmsg
  
  
  
--- 272,278 ----
              (string.join(result, self.conditionElements[otype][3]))
        else:
          tmsg = _('Condition clause "%s" is not supported by this db driver.') 
% otype
!         raise Exceptions.ConditionNotSupported, tmsg
  
  
  
Index: gnue-common/src/datasources/drivers/DBSIG2/Driver.py
diff -c gnue-common/src/datasources/drivers/DBSIG2/Driver.py:1.76.2.1 
gnue-common/src/datasources/drivers/DBSIG2/Driver.py:removed
*** gnue-common/src/datasources/drivers/DBSIG2/Driver.py:1.76.2.1       Thu Oct 
 9 21:21:09 2003
--- gnue-common/src/datasources/drivers/DBSIG2/Driver.py        Tue Nov 18 
21:07:09 2003
***************
*** 1,600 ****
- #
- # This file is part of GNU Enterprise.
- #
- # GNU Enterprise is free software; you can redistribute it
- # and/or modify it under the terms of the GNU General Public
- # License as published by the Free Software Foundation; either
- # version 2, or (at your option) any later version.
- #
- # GNU Enterprise is distributed in the hope that it will be
- # useful, but WITHOUT ANY WARRANTY; without even the implied
- # warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- # PURPOSE. See the GNU General Public License for more details.
- #
- # You should have received a copy of the GNU General Public
- # License along with program; see the file COPYING. If not,
- # write to the Free Software Foundation, Inc., 59 Temple Place
- # - Suite 330, Boston, MA 02111-1307, USA.
- #
- # Copyright 2000-2003 Free Software Foundation
- #
- # FILE:
- # _dbsig/DBdriver.py
- #
- # DESCRIPTION:
- # Generic implementation of dbdriver using Python DB-SIG v2
- # specification.
- #
- # NOTES:
- # The classes below are meant to be extended
- #
- # HISTORY:
- #
- 
- from gnue.common.datasources import GDataObjects, GConditions
- from gnue.common.apps import GDebug
- import string
- import types
- 
- class DBSIG_RecordSet(GDataObjects.RecordSet):
- 
-   def _postChanges(self):
-     if not self.isPending(): return
-     if self._deleteFlag:
-       statement = self._buildDeleteStatement()
-     elif self._insertFlag:
-       statement = self._buildInsertStatement()
-     elif self._updateFlag:
-       statement = self._buildUpdateStatement()
- 
-     GDebug.printMesg(5, "_postChanges: statement=%s" % statement)
- 
-     try:
-       self._parent._update_cursor.execute(statement)
- 
-       # Set _initialData to be the just-now posted values
-       if not self._deleteFlag:
-         self._initialData = {}
-         self._initialData.update(self._fields)
- 
-     except self._parent._dataObject._DatabaseError, err:
-       raise GDataObjects.ConnectionError, err
- 
-     self._updateFlag = 0
-     self._insertFlag = 0
-     self._deleteFlag = 0
- 
-     return 1
- 
- 
-   # If a vendor can do any of these more efficiently (i.e., use a known
-   # PRIMARY KEY or ROWID, then override these methods. Otherwise, leave
-   # as default.  Note that these functions are specific to DB-SIG based
-   # drivers (i.e., these functions are not in the base RecordSet class)
- 
-   def _buildDeleteStatement(self):
-     if self._initialData.has_key(self._parent._dataObject._primaryIdField):
-       where = [self._parent._dataObject._primaryIdFormat % \
-           self._initialData[self._parent._dataObject._primaryIdField]  ]
-     else:
-       where = []
-       for field in self._initialData.keys():
-         if self._parent.isFieldBound(field):
-           if self._initialData[field] == None:
-             where.append ("%s IS NULL" % field)
-           else:
-             where.append ("%s=%s" % (field,
-               
self._parent._dataObject._toSqlString(self._initialData[field])))
- 
-     statement = "DELETE FROM %s WHERE %s" % \
-        (self._parent._dataObject.table, string.join(where,' AND ') )
-     return statement
- 
-   def _buildInsertStatement(self):
-     vals = []
-     fields = []
- 
-     for field in self._modifiedFlags.keys():
-       if self._parent.isFieldBound(field):
-         fields.append (field)
-         if self._fields[field] == None or self._fields[field] == '':
-           vals.append ("NULL") #  % (self._fields[field]))
-         else:
-           vals.append 
(self._parent._dataObject._toSqlString(self._fields[field]))
- 
-     return "INSERT INTO %s (%s) VALUES (%s)" % \
-        (self._parent._dataObject.table, string.join(fields,','), \
-         string.join(vals,',') )
- 
-   def _buildUpdateStatement(self):
-     updates = []
-     for field in self._modifiedFlags.keys():
-       updates.append ("%s=%s" % (field,
-          self._parent._dataObject._toSqlString(self._fields[field])))
- 
-     if self._parent._dataObject._primaryIdField:
-       where = [self._parent._dataObject._primaryIdFormat % \
-           self._initialData[self._parent._dataObject._primaryIdField]  ]
-     else:
-       where = []
-       for field in self._initialData.keys():
-         if self._initialData[field] == None:
-           where.append ("%s IS NULL" % field)
-         else:
-           where.append ("%s=%s" % (field, 
self._parent._dataObject._toSqlString(self._initialData[field])))
- 
-     return "UPDATE %s SET %s WHERE %s" % \
-        (self._parent._dataObject.table, string.join(updates,','), \
-         string.join(where,' AND ') )
- 
- 
- class DBSIG_ResultSet(GDataObjects.ResultSet):
-   def __init__(self, dataObject, cursor=None, \
-         defaultValues={}, masterRecordSet=None):
-     GDataObjects.ResultSet.__init__(
-            self,dataObject,cursor,defaultValues,masterRecordSet)
-     self._recordSetClass = DBSIG_RecordSet
-     self._fieldNames = []
- 
-     if self._cursor:
-       for t in(self._cursor.description):
-         self._fieldNames.append(t[0])
-       GDebug.printMesg(5, "Field names set to %s" % self._fieldNames)
- 
-     self._recordCount = cursor.rowcount or 0
- 
-     GDebug.printMesg(5, 'ResultSet created')
- 
-   def _loadNextRecord(self):
-     if self._cursor:
-       rs = None
- 
-       try:
-         rsets = self._cursor.fetchmany()
-       except self._dataObject._DatabaseError, err:
-         raise GDataObjects.ConnectionError, err
-       if rsets and len(rsets):
-         for rs in(rsets):
-           if rs:
-             i = 0
-             dict = {}
-             for f in (rs):
-               dict[string.lower(self._fieldNames[i])] = f
-               i += 1
-             self._cachedRecords.append (self._recordSetClass(parent=self, \
-                                                              
initialData=dict))
-           else:
-             return 0
-         return 1
-       else:
-         # We no longer need the cursor if we are read only
-         if self._readonly:
-           self._cursor.close()
-         return 0
-     else:
-       return 0
- 
- 
- class DBSIG_DataObject(GDataObjects.DataObject):
- 
-   conditionElements = {
-        'add':             (2, 999, '(%s)',                   '+'       ),
-        'sub':             (2, 999, '(%s)',                   '-'       ),
-        'mul':             (2, 999, '(%s)',                   '*'       ),
-        'div':             (2, 999, '(%s)',                   '/'       ),
-        'and':             (1, 999, '(%s)',                   ' AND '   ),
-        'or':              (2, 999, '(%s)',                   ' OR '    ),
-        'not':             (1,   1, '(NOT %s)',               None      ),
-        'negate':          (1,   1, '-%s',                    None      ),
-        'null':            (1,   1, '(%s IS NULL)',           None      ),
-        'notnull':         (1,   1, '(%s IS NOT NULL)',       None      ),
-        'eq':              (2,   2, '(%s = %s)',              None      ),
-        'ne':              (2,   2, '(%s != %s)',             None      ),
-        'gt':              (2,   2, '(%s > %s)',              None      ),
-        'ge':              (2,   2, '(%s >= %s)',             None      ),
-        'lt':              (2,   2, '(%s < %s)',              None      ),
-        'le':              (2,   2, '(%s <= %s)',             None      ),
-        'like':            (2,   2, '%s LIKE %s',             None      ),
-        'notlike':         (2,   2, '%s NOT LIKE %s',         None      ),
-        'between':         (3,   3, '%s BETWEEN %s AND %s',   None      ),
-        'notbetween':      (3,   3, '(%s NOT BETWEEN %s AND %s)', None  ),
-        # These two are hacks... these are not really valid tags
-        # Used when the 2nd value of EQ or NE is NULL.
-        '__iseq':          (2,   2, '(%s IS %s)',             None      ),
-        '__isne':          (2,   2, '(%s IS NOT %s)',         None      )}
- 
-   schema2nativeTypes={}
- 
-   def __init__(self, strictQueryCount=1):
-     GDataObjects.DataObject.__init__(self)
- 
-     GDebug.printMesg (1,"DB-SIG database driver backend initializing")
- 
-     # This should be set to the Single Quote escape character
-     # (typically either "'" or "\"
-     self._escapeSingleQuote = "'"
-     self._resultSetClass = DBSIG_ResultSet
-     self._DatabaseError = None
-     self._strictQueryCount = strictQueryCount
- 
-     self.distinct = 0
- 
-     # If a DB driver supports a unique identifier for rows,
-     # list it here.  _primaryIdField is the field name (lower case)
-     # that would appear in the recordset (note that this can be
-     # a system generated format). If a primary id is supported,
-     # _primaryIdFormat is the WHERE clause to be used. It will have
-     # the string  % (fieldvalue) format applied to it.
-     #
-     # See Oracle drivers for example
-     self._primaryIdField = None         # Internal recordset field name 
(lowercase!!!)
-     self._primaryIdSelect = ""  # Select clause
-     self._primaryIdFormat = "__gnue__ = '%s'"         # Where clause format
- 
-     # Internal flag to avoid consistently doing the same check
-     # If this is set to 1 initially, then the
-     self._primaryIdChecked = 1  # Internal flag
- 
- 
-     # The date/time format used in insert/select statements
-     # (based on format used for time.strftime())
-     self._dateTimeFormat = "'%c'"
- 
- 
-   def _toSqlString(self, value):
-     try:
-       return value.strftime(self._dateTimeFormat)
-     except AttributeError:
-       if value == None:
-         return "NULL"
-       elif type(value) == types.FloatType:
-         if value==int(value):
-           return "%d" % value
-         else:
-           return str(value)
- 
-       elif type(value) == types.UnicodeType:
-       return "'%s'" % 
string.replace(value.encode(gConfig("textEncoding")),"'",
-                   "%s'" % self._escapeSingleQuote)
-       else:
-       
-       try:
-           return "'%s'" % string.replace(str(value),"'",
-                     "%s'" % self._escapeSingleQuote)
-         except:
-           return "'%s'" % string.replace(value,"'",
-                     "%s'" % self._escapeSingleQuote)
- 
- 
- 
-   # This should be over-ridden only if driver needs more than user/pass
-   def getLoginFields(self):
-     return [['_username', _('User Name'),0],['_password', _('Password'),1]]
- 
- 
-   # Used by drivers with a unique id (like rowid) (see Oracle for example)
-   def _checkForPrimaryId(self):
-     self._primaryIdChecked = 1
- 
- 
-   def _createResultSet(self, conditions={}, readOnly=0, 
masterRecordSet=None,sql=""):
- 
-     # Used by drivers with a unique id (like rowid)
-     if not self._primaryIdChecked: self._checkForPrimaryId()
- 
-     try:
-       cursor = self._dataConnection.cursor()
- 
-       cursor.arraysize = self.cache
-       cursor.execute(self._buildQuery(conditions, additionalSQL=sql))
- 
-       # pull a record count 
-       if self._strictQueryCount:
-         recordCount = cursor.rowcount
-         #disable the count query and see if anyone screams
-         #recordCount = self._getQueryCount(conditions,sql)
-         
-     except self._DatabaseError, err:
-       raise GDataObjects.ConnectionError, err
- 
-     rs = self._resultSetClass(self, cursor=cursor, 
masterRecordSet=masterRecordSet)
-     if self._strictQueryCount:
-       rs._recordCount = recordCount
-     if readOnly:
-       rs._readonly = readOnly
- 
-     return rs
- 
-   def _getQueryCount(self,conditions={},sql=""):
-     cursor = self._dataConnection.cursor()
- 
-     cursor.execute(self._buildQueryCount(conditions,additionalSQL=sql))
-     rs = cursor.fetchone()
-     return int(rs[0])
- 
-   def commit(self):
-     GDebug.printMesg (5,"DB-SIG database driver: commit()")
- 
-     try:
-       self._dataConnection.commit()
-     except self._DatabaseError, value:
-       raise GDataObjects.ConnectionError, value
- 
-     self._beginTransaction()
- 
-   def rollback(self):
-     GDebug.printMesg (5,"DB-SIG database driver: rollback()")
- 
-     try:
-       self._dataConnection.rollback()
-     except:
-       pass    # I'm SURE this isn't right (jcater)
-                 # But not all db's support transactions
- 
-     self._beginTransaction()
- 
- 
-   # Used to convert a condition tree to an sql where clause
-   def _conditionToSQL (self, condition):
-     if condition == {} or condition == None:
-       return ""
-     elif type(condition) == types.DictType:
-       cond = GConditions.buildConditionFromDict(condition)
-     else:
-       cond = condition
- 
-     if not len(cond._children): 
-       return ""
-     elif len(cond._children) > 1:
-       chillun = cond._children[:]
-       cond._children = []
-       _and = GConditions.GCand(cond)
-       _and._children = chillun
- 
-     where = " WHERE (%s)" % (self.__conditionToSQL (cond._children[0]))
-     GDebug.printMesg(5, where)
-     return where
- 
-   #
-   # Used internally by _conditionToSQL
-   #
-   # This code recursively travels down a condition tree replacing the objects
-   # with a strings representation
-   def __conditionToSQL (self, element):
-     if type(element) != types.InstanceType:
-       return "%s" % element
-     else:
-       # Note that we strip the GC from the object types and lowercase the rest
-       otype = string.lower(element._type[2:])
-       #print "Otype: ",otype
-       if otype == 'cfield':
-         return "%s" % element.name
-       elif otype == 'cconst':
-         if element.value == None:
-           return "NULL"
-         elif element.type == 'number':
-           return "%s" % element.value
-         else:
-           return self._toSqlString(element.value)
-       elif otype == 'cparam':
-         v = element.getValue()
-         return (v == None and "NULL") or ("'%s'" % v)
-       elif self.conditionElements.has_key(otype):
-         result=[]
-         for i in range(0, len(element._children)):
-           result.append(self.__conditionToSQL(element._children[i]))
-         if len(result) == 2 and \
-            otype in ('eq','ne') and \
-            result[1] == 'NULL':
-            otype = "__is%s" % otype
-         if len(result) < self.conditionElements[otype][0]:
-           tmsg = _('Condition element "%s" expects at least %s arguments; 
found %s') % \
-               (otype, self.conditionElements[otype][0], len(result))
-           raise GConditions.ConditionError, tmsg
-         if len(result) > self.conditionElements[otype][1]:
-           tmsg = _('Condition element "%s" expects at most %s arguments; 
found %s') % \
-                 (otype, self.conditionElements[otype][0], len(result))
-           raise GConditions.ConditionError, tmsg
- 
-         if self.conditionElements[otype][3] == None:
-           return self.conditionElements[otype][2] % tuple(result)
-         else:
-           return self.conditionElements[otype][2] % \
-             (string.join(result, self.conditionElements[otype][3]))
-       else:
-         tmsg = _('Condition clause "%s" is not supported by this db driver.') 
% otype
-         raise GConditions.ConditionNotSupported, tmsg
- 
-   # Code necessary to force the connection into transaction mode...
-   # this is usually not necessary (MySQL is one of few DBs that must force)
-   def _beginTransaction(self):
-     pass
- 
- 
-   def _buildFieldDefinition(self,field):
-     try:
-       sql="%s %s" % (field.name,
-                      self.schema2nativeTypes[field.type])
-     except:
-       tmsg = _("Datatype '%s' is not supported by database")
-       raise GDataObjects.DataTypeNotAvailable, tmsg
-     
-     if hasattr(field,"size"):
-       sql=sql+"(%s)" % field.size
-          
-     #   if hasattr(field,"precision"):
-     #   if hasattr(field,"scale"):
- 
-     if not field.nullable:
-       sql=sql+" NOT NULL"
-       
-     if hasattr(field,"default"):
-       sql=sql+" DEFAULT %s" % self._toSqlString(field.default)
- 
-     return sql
- 
-   def _buildTableDefinition(self,tbl):
-       
-     sql="CREATE TABLE %s (" % tbl.name
- 
- 
-     # add fields to table
- 
-     fields=tbl.findChildOfType("GSFields")
- 
-     delim=""
- 
-     for field in fields._children:
-       
-        sql=sql+delim+"%s" % self._buildFieldDefinition(field)
-        delim=","
- 
-     # define primary key
- 
-     pk=tbl.findChildOfType("GSPrimaryKey")
- 
-     if (pk!=None) and len(pk._children):
-       
-       sql=sql+", primary key %s (" % pk.name
-       
-       delim=""
-     
-       for pkfield in pk._children:
-         
-         sql=sql+delim+pkfield.name
-         
-         delim=","
- 
-       sql=sql+") "
-       
- 
-     # close definition
- 
-     sql=sql+");"
- 
-     GDebug.printMesg(1,"SQL Statement: %s" % sql)
- 
-     return sql
-   
-   def writeTable(self,tbl,overwrite):
-     
-     sql = self._buildTableDefinition(tbl)
-     
-     try:
-       cursor = self._dataConnection.cursor()
-       cursor.execute(sql)
-       cursor.close()
-     except:
-       # test it is an error because of an existing table
-       # directly raise an error, if it is an access rights problem
-       if not overwrite:
-         return "Could not write table %s to database." % tbl.name
-       else:
-         cursor = self._dataConnection.cursor()
-         # drop table
-         cursor.execute("drop table %s" % tbl.name)
-         # create table
-         cursor.execute(sql)
-         cursor.close()
- 
- 
-   # write Schema to Database
-   def writeSchema(self,obj,overwrite=0):
-     if obj._type=="GSTable":
-       return self.writeTable(obj,overwrite)
- 
-     elif obj._type=="GSView":
-       return self.writeView(obj,overwrite)
- 
-     else:
-       # do the same for all children
-       result=[]
-       for child in obj._children:
-         result.append(self.writeSchema(child))
- 
-       if len(result)==0:
-         return None
-       elif len(result)==1:
-         return result[0]
-       else:
-         return result
- 
- 
- 
- class DBSIG_DataObject_Object:
-   def __init__(self):
-    # TODO: A dummy placeholder to let old db driver work
-    # TODO: each can have their *_DataObject_Object object from __init__ing
-    # TODO: DBSIG_DataObject_Object
-    GDebug.printMesg(0,
-      "Database driver needs updated to not initialize 
DBSIG_DataObject_Object")
- 
-   def _buildQuery(self, conditions={}, forDetail=None, additionalSQL=""):
-     GDebug.printMesg(7,'Implicit Fields: %s' % self._fieldReferences)
-     if self.distinct:
-       distinct = "distinct "
-     else:
-       distinct = ""
- 
-     if self._primaryIdSelect:
-       pis = "%s," % self._primaryIdSelect
-     else:
-       pis = ""
- 
-     whereClause = self._conditionToSQL(conditions)
-     if additionalSQL:
-       if len(whereClause):
-         whereClause += ' and %s' % (additionalSQL)
-       else:
-         whereClause = ' WHERE %s' % (additionalSQL)
-       
-     if forDetail:
-       q = "%s in (SELECT %s FROM %s%s)" % \
-                      (string.join(self._masterfields,","),
-                       string.join(self._detailfields,","),
-                       self.table, whereClause)
-     elif len(self._fieldReferences):
-       q = "SELECT %s%s%s FROM %s%s" % \
-            (distinct, pis, string.join(self._fieldReferences.keys(),","), 
self.table,
-             whereClause)
-     else:
-       self._primaryIdSelect = None
-       q = "SELECT %s* FROM %s%s" % (distinct, self.table,
-                         whereClause)
- 
-     if hasattr(self,'order_by') and not forDetail:
-      q = "%s ORDER BY %s " % (q, self.order_by)
- 
-     GDebug.printMesg(5,q)
- 
-     return q
- 
-   def _buildQueryCount(self, conditions={}, additionalSQL=""):
-     whereClause = self._conditionToSQL(conditions)
-     if additionalSQL:
-       if len(whereClause):
-         whereClause += ' and %s' % (additionalSQL)
-       else:
-         whereClause = ' WHERE %s' % (additionalSQL)
- 
- 
-     q = "SELECT count(*) FROM %s%s" % (self.table, whereClause)
- 
-     GDebug.printMesg(5,q)
- 
-     return q
- 
- class DBSIG_DataObject_SQL:
-   def _buildQuery(self, conditions={}):
-     # Obviously, this is in a pre-alpha state :)
-     return "select zipcode, city, state from zipcode order by zipcode desc"
- 
- supportedDataObjects = {
-   'object': DBSIG_DataObject_Object,
-   'sql':    DBSIG_DataObject_SQL
- }
- 
- 
- 
- 
- 
--- 0 ----
Index: gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py
diff -c gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py:1.1.2.1 
gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py:1.1.2.2
*** gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py:1.1.2.1     Thu Oct 
 9 21:21:10 2003
--- gnue-common/src/datasources/drivers/DBSIG2/RecordSet.py     Tue Nov 18 
21:07:07 2003
***************
*** 31,37 ****
  
  __all__ = ['RecordSet']
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  import string
  import types
--- 31,38 ----
  
  __all__ = ['RecordSet']
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import RecordSet as BaseRecordSet
  from gnue.common.apps import GDebug
  import string
  import types
***************
*** 41,47 ****
  #
  #
  #
! class RecordSet(GDataObjects.RecordSet):
  
    def _postChanges(self):
      if not self.isPending(): return
--- 42,48 ----
  #
  #
  #
! class RecordSet(BaseRecordSet):
  
    def _postChanges(self):
      if not self.isPending(): return
***************
*** 63,69 ****
          self._initialData.update(self._fields)
  
      except self._parent._dataObject._DatabaseError, err:
!       raise GDataObjects.ConnectionError, err
  
      self._updateFlag = 0
      self._insertFlag = 0
--- 64,70 ----
          self._initialData.update(self._fields)
  
      except self._parent._dataObject._DatabaseError, err:
!       raise Exceptions.ConnectionError, err
  
      self._updateFlag = 0
      self._insertFlag = 0
Index: gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py
diff -c gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py:1.1.2.2 
gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py:1.1.2.3
*** gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py:1.1.2.2     Fri Oct 
10 08:18:49 2003
--- gnue-common/src/datasources/drivers/DBSIG2/ResultSet.py     Tue Nov 18 
21:07:07 2003
***************
*** 33,51 ****
  
  __all__ = ['ResultSet']
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  import string
  import types
  
  from RecordSet import RecordSet
  
! class ResultSet(GDataObjects.ResultSet):
!   def __init__(self, dataObject, cursor=None, \
!         defaultValues={}, masterRecordSet=None):
!     GDataObjects.ResultSet.__init__(
!            self,dataObject,cursor,defaultValues,masterRecordSet)
!     self._recordSetClass = RecordSet
      self._fieldNames = []
  
      if self._cursor:
--- 33,50 ----
  
  __all__ = ['ResultSet']
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import ResultSet as BaseResultSet
  from gnue.common.apps import GDebug
  import string
  import types
  
  from RecordSet import RecordSet
  
! class ResultSet(BaseResultSet):
!   _recordSetClass = RecordSet
!   def __init__(self, *args, **parms):
!     BaseResultSet.__init__(self, *args, **parms)
      self._fieldNames = []
  
      if self._cursor:
***************
*** 53,59 ****
          self._fieldNames.append(t[0])
        GDebug.printMesg(5, "Field names set to %s" % self._fieldNames)
  
!     self._recordCount = cursor.rowcount or 0
  
      GDebug.printMesg(5, 'ResultSet created')
  
--- 52,58 ----
          self._fieldNames.append(t[0])
        GDebug.printMesg(5, "Field names set to %s" % self._fieldNames)
  
!     self._recordCount = self._cursor.rowcount or 0
  
      GDebug.printMesg(5, 'ResultSet created')
  
***************
*** 64,70 ****
        try:
          rsets = self._cursor.fetchmany()
        except self._dataObject._DatabaseError, err:
!         raise GDataObjects.ConnectionError, err
        if rsets and len(rsets):
          for rs in(rsets):
            if rs:
--- 63,69 ----
        try:
          rsets = self._cursor.fetchmany()
        except self._dataObject._DatabaseError, err:
!         raise Exceptions.ConnectionError, err
        if rsets and len(rsets):
          for rs in(rsets):
            if rs:
Index: gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py
diff -c 
gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py:1.1.2.1 
Thu Oct  9 21:21:11 2003
--- gnue-common/src/datasources/drivers/adodbapi/adodbapi/Connection.py Tue Nov 
18 21:07:08 2003
***************
*** 50,58 ****
  
  
  class Connection(DBSIG2.Connection):
!   _defaultBehavior = Introspection
    _DatabaseError = SIG2api.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 50,58 ----
  
  
  class Connection(DBSIG2.Connection):
!   defaultBehavior = Introspection
    _DatabaseError = SIG2api.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/appserver/appserver/Connection.py
diff -c 
gnue-common/src/datasources/drivers/appserver/appserver/Connection.py:1.1.2.3 
gnue-common/src/datasources/drivers/appserver/appserver/Connection.py:1.1.2.4
*** 
gnue-common/src/datasources/drivers/appserver/appserver/Connection.py:1.1.2.3   
    Fri Nov  7 11:14:22 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/Connection.py       
Tue Nov 18 21:07:08 2003
***************
*** 33,39 ****
  
  __all__ = ['Connection']
  
! from gnue.common.datasources import GDataObjects, GConditions, GConnection
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
--- 33,40 ----
  
  __all__ = ['Connection']
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import Connection as BaseConnection
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
***************
*** 48,58 ****
  from DataObject import DataObject
  from gnue.common.datasources.drivers.appserver.Schema.Discovery.Introspection 
import Introspection
  
! class Connection(GConnection.Connection):
  
    _DatabaseError = GComm.Error
!   _defaultBehavior = Introspection
!   _supportedDataObjects = {
      'object': DataObject
    }
  
--- 49,59 ----
  from DataObject import DataObject
  from gnue.common.datasources.drivers.appserver.Schema.Discovery.Introspection 
import Introspection
  
! class Connection(BaseConnection):
  
    _DatabaseError = GComm.Error
!   defaultBehavior = Introspection
!   supportedDataObjects = {
      'object': DataObject
    }
  
***************
*** 60,67 ****
    def getLoginFields(self):
      return [['_username', 'User Name',0],['_password', 'Password',1]]
  
-   def connect(self):
  
      user = connectData['_username']
      passwd = connectData['_password']
  
--- 61,68 ----
    def getLoginFields(self):
      return [['_username', 'User Name',0],['_password', 'Password',1]]
  
  
+   def connect(self, connectData):
      user = connectData['_username']
      passwd = connectData['_password']
  
Index: gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py
diff -c 
gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py:1.1.2.2 
gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py:1.1.2.3
*** 
gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py:1.1.2.2   
    Fri Oct 10 08:18:50 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/DataObject.py       
Tue Nov 18 21:07:08 2003
***************
*** 31,37 ****
  
  __all__ = ['DataObject']
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
--- 31,38 ----
  
  __all__ = ['DataObject']
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import DataObject as BaseDataObject
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
***************
*** 42,48 ****
  
  from ResultSet import *
  
! class DataObject(GDataObjects.DataObject):
  
    _resultSetClass = ResultSet
  
--- 43,49 ----
  
  from ResultSet import *
  
! class DataObject(BaseDataObject):
  
    _resultSetClass = ResultSet
  
***************
*** 93,106 ****
          GDebug.printMesg (5,"Setting Conditions ...");
          filter = self._buildQuery(conditions)
      except self._connection._DatabaseError, err:
!       raise GDataObjects.ConnectionError, err
  
      try:
        listcursor = 
self._dataConnection.request(self.table,filter,sort,fieldlist,\
                                                  self._dataObject._unicodeMode)
      except Exception, msg:
        tmsg = _("Error during creation of object list \n\n --- %s ---)") % msg
!       raise GDataObjects.ConnectionError, tmsg
  
      rs = self._resultSetClass(self, cursor=listcursor, masterRecordSet=None)
      
--- 94,107 ----
          GDebug.printMesg (5,"Setting Conditions ...");
          filter = self._buildQuery(conditions)
      except self._connection._DatabaseError, err:
!       raise Exceptions.ConnectionError, err
  
      try:
        listcursor = 
self._dataConnection.request(self.table,filter,sort,fieldlist,\
                                                  self._dataObject._unicodeMode)
      except Exception, msg:
        tmsg = _("Error during creation of object list \n\n --- %s ---)") % msg
!       raise Exceptions.ConnectionError, tmsg
  
      rs = self._resultSetClass(self, cursor=listcursor, masterRecordSet=None)
      
Index: gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py
diff -c 
gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py:1.1.2.2 
gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py:1.1.2.3
*** 
gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py:1.1.2.2    
    Fri Nov  7 11:14:22 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/RecordSet.py        
Tue Nov 18 21:07:08 2003
***************
*** 29,35 ****
  # HISTORY:
  #
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
--- 29,36 ----
  # HISTORY:
  #
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import RecordSet as BaseRecordSet
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
***************
*** 38,45 ****
  import md5
  import sys
  
! class RecordSet(GDataObjects.RecordSet):
!   def _postChanges(self):
    def _postChanges(self):
      if self._deleteFlag:
        GDebug.printMesg(5, 'AppServer database driver: Instance deleted')
--- 39,45 ----
  import md5
  import sys
  
! class RecordSet(BaseRecordSet):
    def _postChanges(self):
      if self._deleteFlag:
        GDebug.printMesg(5, 'AppServer database driver: Instance deleted')
Index: gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py
diff -c 
gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py:1.1.2.1 
gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py:1.1.2.2
*** 
gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py:1.1.2.1    
    Thu Oct  9 21:21:12 2003
--- gnue-common/src/datasources/drivers/appserver/appserver/ResultSet.py        
Tue Nov 18 21:07:08 2003
***************
*** 29,35 ****
  # HISTORY:
  #
  
! from gnue.common.datasources import GDataObjects, GConditions
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
--- 29,36 ----
  # HISTORY:
  #
  
! from gnue.common.datasources import GConditions, Exceptions
! from gnue.common.datasources.drivers.Base import ResultSet as BaseResultSet
  from gnue.common.apps import GDebug
  from gnue.common.rpc import GComm
  
***************
*** 45,51 ****
  # In the Appserver driver a CURSOR is simply the List handle returned
  # via the query interface
  #
! class ResultSet(GDataObjects.ResultSet):
  
    _recordSetClass = RecordSet
  
--- 46,52 ----
  # In the Appserver driver a CURSOR is simply the List handle returned
  # via the query interface
  #
! class ResultSet(BaseResultSet):
  
    _recordSetClass = RecordSet
  
Index: gnue-common/src/datasources/drivers/db2/db2/Connection.py
diff -c gnue-common/src/datasources/drivers/db2/db2/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/db2/db2/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/db2/db2/Connection.py:1.1.2.1   Thu Oct 
 9 21:21:13 2003
--- gnue-common/src/datasources/drivers/db2/db2/Connection.py   Tue Nov 18 
21:07:08 2003
***************
*** 49,56 ****
  
  class Connection(DBSIG2.DataObject):
    _DatabaseError = "Database Error"
!   _defaultBehavior = Introspection
!   _supportedDataObjects = {
      'object': DBSIG2.DataObject_Object,
      'sql':    DBSIG2.DataObject_SQL
    }
--- 49,56 ----
  
  class Connection(DBSIG2.DataObject):
    _DatabaseError = "Database Error"
!   defaultBehavior = Introspection
!   supportedDataObjects = {
      'object': DBSIG2.DataObject_Object,
      'sql':    DBSIG2.DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/dbf/dbf/Connection.py
diff -c gnue-common/src/datasources/drivers/dbf/dbf/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/dbf/dbf/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/dbf/dbf/Connection.py:1.1.2.1   Thu Oct 
 9 21:21:15 2003
--- gnue-common/src/datasources/drivers/dbf/dbf/Connection.py   Tue Nov 18 
21:07:08 2003
***************
*** 35,41 ****
  
  
  class Connection(GConnection.Connection):
!   _supportedDataObjects = {'object': DataObject,
                             'static': DataObject} # TODO: Why static?!?
    _DatabaseError = Error
  
--- 35,41 ----
  
  
  class Connection(GConnection.Connection):
!   supportedDataObjects = {'object': DataObject,
                             'static': DataObject} # TODO: Why static?!?
    _DatabaseError = Error
  
Index: gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py
diff -c gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py:1.1.2.1     
Thu Oct  9 21:21:15 2003
--- gnue-common/src/datasources/drivers/gadfly/gadfly/Connection.py     Tue Nov 
18 21:07:08 2003
***************
*** 68,74 ****
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = Error
!   _supportedDataObjects = {
     'object': DataObject_Object,
     'sql':    DataObject_SQL
    }
--- 68,74 ----
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = Error
!   supportedDataObjects = {
     'object': DataObject_Object,
     'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/informix/informix/Connection.py
diff -c 
gnue-common/src/datasources/drivers/informix/informix/Connection.py:1.1.2.2 
gnue-common/src/datasources/drivers/informix/informix/Connection.py:1.1.2.3
*** gnue-common/src/datasources/drivers/informix/informix/Connection.py:1.1.2.2 
Sat Nov  8 11:14:56 2003
--- gnue-common/src/datasources/drivers/informix/informix/Connection.py Tue Nov 
18 21:07:08 2003
***************
*** 55,61 ****
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 55,61 ----
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/ingres/ingres/Connection.py
diff -c gnue-common/src/datasources/drivers/ingres/ingres/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/ingres/ingres/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/ingres/ingres/Connection.py:1.1.2.1     
Thu Oct  9 21:21:18 2003
--- gnue-common/src/datasources/drivers/ingres/ingres/Connection.py     Tue Nov 
18 21:07:08 2003
***************
*** 56,62 ****
  
  class Connection(DBSIG2.Connection):
    _DatabaseError = SIG2api.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 56,62 ----
  
  class Connection(DBSIG2.Connection):
    _DatabaseError = SIG2api.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/mysql/mysql/Connection.py
diff -c gnue-common/src/datasources/drivers/mysql/mysql/Connection.py:1.1.2.2 
gnue-common/src/datasources/drivers/mysql/mysql/Connection.py:1.1.2.3
*** gnue-common/src/datasources/drivers/mysql/mysql/Connection.py:1.1.2.2       
Sat Nov  8 11:14:56 2003
--- gnue-common/src/datasources/drivers/mysql/mysql/Connection.py       Tue Nov 
18 21:07:08 2003
***************
*** 53,61 ****
  #
  class Connection(DBSIG2.Connection):
  
!   _defaultBehavior = Introspection
    _DatabaseError = MySQLdb.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 53,61 ----
  #
  class Connection(DBSIG2.Connection):
  
!   defaultBehavior = Introspection
    _DatabaseError = MySQLdb.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/oracle/Base/Connection.py
diff -c gnue-common/src/datasources/drivers/oracle/Base/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/oracle/Base/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/oracle/Base/Connection.py:1.1.2.1       
Thu Oct  9 21:21:23 2003
--- gnue-common/src/datasources/drivers/oracle/Base/Connection.py       Tue Nov 
18 21:07:08 2003
***************
*** 47,53 ****
  #
  class Connection(DBSIG2.Connection):
  
!   _defaultBehavior = Introspection
  
    
    #
--- 47,53 ----
  #
  class Connection(DBSIG2.Connection):
  
!   defaultBehavior = Introspection
  
    
    #
Index: gnue-common/src/datasources/drivers/postgresql/Base/Connection.py
diff -c 
gnue-common/src/datasources/drivers/postgresql/Base/Connection.py:1.1.2.3 
gnue-common/src/datasources/drivers/postgresql/Base/Connection.py:1.1.2.4
*** gnue-common/src/datasources/drivers/postgresql/Base/Connection.py:1.1.2.3   
Sat Nov  8 11:14:57 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/Connection.py   Tue Nov 
18 21:07:08 2003
***************
*** 34,39 ****
--- 34,40 ----
  from string import lower, join, split
  import sys
  from gnue.common.apps import GDebug, GConfig
+ from gnue.common.datasources import Exceptions
  from gnue.common.datasources.drivers import DBSIG2
  from DataObject import *
  from 
gnue.common.datasources.drivers.postgresql.Schema.Discovery.Introspection 
import Introspection
***************
*** 45,52 ****
  #
  class Connection(DBSIG2.Connection):
  
!   _defaultBehavior = Introspection
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 46,53 ----
  #
  class Connection(DBSIG2.Connection):
  
!   defaultBehavior = Introspection
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
***************
*** 54,92 ****
    _pg_connectString = 'host=%s dbname=%s user=%s password=%s port=%s'
    _pg_driver = None
  
-   _pg_encTable={'ascii'     :  'SQL_ASCII',     # ASCII
-                 ''          :  'EUC_JP',        # Japanese EUC
-                 ''          :  'EUC_CN',      # Chinese EUC
-                 ''          :  'EUC_KR',      # Korean EUC
-                 ''          :  'JOHAB',               # Korean EUC (Hangle 
base)
-                 ''          :  'EUC_TW',      # Taiwan EUC
-                 'utf-8'     :  'UNICODE',       # Unicode (UTF-8)
-                 ''          :  'MULE_INTERNAL', # Mule internal code
-                 'iso8859-1' :  'LATIN1',      # ISO 8859-1 ECMA-94 Latin 
Alphabet No.1
-                 'iso8859-2' :  'LATIN2',      # ISO 8859-2 ECMA-94 Latin 
Alphabet No.2
-                 'iso8859-3' :  'LATIN3',      # ISO 8859-3 ECMA-94 Latin 
Alphabet No.3
-                 'iso8859-4' :  'LATIN4',      # ISO 8859-4 ECMA-94 Latin 
Alphabet No.4
-                 'iso8859-9' :  'LATIN5',      # ISO 8859-9 ECMA-128 Latin 
Alphabet No.5
-                 'iso8859-10':  'LATIN6',      # ISO 8859-10 ECMA-144 Latin 
Alphabet No.6
-                 'iso8859-13':  'LATIN7',      # ISO 8859-13 Latin Alphabet 
No.7
-                 'iso8859-14':  'LATIN8',      # ISO 8859-14 Latin Alphabet 
No.8
-                 'iso8859-15':  'LATIN9',      # ISO 8859-15 Latin Alphabet 
No.9
-                 'iso8859-16':  'LATIN10',     # ISO 8859-16 ASRO SR 14111 
Latin Alphabet No.10
-                 'iso8859-5' :  'ISO-8859-5',    # ECMA-113 Latin/Cyrillic
-                 'iso8859-6' :  'ISO-8859-6',    # ECMA-114 Latin/Arabic
-                 'iso8859-7' :  'ISO-8859-7',    # ECMA-118 Latin/Greek
-                 'iso8859-8' :  'ISO-8859-8',    # ECMA-121 Latin/Hebrew
-                 ''          :  'KOI8',          # KOI8-R(U)
-                 ''          :  'WIN',           # Windows CP1251
-                 ''          :  'ALT',           # Windows CP866
-                 ''          :  'WIN1256',       # Arabic Windows CP1256
-                 ''          :  'TCVN',          # Vietnamese TCVN-5712 
(Windows CP1258)
-                 ''          :  'WIN874'}        # Thai Windows CP874
  
!   def connect(self                                                            
                                                                                
                                                                                
              , connectData={}):
  
      print "Postgresql database driver initializing"
!     
      if not hasattr(self,'_DatabaseError'):
        self._DatabaseError = self._pg_driver.DatabaseError
  
--- 55,65 ----
    _pg_connectString = 'host=%s dbname=%s user=%s password=%s port=%s'
    _pg_driver = None
  
  
!   def connect(self, connectData):
  
      print "Postgresql database driver initializing"
! 
      if not hasattr(self,'_DatabaseError'):
        self._DatabaseError = self._pg_driver.DatabaseError
  
***************
*** 111,131 ****
                connectData['_password'],
                port)))
        GDebug.printMesg(1,"Exception %s " % value)
!       raise GDataObjects.LoginError, value
  
      try:
        try:
!         self._encoding = connectData['encoding']
!       except KeyError:
!         pass
! 
!       try:
!         self._pg_encoding = self._pg_encTable[self._encoding]
        except KeyError:
          GDebug.printMesg(1,_("Encoding '%s' is not supported by postgresql 
dbdriver.") % \
                           self._encoding + _('Using default encoding.'))
          self._pg_encoding = ''
!         
        if self._pg_encoding not in ("",'DEFAULT'):
          GDebug.printMesg(1,'Setting postgresql client_encoding to %s (%s)' % 
(self._pg_encoding,
                                                                                
self._encoding))
--- 84,99 ----
                connectData['_password'],
                port)))
        GDebug.printMesg(1,"Exception %s " % value)
!       raise Exceptions.LoginError, _("The PostgreSQL driver returned the 
following error:\n\t%s") % value
  
      try:
        try:
!         self._pg_encoding = pg_encTable[self._encoding]
        except KeyError:
          GDebug.printMesg(1,_("Encoding '%s' is not supported by postgresql 
dbdriver.") % \
                           self._encoding + _('Using default encoding.'))
          self._pg_encoding = ''
! 
        if self._pg_encoding not in ("",'DEFAULT'):
          GDebug.printMesg(1,'Setting postgresql client_encoding to %s (%s)' % 
(self._pg_encoding,
                                                                                
self._encoding))
***************
*** 186,188 ****
--- 154,185 ----
        return rv[0]
      except:
        return None
+ 
+ pg_encTable =  {'ascii'     :  'SQL_ASCII',     # ASCII
+                 ''          :  'EUC_JP',        # Japanese EUC
+                 ''          :  'EUC_CN',      # Chinese EUC
+                 ''          :  'EUC_KR',      # Korean EUC
+                 ''          :  'JOHAB',               # Korean EUC (Hangle 
base)
+                 ''          :  'EUC_TW',      # Taiwan EUC
+                 'utf-8'     :  'UNICODE',       # Unicode (UTF-8)
+                 ''          :  'MULE_INTERNAL', # Mule internal code
+                 'iso8859-1' :  'LATIN1',      # ISO 8859-1 ECMA-94 Latin 
Alphabet No.1
+                 'iso8859-2' :  'LATIN2',      # ISO 8859-2 ECMA-94 Latin 
Alphabet No.2
+                 'iso8859-3' :  'LATIN3',      # ISO 8859-3 ECMA-94 Latin 
Alphabet No.3
+                 'iso8859-4' :  'LATIN4',      # ISO 8859-4 ECMA-94 Latin 
Alphabet No.4
+                 'iso8859-9' :  'LATIN5',      # ISO 8859-9 ECMA-128 Latin 
Alphabet No.5
+                 'iso8859-10':  'LATIN6',      # ISO 8859-10 ECMA-144 Latin 
Alphabet No.6
+                 'iso8859-13':  'LATIN7',      # ISO 8859-13 Latin Alphabet 
No.7
+                 'iso8859-14':  'LATIN8',      # ISO 8859-14 Latin Alphabet 
No.8
+                 'iso8859-15':  'LATIN9',      # ISO 8859-15 Latin Alphabet 
No.9
+                 'iso8859-16':  'LATIN10',     # ISO 8859-16 ASRO SR 14111 
Latin Alphabet No.10
+                 'iso8859-5' :  'ISO-8859-5',    # ECMA-113 Latin/Cyrillic
+                 'iso8859-6' :  'ISO-8859-6',    # ECMA-114 Latin/Arabic
+                 'iso8859-7' :  'ISO-8859-7',    # ECMA-118 Latin/Greek
+                 'iso8859-8' :  'ISO-8859-8',    # ECMA-121 Latin/Hebrew
+                 ''          :  'KOI8',          # KOI8-R(U)
+                 ''          :  'WIN',           # Windows CP1251
+                 ''          :  'ALT',           # Windows CP866
+                 ''          :  'WIN1256',       # Arabic Windows CP1256
+                 ''          :  'TCVN',          # Vietnamese TCVN-5712 
(Windows CP1258)
+                 ''          :  'WIN874'}        # Thai Windows CP874
Index: gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py
diff -c 
gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py:1.1.2.1 
gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py:1.1.2.2
*** gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py:1.1.2.1   
Thu Oct  9 21:21:26 2003
--- gnue-common/src/datasources/drivers/postgresql/Base/DataObject.py   Tue Nov 
18 21:07:08 2003
***************
*** 33,45 ****
  
  from gnue.common.datasources.drivers import DBSIG2
  
! 
! class DataObject_SQL(DBSIG2.DataObject_SQL):
    _escapeSingleQuote = '\\'
    _dateTimeFormat = "'%Y-%m-%d %H:%M:%S'"
  
  
! class DataObject_Object(DBSIG2.DataObject_Object):
!   _escapeSingleQuote = '\\'
!   _dateTimeFormat = "'%Y-%m-%d %H:%M:%S'"
  
--- 33,46 ----
  
  from gnue.common.datasources.drivers import DBSIG2
  
! class _Base:
    _escapeSingleQuote = '\\'
    _dateTimeFormat = "'%Y-%m-%d %H:%M:%S'"
  
+ class DataObject_SQL(_Base, DBSIG2.DataObject_SQL):
+   def __init__(self, *args, **parms):
+     DBSIG2.DataObject_SQL.__init__(self, *args, **parms)
  
! class DataObject_Object(_Base, DBSIG2.DataObject_Object):
!   pass
  
Index: gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py
diff -c 
gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py:1.35.2.2 
gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py:1.35.2.3
*** gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py:1.35.2.2   
Sat Nov  8 11:14:58 2003
--- gnue-common/src/datasources/drivers/postgresql/pypgsql/Driver.py    Tue Nov 
18 21:07:08 2003
***************
*** 38,43 ****
--- 38,44 ----
  try:
    from pyPgSQL import PgSQL # pyPgSQL 2.0 support
  except ImportError:
+   # TODO: Re-evaluate the minimum version we support!
    import PgSQL              # pyPgSQL 1.6 support
  
  
***************
*** 89,95 ****
    _pg_driver = PgSQL
    _pg_connectString = '%s::%s:%s:%s::%s'
  
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 90,96 ----
    _pg_driver = PgSQL
    _pg_connectString = '%s::%s:%s:%s::%s'
  
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py
diff -c gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py:1.1.2.1       
Thu Oct  9 21:21:30 2003
--- gnue-common/src/datasources/drivers/sapdb/sapdb/Connection.py       Tue Nov 
18 21:07:09 2003
***************
*** 80,87 ****
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   _defaultBehavior = Introspection
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 80,87 ----
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   defaultBehavior = Introspection
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py
diff -c gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py:1.1.2.1     
Thu Oct  9 21:21:33 2003
--- gnue-common/src/datasources/drivers/sqlite/sqlite/Connection.py     Tue Nov 
18 21:07:09 2003
***************
*** 56,63 ****
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   _defaultBehavior = Introspection
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 56,63 ----
  class Connection(DBSIG2.Connection):
  
    _DatabaseError = SIG2api.DatabaseError
!   defaultBehavior = Introspection
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py
diff -c 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py:1.1.2.1 
Thu Oct  9 21:21:34 2003
--- gnue-common/src/datasources/drivers/sqlrelay/sqlrelay/Connection.py Tue Nov 
18 21:07:09 2003
***************
*** 61,69 ****
  #
  class Connection(DBSIG2.Connection):
  
!   _defaultBehavior = Introspection
    _DatabaseError = SIG2api.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 61,69 ----
  #
  class Connection(DBSIG2.Connection):
  
!   defaultBehavior = Introspection
    _DatabaseError = SIG2api.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
Index: gnue-common/src/datasources/drivers/sybase/sybase/Connection.py
diff -c gnue-common/src/datasources/drivers/sybase/sybase/Connection.py:1.1.2.1 
gnue-common/src/datasources/drivers/sybase/sybase/Connection.py:1.1.2.2
*** gnue-common/src/datasources/drivers/sybase/sybase/Connection.py:1.1.2.1     
Thu Oct  9 21:21:35 2003
--- gnue-common/src/datasources/drivers/sybase/sybase/Connection.py     Tue Nov 
18 21:07:09 2003
***************
*** 54,60 ****
  
  class Connection(DBSIG2.Connection)
    _DatabaseError = SIG2api.DatabaseError
!   _supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }
--- 54,60 ----
  
  class Connection(DBSIG2.Connection)
    _DatabaseError = SIG2api.DatabaseError
!   supportedDataObjects = {
      'object': DataObject_Object,
      'sql':    DataObject_SQL
    }




reply via email to

[Prev in Thread] Current Thread [Next in Thread]